###### 关注微信公众号【OpenCV学堂】

-应知空谷幽人意，只在春风淡荡中...

###### 图像处理之特殊灰度算法技巧

Gray = 0.299 * red + 0.587 * green + 0.114 * blue;

1.       基于像素平均值的图像阈值二值化算法：

a.      首先将彩色图像转换为灰度图像

b.      计算灰度图像的算术平均值– M

c.      以M为阈值，完成对灰度图二值化( 大于阈值M,像素点赋值为白色，否则赋值为黑

public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();

if ( dest == null )
dest = createCompatibleDestImage( src, null );
src = super.filter(src, dest);

int[] inPixels = new int[width*height];
int[] outPixels = new int[width*height];
getRGB(src, 0, 0, width, height, inPixels );

// calculate means of pixel
int index = 0;
double redSum = 0, greenSum = 0, blueSum = 0;
double total = height * width;
for(int row=0; row<height; row++) {
int ta = 0, tr = 0, tg = 0, tb = 0;
for(int col=0; col<width; col++) {
index = row * width + col;
ta = (inPixels[index] >> 24) & 0xff;
tr = (inPixels[index] >> 16) & 0xff;
tg = (inPixels[index] >> 8) & 0xff;
tb = inPixels[index] & 0xff;
redSum += tr;
greenSum += tg;
blueSum +=tb;
}
}
int means = (int)(redSum / total);
System.out.println(" threshold average value = " + means);

// dithering
for(int row=0; row<height; row++) {
int ta = 0, tr = 0, tg = 0, tb = 0;
for(int col=0; col<width; col++) {
index = row * width + col;
ta = (inPixels[index] >> 24) & 0xff;
tr = (inPixels[index] >> 16) & 0xff;
tg = (inPixels[index] >> 8) & 0xff;
tb = inPixels[index] & 0xff;
if(tr >=means) {
tr = tg = tb = 255;
} else {
tr = tg = tb = 0;
}
outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;

}
}
setRGB( dest, 0, 0, width, height, outPixels );
return dest;
}

2.       基于错误扩散的Floyd-Steinberg抖动算法

http://en.wikipedia.org/wiki/Floyd–Steinberg_dithering

@Override
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();

if ( dest == null )
dest = createCompatibleDestImage( src, null );
src = super.filter(src, dest);

int[] inPixels = new int[width*height];
int[] outPixels = new int[width*height];
getRGB( src, 0, 0, width, height, inPixels );
int index = 0;
for(int row=0; row<height; row++) {
for(int col=0; col<width; col++) {
index = row * width + col;
int r1 = (inPixels[index] >> 16) & 0xff;
int g1 = (inPixels[index] >> 8) & 0xff;
int b1 = inPixels[index] & 0xff;
int cIndex = getCloseColor(r1, g1, b1);
outPixels[index] = (255 << 24) | (COLOR_PALETTE[cIndex][0] << 16) | (COLOR_PALETTE[cIndex][1] << 8) | COLOR_PALETTE[cIndex][2];
int er = r1 - COLOR_PALETTE[cIndex][0];
int eg = g1 - COLOR_PALETTE[cIndex][1];
int eb = b1 -  COLOR_PALETTE[cIndex][2];
int k = 0;

if(row + 1 < height && col - 1 > 0) {
k = (row + 1) * width + col - 1;
r1 = (inPixels[k] >> 16) & 0xff;
g1 = (inPixels[k] >> 8) & 0xff;
b1 = inPixels[k] & 0xff;
r1 += (int)(er * kernelData[0]);
g1 += (int)(eg * kernelData[0]);
b1 += (int)(eb * kernelData[0]);
inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);
}

if(col + 1 < width) {
k = row * width + col + 1;
r1 = (inPixels[k] >> 16) & 0xff;
g1 = (inPixels[k] >> 8) & 0xff;
b1 = inPixels[k] & 0xff;
r1 += (int)(er * kernelData[3]);
g1 += (int)(eg * kernelData[3]);
b1 += (int)(eb * kernelData[3]);
inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);
}

if(row + 1 < height) {
k = (row + 1) * width + col;
r1 = (inPixels[k] >> 16) & 0xff;
g1 = (inPixels[k] >> 8) & 0xff;
b1 = inPixels[k] & 0xff;
r1 += (int)(er * kernelData[1]);
g1 += (int)(eg * kernelData[1]);
b1 += (int)(eb * kernelData[1]);
inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);
}

if(row + 1 < height && col + 1 < width) {
k = (row + 1) * width + col + 1;
r1 = (inPixels[k] >> 16) & 0xff;
g1 = (inPixels[k] >> 8) & 0xff;
b1 = inPixels[k] & 0xff;
r1 += (int)(er * kernelData[2]);
g1 += (int)(eg * kernelData[2]);
b1 += (int)(eb * kernelData[2]);
inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);
}
}
}
setRGB( dest, 0, 0, width, height, outPixels );
return dest;
}
3.       选择性灰度算法

关键代码：

public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();

if ( dest == null )
dest = createCompatibleDestImage( src, null );

int[] inPixels = new int[width*height];
int[] outPixels = new int[width*height];
getRGB( src, 0, 0, width, height, inPixels );
int index = 0;
for(int row=0; row<height; row++) {
int ta = 0, tr = 0, tg = 0, tb = 0;
for(int col=0; col<width; col++) {
index = row * width + col;
ta = (inPixels[index] >> 24) & 0xff;
tr = (inPixels[index] >> 16) & 0xff;
tg = (inPixels[index] >> 8) & 0xff;
tb = inPixels[index] & 0xff;
int gray = (int)(0.299 * (double)tr + 0.587 * (double)tg + 0.114 * (double)tb);
double distance = getDistance(tr, tg, tb);
if(distance < threshold) {
double k = distance / threshold;
int[] rgb = getAdjustableRGB(tr, tg, tb, gray, (float)k);
tr = rgb[0];
tg = rgb[1];
tb = rgb[2];
outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
} else {
outPixels[index] = (ta << 24) | (gray << 16) | (gray << 8) | gray;
}

}
}
setRGB( dest, 0, 0, width, height, outPixels );
return dest;
}

public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
if ( dstCM == null )
dstCM = src.getColorModel();
return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);
}

#### 图像的灰度化原理和实现

2006-07-06 23:31:00

#### 图像的二值化和灰度化

2011-08-12 14:56:47

#### 数字图像处理之灰度化

2013-11-24 17:09:55

#### 图像灰度化总结

2016-05-25 09:10:47

#### 图像的灰度化处理的基本原理

2015-12-15 17:25:50

#### 实例说明图像的灰度化和二值化的区别

2016-10-12 15:17:47

#### 图像处理灰度化和二值化

2017-03-10 20:03:21

#### 图像灰度化的三种方法及matlab,c++,python实现

2015-09-23 16:24:49

#### 高斯函数

2016-11-04 11:34:26

#### OpenCV简单的图像灰度化

2017-04-15 18:33:47