what is the LSC?

lens shading 分为:Y-shading , color shading。

在讲LSC之前,我们先来理解一个重要的术语--CRA(Chief ray angle)。

CRA:分为lens cra , sensor cra两种。

1.1什么是lens CRA?

定义:最大像高处的主光线与光轴的倾角。备注:最大像高定义为 像素响应降低为零度角像素响应的80%的像素点。

因为Lens CRA 的存在,所以就出现了FOV (filed of view) 所谓的视角的概念。视角大小=2*CRA。

下图为lens CRA示意图。

1.2 什么是sensor的CRA

               sensor的CRA 说白了是sensor与之配对的micro lens的CRA.

圈1 表示lens折射过来的光,圈2表示micro lens再次折射的光。可以看出,sensor的光电转换二极管接收到的光并不是                 lens直接折射过来的,而是经过microlens再次折射过来的。所以你明白了什么呢?! 这也就是为什么图像边缘会变暗                   的原因,光电转换二极管并不会全部接收到光能。这是LensShading中Y-shading的主要原因。

一般情况下,当lens_cra < micro_cra的时候,在sensor传感器的边缘只会出现Y-shading。

倘若,lens_cra > micro_cra, sensor传感器可能会因为无法有效捕捉某频率的光,就会出现偏色的情况,即Color-                          shading。比如microlens 对R ,G,B的折射率不同,在R_pixel上接收了很小的能量,而在B_pixel上接受了相对较多的能                  量。

如何处理或者叫减轻shading带来的图像不均问题呢?

              1.lens cra要小于micro cra,这样既可以减缓y-shading,又可以大大避免color-shading.

              2.因为镜头是圆的,画面的对角线是最接近镜头成像直径的,所以sensor有效区域最大尺寸是对角线尺寸

3.硬件矫正

4.软件矫正(下面会细讲)

how to LSC with software?

一般模组厂会根据矫正工具将图像划分为17*13(qualcomm),15*15(MTK),33*25(Samsung)等区间,计算每一块的四通道平均值,然后对每个通道与中心块的四通道平均值做除法,得到每个点的增益倍数,整个lut存储在otp中,手机端就可以根据lut进行插值计算每个pixel的增益。

一般用双线性差值或者多项式拟合的方法,确定每个pixel的增益。

原始图片的rgb通道(节选自网络):

y-shading 增益之后,基本与中心数值在同一个平面(节选自网络):

color-shading 增益之后,各区域的r/g,b/g均值相同(节选自网络):

上面三张图片为了让大家理解,节选自网络。本人也模拟了shading矫正过程,但由于colorshading不严重所以矫正效果不明显。下面是我的矫正过程:

1.原始图:

2.三通道三维图

3.(17*13block)r,g,b平均

4.colorgain

5、lensgain=ygain+colorgain

6. 还原后三通道值

7.还原后图片

附上我的代码:

clc
clear all;
close all;
BLOCK_H = 17
BLOCK_V = 13
img = imread('1.bmp');
r= medfilt2(img(:,:,1));%中值滤波抑制边缘凸起噪声
g= medfilt2(img(:,:,2));
b= medfilt2(img(:,:,3));
figure(1)
[rows,cols,channels] = size(img);
width = 1:cols; height = 1:rows; [X1,Y1] = meshgrid(width,height);
mesh(X1,Y1,im2double(r)); hold on; mesh(X1,Y1,im2double(g)); hold on; mesh(X1,Y1,im2double(b));

subSampleRGB=ones(BLOCK_V+1,BLOCK_H+1,3);%6*6*3 gainlut

