这里检讨一下,自己虽然是个搞C/C++的,为了偷懒,先用Matlab解决问题……
这里是Matlab的Bayer抖动的算法,用于将256级别的灰度图像抖动成同样尺寸的黑白图片。
clear;
clc;
m1 = [[0 2];[3 1]];
u1=ones(2, 2);
m2=[[4*m1 4*m1+2*u1];[4*m1+3*u1 4*m1+u1]]
u2=ones(4, 4);
m3=[[4*m2 4*m2+2*u2];[4*m2+3*u2 4*m2+u2]]
I = imread('test.bmp');
gI = .2989*I(:,:,1)...
+.5870*I(:,:,2)...
+.1140*I(:,:,3);
%imshow(gI);
%r = I(:,:,1);
%g = I(:,:,2);
%b = I(:,:,3);
[h w] = size(gI);
bw = 0;
for i=1:h
for j=1:w
if (gI(i,j) / 4> m3(bitand(i, 7) + 1, bitand(j,7) + 1))
bw(i,j)= 255;
else
bw(i,j)= 0;
end
end
end
imshow(bw);
算法具体思想见《抖动算法小议1》。
这里再说说如何将24bit的真彩色图片变为15bit 或者16bit的图片。还是使用Floyd-steinberg算法。先说说15Bit的组成,红色5bit,绿色5bit,蓝色5bit,1位预留。16Bit的颜色,红、绿、蓝分别是5Bit, 6Bit, 5Bit。这是因为人眼对灰度的感觉比色彩要强,绿色对灰度的贡献最多,所以,多1个bit的绿色量化会使得灰度层次表示更加丰富。
clear;
clc;
I = imread('0001.jpg');
img = double(I);%转换图片
[h w] = size(img(:,:,1));%取得图片的大小
d = 1;%为1时,误差从左传递到右侧,为-1时,误差从右传递到左
re = 0;
ge = 0;
be = 0;
rs = 8;%2^n, n = 3 表示将红色量化等级减少到2^5 = 32种。
gs = 8;%2^n, n = 3 表示将绿色量化等级减少到2^5 = 32种。
bs = 8;%2^n, n = 3 表示将蓝色量化等级减少到2^5 = 32种。
for i=1:h
for j=1:w
if (d == 1)
val = rs * fix(img(i,j,1) / rs);
re = img(i, j, 1) - val;
img(i, j, 1) = val;
val = gs * fix(img(i,j,2) / gs);
ge = img(i, j, 2) - val;
img(i, j, 2) = val;
val = bs * fix(img(i,j,3) / bs);
be = img(i, j, 3) - val;
img(i, j, 3) = val;
if ((j + 1) <= w)%计算误差对右侧的像素的传递
img(i, j + 1, 1) = img(i, j + 1, 1) + re * 3 / 8;
img(i, j + 1, 2) = img(i, j + 1, 2) + ge * 3 / 8;
img(i, j + 1, 3) = img(i, j + 1, 3) + be * 3 / 8;
end
if ((i + 1) <= h)%计算误差对下侧的像素传递
img(i + 1, j, 1) = img(i + 1, j, 1) + re * 3 / 8;
img(i + 1, j, 2) = img(i + 1, j, 2) + ge * 3 / 8;
img(i + 1, j, 3) = img(i + 1, j, 3) + be * 3 / 8;
end
if ((i + 1) <= h && (j + 1) <= w)%计算误差对右下侧的像素传递
img(i + 1, j + 1, 1) = img(i + 1, j + 1, 1) + re / 4;
img(i + 1, j + 1, 2) = img(i + 1, j + 1, 2) + ge / 4;
img(i + 1, j + 1, 3) = img(i + 1, j + 1, 3) + be / 4;
end
else
val = rs * fix(img(i,w - j + 1,1) / rs);
re = img(i, w - j + 1, 1) - val;
img(i, w - j + 1, 1) = val;
val = gs * fix(img(i,w - j + 1,2) / gs);
ge = img(i, w - j + 1, 2) - val;
img(i, w - j + 1, 2) = val;
val = bs * fix(img(i,w - j + 1,3) / bs);
be = img(i, w - j + 1, 3) - val;
img(i, w - j + 1, 3) = val;
if ((w - j) > 0)%计算误差对左侧的误差传递
img(i, w - j, 1) = img(i, w - j, 1) + re * 3 / 8;
img(i, w - j, 2) = img(i, w - j, 2) + ge * 3 / 8;
img(i, w - j, 3) = img(i, w - j, 3) + be * 3 / 8;
end
if (i + 1 <= h)%计算误差对下侧的像素误差传递
img(i + 1, j, 1) = img(i + 1, j, 1) + re * 3 / 8;
img(i + 1, j, 2) = img(i + 1, j, 2) + ge * 3 / 8;
img(i + 1, j, 3) = img(i + 1, j, 3) + be * 3 / 8;
end
if ((i + 1) <= h && (w - j) > 0)%计算误差对左下侧的像素误差传递
img(i + 1, w - j, 1) = img(i + 1, w - j, 1) + re / 4;
img(i + 1, w - j, 2) = img(i + 1, w - j, 2) + ge / 4;
img(i + 1, w - j, 3) = img(i + 1, w - j, 3) + be / 4;
end
end
end
d = -d;
end
out = uint8(img);
imshow(out)
这个是处理的原图片:
这个是处理后的图片: