BLC(Black Level Correction)——黑电平校正

产生原因

暗电流:
image
没有暗电流的情况下,中间部分应该为0
AD:
image
模拟信号通过AD转化为数字信号交给ISP算法,因为AD转换一般有一个阈值,所以微弱电流无法直接转化,需要把整体亮度值加一个n,同时人对黑色更加敏感,如:人能发现0-20之间的亮度变化,而对于235-255之间的亮度变化就不会发现。转化为数字信号后,会整体向下减少n。

校正方法

Sensor端:
OBC方法:
将黑色蒙在传感器上,即OB区,此时亮度为0,经过AD后会整体加n,这样根据ad转换的值取平均就可以得到n了。
image
ISP端:
Bayer校正法:
固定值方法:
直接减去n(用c来代表n)会导致部分丢失
image
所以对G进行一个比值的对应,但是对R和G不做操作,因为在自动白平衡之后会×一个参数gain,将R和G映射到0-255
ISO联动:
根据曝光时间计算增益,采样之后取平均。
曲线拟合:
黑布蒙上相机,以GRBG为单位采样,未采样部分使用插值计算的方法。

总结

image

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
posted @ 2022-08-01 13:43  蘑菇王国大聪明  阅读(861)  评论(0编辑  收藏  举报