strideX=floor(cols/BLOCK_H)
strideY=floor(rows/BLOCK_V)
for i=1:BLOCK_H+1%cols
    for j=1:BLOCK_V+1%rows
        for k=1:3%channels
            if i==1
                if j==1%left_top
                   subSampleRGB(j,i,k)=mean2( img(1:floor(strideY*0.5),                                1:floor(strideX*0.5),k) );
                elseif j==BLOCK_V+1 %left_bottom
                   subSampleRGB(j,i,k)=mean2( img(floor((BLOCK_V-0.5)*strideY):BLOCK_V*strideY,        1:floor(strideX*0.5),k) );
                else %left_middle
                   subSampleRGB(j,i,k)=mean2( img(floor((j-1-0.5)*strideY):floor((j-1+0.5)*strideY),   1:floor(strideX*0.5),k) );
                end
            elseif i==BLOCK_H+1
                if j==1%right_top
                   subSampleRGB(j,i,k)=mean2( img(1:floor(strideY*0.5),                                floor(strideX*(BLOCK_H-0.5)):BLOCK_H*strideX,k) );
                elseif j==BLOCK_V+1 %right_bottom
                   subSampleRGB(j,i,k)=mean2( img(floor((BLOCK_V-0.5)*strideY):BLOCK_V*strideY,        floor(strideX*(BLOCK_H-0.5)):BLOCK_H*strideX,k) );
                else %right_middle
                   subSampleRGB(j,i,k)=mean2( img(floor((j-1-0.5)*strideY):floor((j-1+0.5)*strideY),        floor(strideX*(BLOCK_H-0.5)):BLOCK_H*strideX,k) );
                end
            elseif j==1%top without corner
                if i~=1&&i~=BLOCK_H+1
                    subSampleRGB(j,i,k)=mean2( img(1:floor(0.5*strideY),                               floor(strideX*(i-1-0.5)):floor(strideX*(i-1+0.5)),k) );
                end
            elseif j==BLOCK_V+1%bottom without corner
                if i~=1&&i~=BLOCK_H+1
                    subSampleRGB(j,i,k)=mean2( img(floor((BLOCK_V-0.5)*strideY):BLOCK_V*strideY,       floor(strideX*(i-1-0.5)):floor(strideX*(i-1+0.5)),k));
                end
            else
                if i~=1&&i~=BLOCK_H+1&&j~=1&&j~=BLOCK_V+1 %center area
                    subSampleRGB(j,i,k)=mean2( img(floor((j-1-0.5)*strideY):floor((j-1+0.5)*strideY),  floor(strideX*(i-1-0.5)):floor(strideX*(i-1+0.5)),k));
                end
            end
        end
    end
end

figure(2)
[A,B] = meshgrid(1:BLOCK_H+1,1:BLOCK_V+1);
mesh(A,B,subSampleRGB(:,:,1));
hold on
mesh(A,B,subSampleRGB(:,:,2));
hold on
mesh(A,B,subSampleRGB(:,:,3));

%Gainlut luma gain (Y-shading gain)
gainlut=zeros(BLOCK_V+1,BLOCK_H+1,3);% gainlut
for i = 1:BLOCK_H+1
    for j =1:BLOCK_V+1
        for k = 1:3
           gainlut(j,i,k)=mean2( subSampleRGB(floor(BLOCK_V/2+1) : floor(BLOCK_V/2+1)+1,  floor(BLOCK_H/2+1) : floor(BLOCK_H/2+1)+1,k)) / subSampleRGB(j,i,k);
        end
    end
end

%Gainlut chroma gain (colorshading gain)
gainlut_c = zeros(BLOCK_V+1,BLOCK_H+1,2);
center_RoverG = mean2( subSampleRGB(floor(BLOCK_V/2+1) : floor(BLOCK_V/2+1)+1,  floor(BLOCK_H/2+1) : floor(BLOCK_H/2+1)+1,1)) / mean2( subSampleRGB(floor(BLOCK_V/2+1) : floor(BLOCK_V/2+1)+1,  floor(BLOCK_H/2+1) : floor(BLOCK_H/2+1)+1,2));
center_BoverG = mean2( subSampleRGB(floor(BLOCK_V/2+1) : floor(BLOCK_V/2+1)+1,  floor(BLOCK_H/2+1) : floor(BLOCK_H/2+1)+1,3)) / mean2( subSampleRGB(floor(BLOCK_V/2+1) : floor(BLOCK_V/2+1)+1,  floor(BLOCK_H/2+1) : floor(BLOCK_H/2+1)+1,2));
for i = 1:BLOCK_H+1
    for j =1:BLOCK_V+1
           RoverG = subSampleRGB(j,i,1)/subSampleRGB(j,i,2);
           BoverG = subSampleRGB(j,i,3)/subSampleRGB(j,i,2);
           gainlut_c(j,i,1) = center_RoverG/RoverG-1;
           gainlut_c(j,i,2) = center_BoverG/BoverG-1;
    end
