我在网站上找到了这个公式及其描述
l(x,y)=(l(x,y)-min)(no of intensity levels/(max-min)) + initial intensity level
其中,I(x,y)表示图像,左侧表示输出图像,而右侧表示输入图像中第y列的第x个像素。在该等式中,“min”和“max”是当前图像中的最小强度值和最小强度值。这里“强度等级的数量”表示可以分配给像素的强度值的总数。例如,通常在灰度图像中,最低可能强度为0,最高强度值为255.因此“强度等级数”等于255.
我已将其转换为代码,我是否正确转换了它?
for(int y = 0; y < bmp.bmHeight; y++)
{
for(int x = 0; x < bmp.bmWidth; x++)
{
COLORREF rgb = dc.GetPixel(x, y);
BYTE r = GetRValue(rgb);
BYTE g = GetGValue(rgb);
BYTE b = GetBValue(rgb);
BYTE p,p1;
if(r<g)
{
p=r;
p1=g;
}
else
{
p=g;
p1=r;
}
if(b<p)
p=b;
if(b>p1)
p1=b;
BYTE bw = (RGB(r, g, b)-p);
bw=bw*(255/(p1-p));
bw+=p1;
dc.SetPixel(x, y, RGB(bw, bw, bw));
}
答案 0 :(得分:3)
这是我尝试对公式进行编码。基于Fisher et al的公式。请注意,除非您使用Fisher的文章中描述的截止分数,否则您仍将遇到人工外观图像,但这是您自己的作业; - )
我没有用真实图像测试这个,调试它也是你的功课。
参考: 有关强度的计算,请参阅HSL and HSV on wikipedia。
typedef unsigned char byte;
const byte OUT_MIN = 0; // The desired min output luminosity 0 to stretch to entire spectrum
const byte OUT_MAX = 255; // The desired max output luminosity 255 to stretch to entire spectrum
byte min = 255, max = 0;
// get the minimum and maximum values.
for( int y = 0; y < bmp.bmHeight; y++ )
{
for( int x = 0; x < bmp.bmWidth; x++ )
{
COLORREF rgb = dc.GetPixel(x, y);
byte intensity = ( rValue(rgb) + gValue(rgb) + bValue(rgb) ) / 3;
min = min < intensity ? min : intensity;
max = max > intensity ? max : intensity;
}
}
// set the new pixel values
for(int y = 0; y < bmp.bmHeight; y++)
{
for(int x = 0; x < bmp.bmWidth; x++)
{
COLORREF rgb = dc.GetPixel(x, y);
// Creates color image
// Calculate new color using the formula. Has to be int, not byte, because you might go out of range.
// We correct the range manually on the next two lines.
int r = ( rValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
r = r < 0 ? 0 : r;
r = r > 255 ? 255 : r;
int g = ( gValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
g = g < 0 ? 0 : g;
g = g > 255 ? 255 : g;
int b = ( bValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
b = b < 0 ? 0 : b;
b = b > 255 ? 255 : b;
dc.SetPixel( x, y, RGB( r, g, b ) );
}
}
答案 1 :(得分:1)
在使用主对比度拉伸算法的循环之前,您需要一个单独的循环来在整个图像的基础上计算p
和p1
(顺便说一下可怕的变量名称)。
此外,在您给出的示例中,有256个强度等级,而不是255. 0也是强度等级。
最后,您可能应该在运行算法之前将图像转换为HSV,并且仅在V值上运行它,或者为R,G和B单独运行它。按照您的方式选择最小和最大强度不是可能会为彩色图片产生有用的结果。
答案 2 :(得分:0)
你需要在图像中进行两次传递。第一遍:找到图片的max
和min
级别。第二遍:使用max
和min
值进行对比度拉伸。
答案 3 :(得分:0)
我编辑了@nus的代码。实际上我不知道我的代码是否正确或@nus的代码,但我的代码有更好的结果。
typedef unsigned char byte;
const byte OUT_MIN = 0;
const byte OUT_MAX = 255;
byte min = 255, max = 0;
for( int y = 0; y < bmp.bmHeight; y++ )
{
for( int x = 0; x < bmp.bmWidth; x++ )
{
COLORREF rgb = dc.GetPixel(x, y);
byte r = rValue(rgb);
byte g = gValue(rgb);
byte b = bValue(rgb);
if (min > r) min = r;
if (min > g) min = g;
if (min > b) min = b;
if (max < r) max = r;
if (max < g) max = g;
if (max < b) max = b;
}
}
for(int y = 0; y < bmp.bmHeight; y++)
{
for(int x = 0; x < bmp.bmWidth; x++)
{
COLORREF rgb = dc.GetPixel(x, y);
int r = ( rValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
r = r < 0 ? 0 : r;
r = r > 255 ? 255 : r;
int g = ( gValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
g = g < 0 ? 0 : g;
g = g > 255 ? 255 : g;
int b = ( bValue( rgb ) - min ) * ( OUT_MAX / (max - min) ) + OUT_MIN;
b = b < 0 ? 0 : b;
b = b > 255 ? 255 : b;
dc.SetPixel( x, y, RGB( r, g, b ) );
}
}