ISP图像处理之Demosaic算法(reference model篇)

写作意图:

写接下来几篇的原因是,谈谈自己对UVM框架的理解,以及用UVM实现对ISP的验证。之前在github上找了很多UVM相关的代码,并没有找到与图像处理相关的UVM框架。

因此,我就自己动手搭建一个UVM框架,来处理ISP中的demosaic模块,而其他模块的RTL代码也很难找的到,或者很难找到自己想要的那种,只能自己在动手写一个简单的RTL代码了。

Demosaic的目的是:将raw图像(单张)通过插值算法转化为R, G, B三通道的三张图像,RGB三通道合成为彩色图像。

一、CMOS成像原理

黑白CMOS传感器:没有色彩还原度指标,只有灰度值没有色彩。
彩色CMOS传感器通过在光电二极管前面配置三色滤光片(color filter array, CFA ),让对应的颜色光透过,然后进行光电转换。三色滤光片其以1:2:1的构成由四个像点构成一个彩色像素,即R, B滤光片分别覆盖一个像点,剩下的两个像点都覆盖G滤光片,采取这种比例的原因是人眼对绿色较为敏感。图1给出了CMOS图像传感器的部分结构。

7a101c383f6e40e79686081282216c08.png

 图1:CMOS 传感器的内部结构。黄色:微透镜,紫色:感光片(光电二极管),每个感光片上都会对应周期排布的R, Gr, Gb, B四种颜色的滤波片。

因此,看起来像mosaic的raw图像是彩色CMOS传感器得到如图2所示的玩意。

52fafb1b8bff4c7886905238b9df1365.png

图2:mosaic图像

Demosaic的原理是从类似于图2的mosaic中,分离出R, G, B三通道(如图3所示),其采用的方法如插值算法。

e0299fcd987e4237b04938efe1189f65.png

图3 RGB分离

二、插值算法理论:

[1]: 周围3x3区域,四个角存在相同颜色点的:那中心点的值为四个点的均值

[2]: 周围3x3区域,只有水平方向存在上下两个相同颜色点::那中心点的值为左右2个点的均值

[3]: 周围3x3区域,只有垂直方向存在上下两个相同颜色点::那中心点的值为上下2个点的均值

600e0a2b73024e61b7eb87fcd65f9e27.png

算法总结为:

第0行的 R  :  偶数列 用的是 其本身               、奇数列 水平方向2合一
第0行的 Gr:  偶数列 用的是 水平方向2合一  、 奇数列 其本身
第0行的 Gb: 偶数列 用的是 上下方向2合一  、奇数列  4合一
第0行的 B  :  偶数列 用的是 4合一               、奇数列  上下方向2合一

第1行的 R  : 用的是 上下方向2合一 (偶数列) 、4合一
第1行的 Gr : 用的是 4合一 (偶数列)                、上下方向2合一(奇数列)
第1行的 Gb: 用的是 其本身(偶数列)               、水平方向2合一(奇数列)
第1行的 B  : 用的是 水平方向2合一(奇数列)  、其本身(偶数列)

Gr, Gb 两者均值合成G。

其他行,都是周期性重复。但是,对于上、下、左、右四个边界,需要做特殊处理,如镜像处理,才能构造出3x3区域。

三、reference model实现(matlab)

代码实现上述算法,其作为reference model,与后续的RTL结果进行一致性确认。参考如下:

clear all; clc; close all


height  = 512;
width   = 768;