end

%chroma+luma gain
gainlut_full = zeros(BLOCK_V+1,BLOCK_H+1,2);
for i = 1:BLOCK_H+1
    for j =1:BLOCK_V+1
           gainlut_full(:,:,1) = gainlut(:,:,1) + gainlut_c(j,i,1);
           gainlut_full(:,:,2) = gainlut(:,:,2) + gainlut_c(j,i,2);
    end
end

%(BLOCK_H+1)*(BLOCK_V+1) colorgain
figure(3)
[C,D] = meshgrid(1:BLOCK_H+1,1:BLOCK_V+1);
mesh(C,D,gainlut_c(:,:,1))
hold on
mesh(C,D,gainlut_c(:,:,2))

figure(4)
mesh(C,D,gainlut_full(:,:,1))
hold on
mesh(C,D,gainlut_full(:,:,2))
hold on
mesh(C,D,gainlut(:,:,2))

%双线性插值FullGainLut
x = 1:strideX:cols+1;
x(end) = cols;
y = 1:strideY:rows+1;
y(end) = rows;

xitp = 1:cols;
yitp = 1:rows;
[Xitp,Yitp]=meshgrid(xitp,yitp);
rgain=interp2(x,y,gainlut(:,:,1),Xitp,Yitp);
ggain=interp2(x,y,gainlut(:,:,2),Xitp,Yitp);
bgain=interp2(x,y,gainlut(:,:,3),Xitp,Yitp);

%shading r,b,g gain
figure(5)
r=im2uint8( (im2double(r).*rgain) );
mesh(X1,Y1,im2double(r));
b=im2uint8( (im2double(b).*bgain) );
hold on
mesh(X1,Y1,im2double(b));
g=im2uint8( (im2double(g).*ggain) );
hold on
mesh(X1,Y1,im2double(g));

%shading corrected img
figure(6)
lscgain = cat(3,rgain,ggain,bgain);%merge三通道gain
imgDoubleType = im2double(img);
imgDoubleType = imgDoubleType.*lscgain;
imgUint = im2uint8(imgDoubleType);
imshow(imgUint)

