\quad\quad 关于为什么要做去马赛克参加博文Understanding ISP Pipeline - Demosaicking。简单来说就是当前使用较多的CCD和CMOS sensor用的是Bayer CFA格式,或者Bayer mosaic格式,支持这种格式的成像器件(包括CCD和CMOS两种)输出的数据格式俗称RAW格式,特点是每个像素只提供RGB三种颜色中的一种,另外两种颜色需要后续处理环节中通过一定的软件算法进行插值补全。
参考博文ISP算法简述与逻辑实现-demosaic和ISP图像处理之Demosaic算法及相关
双线性插值是比较简单的算法,简而言之就是用周围相同颜色的像素值的平均来填补当前像素确实的颜色。
G通道上RB插值,以G23为例,
R通道上GB插值,以R33为例,
B通道上的RG插值,以B24为例
function imDst = Demosaic_bilinear(bayer,pattern)
[H,W] = size(bayer);
imDst = zeros(H,W,3);
g1 = [0 1/4 0; 1/4 0 1/4; 0 1/4 0];
g2 = [1/4 0 1/4; 0 0 0; 1/4 0 1/4];
h = [0.5 0 0.5];
tmp1 = conv2(bayer,g1,'same');
tmp2 = conv2(bayer,g2,'same');
tmp3 = conv2(bayer,h,'same');
tmp4 = conv2(bayer,h','same');
switch pattern
case 'grbg'
G(1:2:H,1:2:W) = bayer(1:2:H,1:2:W);
G(2:2:H,2:2:W) = bayer(2:2:H,2:2:W);
G(1:2:H,2:2:W) = tmp1(1:2:H,2:2:W);
G(2:2:H,1:2:W) = tmp1(2:2:H,1:2:W);
R(1:2:H,2:2:W) = bayer(1:2:H,2:2:W);
R(1:2:H,1:2:W) = tmp3(1:2:H,1:2:W);
R(2:2:H,2:2:W) = tmp4(2:2:H,2:2:W);
R(2:2:H,1:2:W) = tmp2(2:2:H,1:2:W);
B(2:2:H,1:2:W) = bayer(2:2:H,1:2:W);
B(1:2:H,1:2:W) = tmp4(1:2:H,1:2:W);
B(2:2:H,2:2:W) = tmp3(2:2:H,2:2:W);
B(1:2:H,2:2:W) = tmp2(1:2:H,2:2:W);
case 'gbrg'
G(1:2:H,1:2:W) = bayer(1:2:H,1:2:W);
G(2:2:H,2:2:W) = bayer(2:2:H,2:2:W);
G(1:2:H,2:2:W) = tmp1(1:2:H,2:2:W);
G(2:2:H,1:2:W) = tmp1(2:2:H,1:2:W);
R(2:2:H,1:2:W) = bayer(2:2:H,1:2:W);
R(1:2:H,1:2:W) = tmp4(1:2:H,1:2:W);
R(2:2:H,2:2:W) = tmp3(2:2:H,2:2:W);
R(1:2:H,2:2:W) = tmp2(1:2:H,2:2:W);
B(1:2:H,2:2:W) = bayer(1:2:H,2:2:W);
B(1:2:H,1:2:W) = tmp3(1:2:H,1:2:W);
B(2:2:H,2:2:W) = tmp4(2:2:H,2:2:W);
B(2:2:H,1:2:W) = tmp2(2:2:H,1:2:W);
case 'rggb'
G(1:2:H,2:2:W) = bayer(1:2:H,2:2:W);
G(2:2:H,1:2:W) = bayer(2:2:H,1:2:W);
G(1:2:H,1:2:W) = tmp1(1:2:H,1:2:W);
G(2:2:H,2:2:W) = tmp1(2:2:H,2:2:W);
R(1:2:H,1:2:W) = bayer(1:2:H,1:2:W);
R(1:2:H,2:2:W) = tmp3(1:2:H,2:2:W);
R(2:2:H,1:2:W) = tmp4(2:2:H,1:2:W);
R(2:2:H,2:2:W) = tmp2(2:2:H,2:2:W);
B(2:2:H,2:2:W) = bayer(2:2:H,2:2:W);
B(1:2:H,2:2:W) = tmp4(1:2:H,2:2:W);
B(2:2:H,1:2:W) = tmp3(2:2:H,1:2:W);
B(1:2:H,1:2:W) = tmp2(1:2:H,1:2:W);
case 'bggr'
G(1:2:H,2:2:W) = bayer(1:2:H,2:2:W);
G(2:2:H,1:2:W) = bayer(2:2:H,1:2:W);
G(1:2:H,1:2:W) = tmp1(1:2:H,1:2:W);
G(2:2:H,2:2:W) = tmp1(2:2:H,2:2:W);
R(2:2:H,2:2:W) = bayer(2:2:H,2:2:W);
R(1:2:H,2:2:W) = tmp4(1:2:H,2:2:W);
R(2:2:H,1:2:W) = tmp3(2:2:H,1:2:W);
R(1:2:H,1:2:W) = tmp2(1:2:H,1:2:W);
B(1:2:H,1:2:W) = bayer(1:2:H,1:2:W);
B(1:2:H,2:2:W) = tmp3(1:2:H,2:2:W);
B(2:2:H,1:2:W) = tmp4(2:2:H,1:2:W);
B(2:2:H,2:2:W) = tmp2(2:2:H,2:2:W);
end
imDst = cat(3,R,G,B);
色差恒定准则与色比恒定准则都是基于颜色通道之间的相关性,目的都是把颜色通道之间的相关性信息引入颜色插值算法,提高插值的准确性。具体算法参考博文ISP算法简述与逻辑实现-demosaic,算法流程如下:
function imDst = Demosaic_color_diff(raw_img,pattern)
[hei,wid] = size(raw_img);
imDst = zeros(hei,wid,3);
Kr = zeros(hei,wid);
Kb = zeros(hei,wid);
bayerPadding = zeros(hei+2,wid+2);
bayerPadding(2:hei+1,2:wid+1) = raw_img;
bayerPadding(1,:) = bayerPadding(3,:);
bayerPadding(hei+2,:) = bayerPadding(hei,:);
bayerPadding(:,1) = bayerPadding(:,3);
bayerPadding(:,wid+2) = bayerPadding(:,wid);
if pattern == 'grbg'
% g
imDst(1:2:hei,1:2:wid,2) = bayerPadding(2:2:hei+1,2:2:wid+1);
imDst(2:2:hei,2:2:wid,2) = bayerPadding(3:2:hei+1,3:2:wid+1);
imDst(1:2:hei,2:2:wid,2) = (bayerPadding(1:2:hei,3:2:wid+2)+bayerPadding(3:2:hei+2,3:2:wid+2)+...
bayerPadding(2:2:hei+1,2:2:wid+1)+bayerPadding(2:2:hei+1,4:2:wid+2))/4;
imDst(2:2:hei,1:2:wid,2) = (bayerPadding(2:2:hei+1,2:2:wid+1)+bayerPadding(4:2:hei+2,2:2:wid+1)+...
bayerPadding(3:2:hei+2,1:2:wid)+bayerPadding(3:2:hei+2,3:2:wid+2))/4;
% Kr Kb
Kr(1:2:hei,2:2:wid) = imDst(1:2:hei,2:2:wid,2) - bayerPadding(2:2:hei+1,3:2:wid+1);
Kb(2:2:hei,1:2:wid) = imDst(2:2:hei,1:2:wid,2) - bayerPadding(3:2:hei+2,2:2:wid+1);
Kr = Demosaic_bilinear(Kr,pattern);
Kr = Kr(:,:,1);
Kb = Demosaic_bilinear(Kb,pattern);
Kb = Kb(:,:,3);
imDst(:,:,1) = imDst(:,:,2) - Kr;
imDst(:,:,3) = imDst(:,:,2) - Kb;
elseif pattern == 'gbrg'
% g
imDst(1:2:hei,1:2:wid,2) = bayerPadding(2:2:hei+1,2:2:wid+1);
imDst(2:2:hei,2:2:wid,2) = bayerPadding(3:2:hei+1,3:2:wid+1);
imDst(1:2:hei,2:2:wid,2) = (bayerPadding(1:2:hei,3:2:wid+2)+bayerPadding(3:2:hei+2,3:2:wid+2)+...
bayerPadding(2:2:hei+1,2:2:wid+1)+bayerPadding(2:2:hei+1,4:2:wid+2))/4;
imDst(2:2:hei,1:2:wid,2) = (bayerPadding(2:2:hei+1,2:2:wid+1)+bayerPadding(4:2:hei+2,2:2:wid+1)+...
bayerPadding(3:2:hei+2,1:2:wid)+bayerPadding(3:2:hei+2,3:2:wid+2))/4;
% Kr Kb
Kb(1:2:hei,2:2:wid) = imDst(1:2:hei,2:2:wid,2) - bayerPadding(2:2:hei+1,3:2:wid+1);
Kr(2:2:hei,1:2:wid) = imDst(2:2:hei,1:2:wid,2) - bayerPadding(3:2:hei+2,2:2:wid+1);
Kr = Demosaic_bilinear(Kr,pattern);
Kr = Kr(:,:,1);
Kb = Demosaic_bilinear(Kb,pattern);
Kb = Kb(:,:,3);
imDst(:,:,1) = imDst(:,:,2) - Kr;
imDst(:,:,3) = imDst(:,:,2) - Kb;
elseif pattern == 'rggb'
% g
imDst(1:2:hei,2:2:wid,2) = bayerPadding(2:2:hei+1,3:2:wid+2);
imDst(2:2:hei,1:2:wid,2) = bayerPadding(3:2:hei+2,2:2:wid+1);
imDst(1:2:hei,1:2:wid,2) = (bayerPadding(1:2:hei,2:2:wid+1)+bayerPadding(3:2:hei+2,2:2:wid+1)+...
bayerPadding(2:2:hei+1,1:2:wid)+bayerPadding(2:2:hei+1,3:2:wid+2))/4;
imDst(2:2:hei,2:2:wid,2) = (bayerPadding(2:2:hei+1,3:2:wid+2)+bayerPadding(4:2:hei+2,3:2:wid+2)+...
bayerPadding(3:2:hei+2,2:2:wid+1)+bayerPadding(3:2:hei+2,4:2:wid+2))/4;
% Kr Kb
Kr(1:2:hei,1:2:wid) = imDst(1:2:hei,1:2:wid,2) - bayerPadding(2:2:hei+1,2:2:wid+1);
Kb(2:2:hei,2:2:wid) = imDst(2:2:hei,2:2:wid,2) - bayerPadding(3:2:hei+2,3:2:wid+2);
Kr = Demosaic_bilinear(Kr,pattern);
Kr = Kr(:,:,1);
Kb = Demosaic_bilinear(Kb,pattern);
Kb = Kb(:,:,3);
imDst(:,:,1) = imDst(:,:,2) - Kr;
imDst(:,:,3) = imDst(:,:,2) - Kb;
elseif pattern == 'bggr'
% g
imDst(1:2:hei,2:2:wid,2) = bayerPadding(2:2:hei+1,3:2:wid+2);
imDst(2:2:hei,1:2:wid,2) = bayerPadding(3:2:hei+2,2:2:wid+1);
imDst(1:2:hei,1:2:wid,2) = (bayerPadding(1:2:hei,2:2:wid+1)+bayerPadding(3:2:hei+2,2:2:wid+1)+...
bayerPadding(2:2:hei+1,1:2:wid)+bayerPadding(2:2:hei+1,3:2:wid+2))/4;
imDst(2:2:hei,2:2:wid,2) = (bayerPadding(2:2:hei+1,3:2:wid+2)+bayerPadding(4:2:hei+2,3:2:wid+2)+...
bayerPadding(3:2:hei+2,2:2:wid+1)+bayerPadding(3:2:hei+2,4:2:wid+2))/4;
% Kr Kb
Kb(1:2:hei,1:2:wid) = imDst(1:2:hei,1:2:wid,2) - bayerPadding(2:2:hei+1,2:2:wid+1);
Kr(2:2:hei,2:2:wid) = imDst(2:2:hei,2:2:wid,2) - bayerPadding(3:2:hei+2,3:2:wid+2);
Kr = Demosaic_bilinear(Kr,pattern);
Kr = Kr(:,:,1);
Kb = Demosaic_bilinear(Kb,pattern);
Kb = Kb(:,:,3);
imDst(:,:,1) = imDst(:,:,2) - Kr;
imDst(:,:,3) = imDst(:,:,2) - Kb;
end