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

简介

  在接触过的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!!!!!!\n");
        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!!!!!!\n");
        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
时间: 2024-11-04 07:35:24

opencv实现camera模组的暗电流和lenshading补偿的相关文章

android camera(一):camera模组CMM介绍【转】

转自:http://blog.csdn.net/xubin341719/article/details/7723725 版权声明:本文为博主原创文章,未经博主允许不得转载. 关键词:android  camera CMM 模组 camera参数 平台信息: 内核:linux 系统:android 平台:S5PV310(samsung exynos 4210)  作者:xubin341719(欢迎转载,请注明作者) 下载:常用摄像头规格书(个别有android驱动程序)  :bf3703 30W.

android camera(一):camera模组CMM介绍

一.摄像头模组(CCM)介绍: 1.camera特写 摄像头模组,全称CameraCompact Module,以下简写为CCM,是影像捕捉至关重要的电子器件.先来张特写,各种样子的都有,不过我前一段时间调试那个有点丑. 2.摄像头工作原理.camera的组成各组件的作用 想完全的去理解,还得去深入,如果是代码我们就逐步分析,模组的话我们就把它分解开来,看他到底是怎么工作的.看下它是有那些部分构成的,如下图所示: (1).工作原理:物体通过镜头(lens)聚集的光,通过CMOS或CCD集成电路,

MTK 平台上查询当前使用的摄像头模组及所支持预览分辨率

1,MTK 平台如何查询当前使用的是哪颗摄像头及相关的模组信息? 在该目录下可以查到当前平台及相关项目的配置文件 ProjectConfig.mk \ALPS.JB.MP.V1_W_20120919\mediatek\config\project**\ 该文件中配置了当前项目中使用的硬件芯片等信息 //如这个是指收音机所使用的芯片信息 CUSTOM_HAL_FMRADIO = mt6628 //下面这个是指当前项目所采用的 ROM 芯片CUSTOM_HAL_EEPROM=IMX111OTP_EE

mycncart操作使用教程 - 品牌展示模组

许多朋友对于[品牌展示]模组中的相关图片是从哪里设置的不知道. 如要修改[品牌展示模组]中的图片,路径为:[系统设置]->[规划设计]->[横幅广告],默认mycncart系统中有[品牌制造商],可以编辑它以替换图片.

020# Adempiere的会计功能模组(一)

在Adempiere系统中会计和生产是它的核心部分,其中会计贯彻了整个ERP系统,构建起环环相扣.处处相连的商业管理模型.将系统的各个功能模组诸如:业务伙伴.系统银行账户.现金账户.物料产品价格.工程项目.进销存管理.生产管理等等错综复杂的紧密联系在一起,最后进入系统总账. 一.Adempiere系统所走的会计规则是"国际会计规则(GAAP)",国际会计规则标准编码如下: 二.AD系统依照国际会计编码设置会计科目分类(会计元素),资产1.负债2.权益3.收入4..... 1.资产科目编

AP_应付模组在月结的处理

2014-06-04 BaoXinjian 1. 完成所有交易及检查Interface     (1). Invoice and Credits     (2). Prepayments     (3). Expense Report     (4). Invoice Import      (5). Payments 2. 核准所有的应付帐款立帐(Invoices)及确认(Confirm)所有的批次付款     Program: Payables Approve 3. 若有应付远期票据,且已到

『TensorFlow』徒手装高达_初号机_添加训练模组并整合为可用分类网络

摘要: 本次整合了前面两节的模组,并添加向前传播&反馈训练部分,使之成为一个包含训练&验证&测试的分类网络. 文件架构: 代码整合: image_info.py,图片读取部分 1 import glob 2 import os.path 3 import random 4 import numpy as np 5 import tensorflow as tf 6 7 def creat_image_lists(validation_percentage,testing_perce

Pyhon学习笔记3:模组(引用第三方模块)

模组更通俗的讲叫类库或者模块,在实际开发中,会使用到系统的标准模块或者第三方模块.例如,与时间有关的是系统的time块,文件操作相关的是os模块,使用selenium实现的web自动化测试,使用的是selenium扩展块. 引用模块:import  ... from .. import... 举例:输出系统时间 import time print(time.ctime()) 结果: ======================= RESTART: D:/selenium/test/5.py ==

关于模组电源

模组电源 所谓模组化电源,是指某个电源包含若干具有独立供电功用的模组单元 对于台式PC电源,称之为模组电源,只能是因为其具有电源线模块 背景 随着IT软硬件的升级,大部分主流电源标配 1个20+4pin主电源接口 4+4pin CPU +12V供电接口 1个6pin PCI-E +12V供电接口 3个4pin D型接口 1个软驱供电接口 4个SATA硬盘供电接口 已经不能满足正常需要 如果将如此多的接口线,整个直连到电源上的话,会非常紊乱 因此,把基础的接口线直连到电源上,其余的接口线通过模组的