BLC(Black Level Correction)——黑电平校正
产生原因
暗电流:
没有暗电流的情况下,中间部分应该为0
AD:
模拟信号通过AD转化为数字信号交给ISP算法,因为AD转换一般有一个阈值,所以微弱电流无法直接转化,需要把整体亮度值加一个n,同时人对黑色更加敏感,如:人能发现0-20之间的亮度变化,而对于235-255之间的亮度变化就不会发现。转化为数字信号后,会整体向下减少n。
校正方法
Sensor端:
OBC方法:
将黑色蒙在传感器上,即OB区,此时亮度为0,经过AD后会整体加n,这样根据ad转换的值取平均就可以得到n了。
ISP端:
Bayer校正法:
固定值方法:
直接减去n(用c来代表n)会导致部分丢失
所以对G进行一个比值的对应,但是对R和G不做操作,因为在自动白平衡之后会×一个参数gain,将R和G映射到0-255
ISO联动:
根据曝光时间计算增益,采样之后取平均。
曲线拟合:
黑布蒙上相机,以GRBG为单位采样,未采样部分使用插值计算的方法。
总结
matlab实现
readData.m
function rawData = readRaw(fileName, bitsNum, row, col)
% readRaw.m get rawData from HiRawImage
% Input:
% fileName the path of HiRawImage
% bitsNum the number of bits of raw image
% row the row of the raw image
% col the column of the raw image
% Output:
% rawData the matrix of raw image data
% Instructions:
% author: wtzhu
% e-mail: wtzhu_13@163.com
% Last Modified by wtzhu v1.0 2021-06-29
% Note:
% get fileID
fin = fopen(fileName, 'r');
% format precision
switch bitsNum
case 8
disp('bits: 8');
format = sprintf('uint8=>uint8');
case 10
disp('bits: 10');
format = sprintf('uint16=>uint16');
case 12
disp('bits: 12');
format = sprintf('uint16=>uint16');
case 16
disp('bits: 16');
format = sprintf('uint16=>uint16');
end
I = fread(fin, row*col, format);
% plot(I, '.');
z = reshape(I, row, col);
z = z';
rawData = z;
% imshow(z);
end
blc.m
clc;clear;close all;
% ------------Raw Format----------------
filePath = 'images/HisiRAW_4208x3120_8bits_RGGB.raw';
bayerFormat = 'RGGB';
row = 4208;
col = 3120;
bits = 8;
% --------------------------------------
% I(1:2:end, 1:2:end) = R(1:1:end, 1:1:end);
data = readRaw(filePath, bits, row, col);
% get the four channels by bayerFormat
switch bayerFormat
case 'RGGB'
disp('bayerFormat: RGGB');
R = data(1:2:end, 1:2:end);
Gr = data(1:2:end, 2:2:end);
Gb = data(2:2:end, 1:2:end);
B = data(2:2:end, 2:2:end);
case 'GRBG'
disp('bayerFormat: GRBG');
Gr = data(1:2:end, 1:2:end);
R = data(1:2:end, 2:2:end);
B = data(2:2:end, 1:2:end);
Gb = data(2:2:end, 2:2:end);
case 'GBRG'
disp('bayerFormat: GBRG');
Gb = data(1:2:end, 1:2:end);
B = data(1:2:end, 2:2:end);
R = data(2:2:end, 1:2:end);
Gr = data(2:2:end, 2:2:end);
case 'BGGR'
disp('bayerFormat: BGGR');
B = data(1:2:end, 1:2:end);
Gb = data(1:2:end, 2:2:end);
Gr = data(2:2:end, 1:2:end);
R = data(2:2:end, 2:2:end);
end
% calculate the Correction coefficient of every channel
R_mean = round(mean(mean(R)));
Gr_mean = round(mean(mean(Gr)));
Gb_mean = round(mean(mean(Gb)));
B_mean = round(mean(mean(B)));
% Correct each channel separately
cR = R-R_mean;
cGr = Gr-Gr_mean;
cGb = Gb-Gb_mean;
cB = B-B_mean;
fprintf('R:%d Gr:%d Gb:%d B:%d\n', R_mean, Gr_mean, Gb_mean, B_mean);
cData = zeros(size(data));
% Restore the image with four channels
switch bayerFormat
case 'RGGB'
disp('bayerFormat: RGGB');
cData(1:2:end, 1:2:end) = cR(1:1:end, 1:1:end);
cData(1:2:end, 2:2:end) = cGr(1:1:end, 1:1:end);
cData(2:2:end, 1:2:end) = cGb(1:1:end, 1:1:end);
cData(2:2:end, 2:2:end) = cB(1:1:end, 1:1:end);
case 'GRBG'
disp('bayerFormat: GRBG');
cData(1:2:end, 1:2:end) = cGr(1:1:end, 1:1:end);
cData(1:2:end, 2:2:end) = cR(1:1:end, 1:1:end);
cData(2:2:end, 1:2:end) = cB(1:1:end, 1:1:end);
data(2:2:end, 2:2:end) = cGb(1:1:end, 1:1:end);
case 'GBRG'
disp('bayerFormat: GBRG');
cData(1:2:end, 1:2:end) = cGb(1:1:end, 1:1:end);
cData(1:2:end, 2:2:end) = cB(1:1:end, 1:1:end);
cData(2:2:end, 1:2:end) = cR(1:1:end, 1:1:end);
cData(2:2:end, 2:2:end) = cGr(1:1:end, 1:1:end);
case 'BGGR'
disp('bayerFormat: BGGR');
cData(1:2:end, 1:2:end) = cB(1:1:end, 1:1:end);
cData(1:2:end, 2:2:end) = cGb(1:1:end, 1:1:end);
cData(2:2:end, 1:2:end) = cGr(1:1:end, 1:1:end);
cData(2:2:end, 2:2:end) = cR(1:1:end, 1:1:end);
end
主要是给自己看的,所以肯定会出现很多错误哈哈哈哈哈