isp算法学习-BLC
700 Words|Read in about 3 Min|本文总阅读量次
本文是isp算法学习的第二篇章,主要是讲述BLC原理和算法。
1产生原因
通常使用的CMOS或者CCD的Sensor。而CMOS就是MOS管,学过模拟电路的应该知道,MOS管(光电管)本质就是PN结。
1.1暗电流
左边的图是二极管的图,CMOS的PN结工作范围是反向,即UB到O的这段。在反向截止的区域里面,没有光照,依然存在电压,虽然电压的值非常小。这段区域就会产生暗电流,暗电流一般跟载流子的扩散和制造工艺相关。
理论上应该是0,0,0的输出,但是由于暗电流的存在,经过光电转换之后就会存在类似5,5,6的输出。
1.2AD前增加一个固定值
另外,由于AD模数转换前,会在模拟信号前加上一个固定的电压值,保证AD转换在精度范围内。
2校正方法
当前的主流方法有两种,sensor端和isp段。
2.1Sensor端
sensor端主要跟芯片相关
上图可以看到,有效的像素区域是3280*2464,底下灰色的区域为OB区域(Sensor预留了一些完全没有曝光的像素)。当整个Sensor处理完全黑暗环境,OB区域每个像素也会有一个值。
最简单的方法,就是对OB区取个平均值,然后让所有有效像素区减去这个值(模拟信号的值)即可。
其他算法可以查看这个专利。
2.2isp端
2.2.1固定值
本身有四个通道GR,GB,R,B通道。由于开始会在AD前增加一个固定值,这个时候把这个减掉即可。相当于区域往下平移C(C指的是固定值的偏移量),但是发现区域往下移动,整个区域就为0~(255-C)。我们这个时候会对两个G通道进行运算处理 $$ G_{in} = \frac{255}{255 - \Delta{C}} $$ 校正完成后,就能恢复到0~255的范围。
这里不对R和B通道处理,后面pipeline的AWB内容,会对其进行RGain和BGain的操作。
2.2.2ISO联动
黑电平直接和曝光增益相关联。(RK目前用的也是这个方式)
本身曝光增益跟曝光时间有关,曝光时间会影响温度,而温度也会间接影响到暗电流。通过曝光的倍数来减去对应的数值取平均也可以对其进行校正。
2.2.3曲线拟合
到isp端的RAW图,每个像素点的值都不是相同的值,选取一定数量的样本点,每个样本点需要包含四个通道GR,GB,R,B,然后对样本点的周围进行拟合。
2.3总结
目前固定值的方式是最普遍的,代价也是最小的。
其余两种方式或是存表或是联动,都需要一定的内存开销。
3方法实现
盖上镜头盖或者处于全黑的环境下,抓取Raw图,四个通道的值因为存在暗电流和固定值,所以必定存在一个值。
1)分成四个通道
2)每个通道求mean值(或者中位值),求得△R,△GR,△GB,△B
3)RAW图上的每个像素点所在的通道,减去对应通道的平均值即可,就能大致恢复到RGB(0,0,0)
上面的左边那张图,显示有一定的值,经过BLC之后,就是最右的图,显示的值都趋于为0,且图片颜色会更加黑。
3.1效果展示
3.2Raw图信息
1% ------------Raw Format----------------
2filePath = 'images/HisiRAW_4208x3120_8bits_RGGB.raw';
3bayerFormat = 'RGGB';
4row = 4208;
5col = 3120;
6bits = 8;
7% --------------------------------------
3.3 读取Raw矩阵
1% I(1:2:end, 1:2:end) = R(1:1:end, 1:1:end);
2
3data = readRaw(filePath, bits, row, col);
readRaw
1function rawData = readRaw(fileName, bitsNum, row, col)
2% readRaw.m get rawData from HiRawImage
3% Input:
4% fileName the path of HiRawImage
5% bitsNum the number of bits of raw image
6% row the row of the raw image
7% col the column of the raw image
8% Output:
9% rawData the matrix of raw image data
10% Instructions:
11% author: wtzhu
12% e-mail: wtzhu_13@163.com
13% Last Modified by wtzhu v1.0 2021-06-29
14% Note:
15
16% get fileID
17fin = fopen(fileName, 'r');
18% format precision
19switch bitsNum
20 case 8
21 disp('bits: 8');
22 format = sprintf('uint8=>uint8');
23 case 10
24 disp('bits: 10');
25 format = sprintf('uint16=>uint16');
26 case 12
27 disp('bits: 12');
28 format = sprintf('uint16=>uint16');
29 case 16
30 disp('bits: 16');
31 format = sprintf('uint16=>uint16');
32end
33% 转换成列向量
34I = fread(fin, row*col, format);
35%转换成1维矩阵
36% plot(I, '.');
37z = reshape(I, row, col);
38z = z';
39rawData = z;
40% imshow(z);
41end
- 判断是8bit,10bit,12bit还是16bit的值
- 转换成列向量
- 转换成一维矩阵
3.4分成四个通道
根据R|GR|GB|B的排布方式,分成四个通道
1% get the four channels by bayerFormat
2switch bayerFormat
3 case 'RGGB'
4 disp('bayerFormat: RGGB');
5 R = data(1:2:end, 1:2:end);
6 Gr = data(1:2:end, 2:2:end);
7 Gb = data(2:2:end, 1:2:end);
8 B = data(2:2:end, 2:2:end);
9 case 'GRBG'
10 disp('bayerFormat: GRBG');
11 Gr = data(1:2:end, 1:2:end);
12 R = data(1:2:end, 2:2:end);
13 B = data(2:2:end, 1:2:end);
14 Gb = data(2:2:end, 2:2:end);
15 case 'GBRG'
16 disp('bayerFormat: GBRG');
17 Gb = data(1:2:end, 1:2:end);
18 B = data(1:2:end, 2:2:end);
19 R = data(2:2:end, 1:2:end);
20 Gr = data(2:2:end, 2:2:end);
21 case 'BGGR'
22 disp('bayerFormat: BGGR');
23 B = data(1:2:end, 1:2:end);
24 Gb = data(1:2:end, 2:2:end);
25 Gr = data(2:2:end, 1:2:end);
26 R = data(2:2:end, 2:2:end);
27end
3.5计算每个通道均值
1% calculate the Correction coefficient of every channel
2R_mean = round(mean(mean(R)));
3Gr_mean = round(mean(mean(Gr)));
4Gb_mean = round(mean(mean(Gb)));
5B_mean = round(mean(mean(B)));
6
7% Correct each channel separately
8cR = R-R_mean;
9cGr = Gr-Gr_mean;
10cGb = Gb-Gb_mean;
11cB = B-B_mean;
12fprintf('R:%d Gr:%d Gb:%d B:%d\n', R_mean, Gr_mean, Gb_mean, B_mean);
13
14cData = zeros(size(data));
3.6四个通道还原到Raw图
1% Restore the image with four channels
2switch bayerFormat
3 case 'RGGB'
4 disp('bayerFormat: RGGB');
5 cData(1:2:end, 1:2:end) = cR(1:1:end, 1:1:end);
6 cData(1:2:end, 2:2:end) = cGr(1:1:end, 1:1:end);
7 cData(2:2:end, 1:2:end) = cGb(1:1:end, 1:1:end);
8 cData(2:2:end, 2:2:end) = cB(1:1:end, 1:1:end);
9 case 'GRBG'
10 disp('bayerFormat: GRBG');
11 cData(1:2:end, 1:2:end) = cGr(1:1:end, 1:1:end);
12 cData(1:2:end, 2:2:end) = cR(1:1:end, 1:1:end);
13 cData(2:2:end, 1:2:end) = cB(1:1:end, 1:1:end);
14 data(2:2:end, 2:2:end) = cGb(1:1:end, 1:1:end);
15 case 'GBRG'
16 disp('bayerFormat: GBRG');
17 cData(1:2:end, 1:2:end) = cGb(1:1:end, 1:1:end);
18 cData(1:2:end, 2:2:end) = cB(1:1:end, 1:1:end);
19 cData(2:2:end, 1:2:end) = cR(1:1:end, 1:1:end);
20 cData(2:2:end, 2:2:end) = cGr(1:1:end, 1:1:end);
21 case 'BGGR'
22 disp('bayerFormat: BGGR');
23 cData(1:2:end, 1:2:end) = cB(1:1:end, 1:1:end);
24 cData(1:2:end, 2:2:end) = cGb(1:1:end, 1:1:end);
25 cData(2:2:end, 1:2:end) = cGr(1:1:end, 1:1:end);
26 cData(2:2:end, 2:2:end) = cR(1:1:end, 1:1:end);
27end
3.7展示效果
1function show(orgData, corData, bitsNum, mean)
2% show.m Data visualization
3% Input:
4% orgData the org img data
5% corData the corrected data of img
6% bitsNum the count of bits
7% Output:
8% Instructions:
9% author: wtzhu
10% e-mail: wtzhu_13@163.com
11% Last Modified by wtzhu v1.0 2021-06-30
12% Note:
13 yMax = 2^bitsNum;
14 listOrgData = orgData(:);
15 listCorData = corData(:);
16 figure;
17 subplot(221);
18
19 imshow(orgData);
20 title('orgDta');
21 subplot(222);
22
23 imshow(uint8(corData));
24 title('corData');
25 subplot(223)
26
27 plot(listOrgData(listOrgData<(mean+10)))
28 title('org pixel value');
29 ylim([-10 yMax]);
30 subplot(224);
31
32 plot(listCorData(listCorData<(yMax*10/255)));
33 title('cor pixel value');
34 ylim([-10 yMax]);
35end
源码查看
可以点击这里