ISP PIPLINE (二) LensShading Correct的更多相关文章

  1. ISP PIPLINE (六) 3A 综述

    前言: 上一篇文章: ISP PIPLINE (五) Denoise 下一篇文章: (1)3A定义包括什么 Iris:自动光圈,根据环境自动调节光圈. 既然讲到光圈,就先看一下光圈是什么,以及它如何影 ...

  2. ISP PIPLINE (十四) AE(自动曝光)

    自动曝光可以可以通过调节 模拟增益,数字增益,曝光时间,光圈大小来调剂曝光. 曝光在ISP PIPLINE的位置. (先介绍一个额外的知识点: ) gamma compression(也就是de-ga ...

  3. ISP PIPLINE(零) 知识综述预热

    本文为camera isp pipline概述 ISP,即image signal processing.为图像成型做的处理工作.适应不同光学环境下图像的还原. pipline流程如下: 光通过LEN ...

  4. ISP PIPLINE (十二) Sharpening

    什么是sharpening? 不解释,从左到右为sharpen , 从右到左为blur. 简单理解为边缘增强,使得轮廓清晰.增强对比度. 如何进行sharpening? 下面是实际sharpen的过程 ...

  5. ISP PIPLINE (七) gamma

    what is the gamma? CCD.CMOS成像方式是通过像点中的"硅"感受光线的强弱而获得画面.而硅感光是物理成像,它真实地反应光线强度的变化,来多少就输出多少,因此它 ...

  6. ISP PIPLINE (一) BLC 以及 线性化

    what is the BlackLevel? 暗电流来源1.raw8为例,单个pixel的有效值是0~255,但是实际AD芯片的精度可能无法将电压值很小的一部分转换出来,芯片厂会刻意添加一个固定的偏 ...

  7. ISP PIPLINE (十五) AF

    主流的AF: CDAF, PDAF, laser assist AF(这个只是辅助,在微距或者拍摄纹理不明显的场景下好用). AF的大致原理就是检测图像锐度或者等价于锐度的参数,推动马达实现合焦或者对 ...

  8. ISP PIPLINE (九_2) Denoise 之 time domain denoise

    时域噪声是空域噪声在时间上波动的一种描述. 1.多帧平均去噪法 1.1 理论: 1.2 帧数增加,噪声减小: 1.3 IIR滤波器的效果 2.1中的两种方法在拍摄视频的时候,如果有运动物体,则会出现拖 ...

  9. ISP PIPLINE (九_1) Denoise 之 space domain denoise

    1.空间域噪声类型 1.gauss+possion 2.椒盐噪声(dpc处理已经处理了) 去除空域噪声有哪些方法? 空域噪声一般的思想是对某pixel邻域的pixels进行加权平均. 比如 1.高斯降 ...

随机推荐

  1. pytest 12 函数传参和fixture传参数request

    前沿: 有的case,需要依赖于某些特定的case才可以执行,比如,登陆获取到的cookie,每次都需要带着他,为了确保是同一个用户,必须带着和登陆获取到的同一个cookies. 大部分的用例都会先登 ...

  2. 批量ping 检测linux主机是否可以通

    批量ping 检测linux主机是否可以通 # 1.配置列表 [root@db137 liweiwie]# cat /home/dbatlbb/script/liweiwie/ping_ip.txt ...

  3. lcd驱动框架

    目录 lcd驱动框架 框图 程序分析 入口 打开open 读read 初始化registered_fb 注册 小结 程序设计 测试 方式一操作fb0 方式二操作tty 方式三操作终端 完整程序 tit ...

  4. 使用Spring-Integration实现http消息转发

    目标:接收来自华为云的服务器报警信息,并转发到钉钉的自定义机器人中 使用Spring-Integration不仅节省了很多配置,还增加了可用性. 更多关于Spring-Integration的介绍可参 ...

  5. [再寄小读者之数学篇](2014-06-23 二阶导数估计 [中国科学技术大学2013年高等数学B 考研试题])

    设 $f(x)$ 二阶连续可导, $f(0)=f(1)=0$, $\dps{\max_{0\leq x\leq 1}f(x)=2}$. 证明: $$\bex \min_{0\leq x\leq 1}f ...

  6. [物理学与PDEs]第4章第2节 反应流体力学方程组 2.1 粘性热传导反应流体力学方程组

    1.  记号: $Z=Z(t,{\bf x})$ 表示未燃气体在微团中所占的百分比 ($Z=1$ 表示完全未燃烧; $Z=0$ 表示完全燃烧). 2.  物理化学 (1)  燃烧过程中, 通过化学反应 ...

  7. [物理学与PDEs]第1章习题4 偶极子的极限电势

    对在 $P_0$ 及 $P_1$ 处分别置放 $-q$ 及 $+q$ 的点电荷所形成的电偶极子, 其偶极距 ${\bf m}=q{\bf l}$, ${\bf l}=\vec{P_0P_1}$. 试证 ...

  8. MySQL的一些基本命令笔记(3)

    指明外键: 1 :1 两个表中的主键都可以当成外键 1 :N 在 "多" 的实体表中新增加一个字段,该字段是 "一" 实体表的主键 M : N 拆成两个1 :N ...

  9. H5——while循环,for循环

    [循环结构的步骤] * ① 声明循环变量 * ② 判断循环条件 * ③ 执行循环体(while的{}中的所有代码) * ④ 更改循环变量 * 然后执行② ③ ④   var n=1; // ① 声明循 ...

  10. Yii2.0连接多个数据库

    Yii2.0连接多个数据库    一个项目根据需要会要求连接多个数据库,这里记录下实际项目中的操作流程.包括对数据库连接的配置以及如何生成模型文件,在控制器中加以运用. 一.配置 打开数据库配置文件c ...