写作意图:
写接下来几篇的原因是,谈谈自己对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图像传感器的部分结构。
图1:CMOS 传感器的内部结构。黄色:微透镜,紫色:感光片(光电二极管),每个感光片上都会对应周期排布的R, Gr, Gb, B四种颜色的滤波片。
因此,看起来像mosaic的raw图像是彩色CMOS传感器得到如图2所示的玩意。
图2:mosaic图像
Demosaic的原理是从类似于图2的mosaic中,分离出R, G, B三通道(如图3所示),其采用的方法如插值算法。
图3 RGB分离
二、插值算法理论:
[1]: 周围3x3区域,四个角存在相同颜色点的:那中心点的值为四个点的均值
[2]: 周围3x3区域,只有水平方向存在上下两个相同颜色点::那中心点的值为左右2个点的均值
[3]: 周围3x3区域,只有垂直方向存在上下两个相同颜色点::那中心点的值为上下2个点的均值
算法总结为:
第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