ori_p   = "./raw_512x768_rggb.bin";
ori     = binview(ori_p , height, width);
%ori0    = uint8(ori');


%%  reference modele 上下左右四条边界 做镜像处理
up1      = ori(2       , :);
down1    = ori(height-1, :);
new1     = [up1 ; ori; down1];
new2     = new1';
up2      = new2(2  , :);
down2    = new2(width-1, :);
new3     = [up2 ; new2; down2];

ori_pad  = new3';
clear up1 down1 up2 down2 new1 new2 new3

% 运算 4个通道的图像初始化

rec_R    = zeros(height, width); % 默认为左上点
rec_Gr   = zeros(height, width); % 默认为右上点
rec_Gb   = zeros(height, width); % 默认为左下点
rec_B    = zeros(height, width); % 默认为右下点

for i = 1 : height
    for j = 1 : width 
        if     ( (mod(i, 2) == 1) && (mod(j, 2) == 1) ) % 左上角
            rec_R (i, j)  = fix( ori_pad(i + 1, j + 1)        );     % 等于其本身
            rec_Gr(i, j)  = fix((ori_pad(i + 1, j + 0) + ori_pad(i + 1, j + 2) ) / 2  ); % 水平方向相加
            rec_Gb(i, j)  = fix((ori_pad(i + 0, j + 1) + ori_pad(i + 2, j + 1) ) / 2  ); % 竖直方向相加
            rec_B (i, j)  = fix((ori_pad(i + 0, j + 0) + ori_pad(i + 2, j + 0) +  ori_pad(i + 0, j + 2) + ori_pad(i + 2, j + 2) ) / 4 );
            
        elseif ( (mod(i, 2) == 1) && (mod(j, 2) == 0) ) % 左上角
            rec_R (i, j)  = fix((ori_pad(i + 1, j + 0) + ori_pad(i + 1, j + 2) ) / 2 ); % 水平方向相加
            rec_Gr(i, j)  = fix( ori_pad(i + 1, j + 1)       );     % 等于其本身
            rec_Gb(i, j)  = fix((ori_pad(i + 0, j + 0) + ori_pad(i + 2, j + 0) + ori_pad(i + 0, j + 2) + ori_pad(i + 2, j + 2) ) / 4 );
            rec_B (i, j)  = fix((ori_pad(i + 0, j + 1) + ori_pad(i + 2, j + 1) ) / 2 ); % 竖直方向相加


        elseif ( (mod(i, 2) == 0) && (mod(j, 2) == 1) ) % 左下角
            rec_R (i, j)  = fix((ori_pad(i + 0, j + 1) + ori_pad(i + 2, j + 1)) / 2 ); % 竖直方向相加
            rec_Gr(i, j)  = fix((ori_pad(i + 0, j + 0) + ori_pad(i + 2, j + 0) + ori_pad(i + 0, j + 2) + ori_pad(i + 2, j + 2) ) / 4 );
            rec_Gb(i, j)  = fix( ori_pad(i + 1, j + 1));     % 等于其本身
            rec_B (i, j)  = fix((ori_pad(i + 1, j + 0) + ori_pad(i + 1, j + 2)) / 2 ) ; % 水平方向相加

        elseif ( (mod(i, 2) == 0) && (mod(j, 2) == 0) ) % 右下角
            rec_R (i, j)  = fix((ori_pad(i + 0, j + 0) + ori_pad(i + 2, j + 0) + ori_pad(i + 0, j + 2) + ori_pad(i + 2, j + 2) ) / 4 );
            rec_Gr(i, j)  = fix((ori_pad(i + 0, j + 1) + ori_pad(i + 2, j + 1)) / 2 ); % 竖直方向相加
            rec_Gb(i, j)  = fix((ori_pad(i + 1, j + 0) + ori_pad(i + 1, j + 2)) / 2 ); % 水平方向相加
            rec_B (i, j)  = fix( ori_pad(i + 1, j + 1));     % 等于其本身
        end
    end
end

% 像素极值的边界处理:
rec_G   = fix((rec_Gr + rec_Gb)/2);

rec_R(find(rec_R > 255)) = 255;
rec_G(find(rec_G > 255)) = 255;
rec_B(find(rec_B > 255)) = 255;

figure(1); imagesc(ori')   ; colormap(jet); colorbar; title("rggb原始图像")
outimg2 = cat(3, uint8(rec_R'), uint8(rec_G'), uint8(rec_B'));
figure(2); imagesc(outimg2); colormap(jet); title("demosaic预期值")

所用到的图像如下:

链接:https://pan.baidu.com/s/1buruDTKCBadrO1M_gvHLCg 
提取码:xb89

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值