• opencv实现camera模组的暗电流和lenshading补偿 .


    目录(?)[-]

    1. 简介
    2. 基本原理
      1. 产生原因
      2. 校正补偿原理
    3. 具体实现
      1. 框架搭建
      2. 功能实现
        1. 暗电流
        2. lenshading补偿
      3. 效果演示
        1. 图片处理
      4. 效果演示

    简介

      在接触过的qcom和mtk平台中,camera调试软件和流程基本都是大同小异。所以查了点资料,然后模仿这些软件,自己练习写了下最开始的
    两步:暗电流和len shading补偿。
    

    基本原理

    产生原因

      在camera模组中,会因为sensor本身的暗电流,从而对图像参数噪声。同时也会因为模组镜头的原因,导致拍摄照片的亮度,中间亮而四周相对较暗。
    所以在模组工作中,我们需要对模组做暗电流的校正和len shading相关的补偿。对这方面深入的了解,请自己查询相关资料吧,这里只简单讲解下。
    

    校正补偿原理

      理解到了暗电流和len shading产生原因之后,就可以通过如下步骤开始进行校正。
      暗电流校正:1、用黑胶布遮住摄像头,然后在全黑环境下拍摄一张全尺寸的照片。
                    2、软件读取并保存住这张图片的值,这里面非0的值,都是由sensor的暗电流产生的噪点,当对照片处理的时候,
                       需要减去这些对应的噪声。
      lenshading补偿:1、用毛玻璃盖住模组,在灯箱下拍摄一张照片。正常情况下,可以看到照片是中心亮,而四周相对较暗。
                        2、将拍摄的照片通过处理,找出照片中最亮位置的亮度,然后用这个亮度为基准,记录下整个图片中,每个像素位置亮度和
                           这个亮度的比值。当对照片处理的时候,对应像素位置乘以这个比值。
    

    具体实现

    框架搭建

      根据前面一篇提到的《opencv模拟button》,构建出了基本软件背景界面和三个操作按键。分别对应为暗电流、len shading补偿、图片处理。
    效果如下:
             
                       

      软件的运行如下:./XXX darkcurrent.jpg lenshading.jpg tmp.jpg
      darkcurrent.jpg:拍摄的暗电流照片。
      lenshading.jpg:拍摄的len shading照片。
      tmp.jpg:需要被处理的照片。
    

    功能实现

      所以我们需要关心的就是那三个控件对应的事件处理功能。
    
    void on_button(int buttonNow, Mat img){
        if(buttonNow == 0){
            doDarkCurrent(img);
        }else if(buttonNow == 1){
            lenrollOff(img);
        }else if(buttonNow == 2){
            pic_process(img);
        }
        buttonFlag[buttonNow] = true;
    }

    暗电流

    void doDarkCurrent(Mat mat){                                                                                                         
        IplImage pI = mat;
        IplImage pI_2 = img3;
        int width = mat.rows;
        int height = mat.cols;
        CvScalar s;
        int i, j;
        double b_count = 0, g_count = 0, r_count = 0;
     
        for(i=0; i<height; i++){
            for(j=0; j<width; j++){
                s = cvGet2D(&pI, j, i);
                cvSet2D(&pI_2, j, i, s);
            }
        }
    }
      实现很简单,就是将darkcurrent.jpg的照片数据保存到img3中,作为暗电流操作的操作数据。
    

    lenshading补偿

    void lenrollOff(Mat img){                                                                                                            
        int *address;
        double maxLight;
        address = (int *)malloc(2);
        IplImage pI = img;
        getMaxLight(img, address, &maxLight); /* 找到图像中最亮的点位置,address为最亮点所在的坐标 */
        lenShading(maxLight, img, img4);
    }
      img对应为传入的lenshading.jpg。首先通过函数getMaxLight,建立一个8X8的矩阵,然后该图片中从头到尾计算出矩阵包围的图片区域亮度,
    并找出最高的位置和对应平均亮度。
      接着使用函数lenShading,计算出图片所有像素和上一步得到的最大亮度之间比值,对应的保存在img4中。
    

    效果演示

      使用步骤:1、运行软件:./xxx ./res/dark.jpg ./res/lenoff.jpg ./res/1.jpg
                2、依次点击控件:darkcurrent lenrolloff process。
                3、最后效果如下:
    

    图片处理

      在第一步和第二步处理完了之后,接着就可以进行第三步的图片处理。
    
    void pic_process(Mat img){
        imshow("poc_process", img);
        /*process for DarkCurrent*/
        proDark(img);
     
        /*process for lenrollOff*/
        prolenOff(img);
        imshow("prolenOff", img);
    }
      这一步中,首先显示出来,需要被处理的照片,也就是之前传入的tmp.jpg。接着使用proDark来减去暗电流产生的噪点。接着使用函数prolenOff进行
    图片lenshading的补偿,最后将处理后的图片也显示出来。
    
    void proDark(Mat img){
        int width = img.rows;
        int height = img.cols;
        IplImage pI = img;
        int i, j;
        CvScalar s, s1;
        IplImage pI_2 = img3;
        int start_Haddr = img3.cols / 2 - height / 2;
        int end_Haddr = img3.cols / 2 + height / 2;
        int start_Waddr = img3.rows / 2 - width / 2;
        int end_Waddr = img3.rows / 2 + width / 2;
     
        if((width > img3.rows) || (height > img3.cols)){
            printf("proDark is error!!!!!!
    ");
            return;
        }
        for(i=start_Haddr; i < end_Haddr; i++){
            for(j = start_Waddr; j < end_Waddr; j++){
                s = cvGet2D(&pI_2, j, i);
                s1 = cvGet2D(&pI, j - start_Waddr, i - start_Haddr);
     
                s1.val[0] = s1.val[0] - s.val[0];
                s1.val[1] = s1.val[1] - s.val[1];
                s1.val[2] = s1.val[2] - s.val[2];
     
                cvSet2D(&pI, j - start_Waddr, i - start_Haddr, s1);
            }   
        }
    }
      在传入的处理图片中,如果是被sensor裁剪过的话,那就从暗电流保存数据的中心开始,计算出和处理照片同样大小的数据,然后处理照片再依次
    减去对应的暗电流噪声数据。
    
    void prolenOff(Mat img){
        int width = img.rows;
        int height = img.cols;
        IplImage pI = img;
        IplImage pI_2 = img4;
        int i, j;
        CvScalar s, s1;
     
        cvCvtColor(&pI, &pI, CV_RGB2YCrCb);
        if((width > img4.rows) || (height > img4.cols)){
            printf("prolenOff is error!!!!!!
    ");
            return;
        }
        int start_Haddr = img4.cols / 2 - height / 2;
        int end_Haddr = img4.cols / 2 + height / 2;
        int start_Waddr = img4.rows / 2 - width / 2;
        int end_Waddr = img4.rows / 2 + width / 2;
     
        for(i=start_Haddr; i < end_Haddr; i++){
            for(j = start_Waddr; j < end_Waddr; j++){
                s = cvGet2D(&pI_2, j, i);
                s1 = cvGet2D(&pI, j - start_Waddr, i - start_Haddr);
                s1.val[0] = s1.val[0] * s.val[0] / 50;
     
                cvSet2D(&pI, j - start_Waddr, i - start_Haddr, s1);
            }   
        }
        cvCvtColor(&pI_2, &pI_2, CV_YCrCb2RGB);
        cvCvtColor(&pI, &pI, CV_YCrCb2RGB);
    }
      len shading补偿也是一样,根据处理图片大小,从补偿数据的中心开始,取出相应大小的数据,然后将图片对应转化为YCrCb,根据补偿值从新调整
    权重,接着将图像转换会RGB图像。
    

    效果演示

      使用步骤:1、运行软件:./xxx ./res/dark.jpg ./res/lenoff.jpg ./res/1.jpg
                2、依次点击控件:darkcurrent lenrolloff process。
                3、最后效果如下:
       

    代码下载:http://download.csdn.net/detail/u011630458/8691453
  • 相关阅读:
    7.1类模板
    异质链表
    8.1多态性
    8.2虚函数
    error: C2664: “zajiao::zajiao(const zajiao &)”: 无法将参数 1 从“const char [12]”转换为“char *”
    #include <QPushButton>
    6.3多重继承
    华为集群后killsql命令和查看mr占用的磁盘空间
    linux的逻辑运算符
    test命令
  • 原文地址:https://www.cnblogs.com/whw19818/p/6228977.html
Copyright © 2020-2023  润新知