camera HDR 拍照模式的原理,实现及应用

https://blog.csdn.net/qq160816/article/details/50789802

camera HDR 拍照:
        (High Dynamic Range Imaging)高动态范围成像

1. what:

用来实现比普通数字图像技术更大曝光动态范围(即更大的明暗差别)的一组技术。

2. 原理:

相比普通的图像,可以提供更多的动态范围和图像细节,根据不同的曝光时间的LDR(Low-Dynamic Range)图像,利用每个曝光时间相对应最佳细节的LDR图像来合成最终HDR图像。 

3. 目的:

正确地表示真实世界中从太阳光直射到最暗的阴影这样大的范围亮度,现在一般的数码相机和手机中都实现这种拍照模式。

4.适合场景:
        比较适合在阴暗变化明显的场景下使用,这样能使明处的景物不致过曝,而使得暗处的景物不致欠曝。譬如逆光环境下拍人物,可以将人物和环境都能拍清晰。
或者说能将处在暗处的景物拍摄出来的细节表现得更加充分!


下面来看几组照片:

                          图1

如上图1中所示,开启 HDR 后,暗处的树和墙壁都获得正确的曝光,都能看得清楚。

 

                                                 图2

  

                            图3

如上图3中开启了 HDR, 左上角及楼道里的场景能拍得更亮一些。图片均来自网络!

 

具体实现方法:

        其实现方法是通过设三组 ev 值来对当前拍摄的景物曝光,一张照片是使用当前测光从而算出来的正常情况下的ev值曝光,另外两张则分别使用其0.5倍的ev值和2倍的ev值进行曝光。最终对三张照片按某种算法进行合成,暗处的景物使用2倍ev曝光的局部照片,而亮处的物体则使用0.5倍ev曝光的局部照片。这样就能使得整个照片的场景都不致于太亮或太暗。

 

代码实现:
在 xxx\ALPS.JB3.TDD.MP.V2_TD_xxx\mediatek\custom\common\kernel\imgsensor\ov5645_mipi_yuv\ov5645mipiyuv_Sensor.c 驱动文件中有这样一个函数

 

BOOL OV5645MIPI_set_param_exposure_for_HDR(UINT16 para)  
{  
    kal_uint32 totalGain = 0, exposureTime = 0;  
    OV5645MIPISENSORDB("[OV5645MIPI]enter OV5645MIPI_set_param_exposure_for_HDR function:\n ");  
    OV5645MIPISENSORDB("[OV5645MIPI]enter para=%d,manualAEStart%d\n",para,OV5645MIPISensor.manualAEStart);  
    if (0 == OV5645MIPISensor.manualAEStart)  
    {         
        OV5645MIPI_set_AE_mode(KAL_FALSE);//Manual AE enable  
        spin_lock(&ov5645mipi_drv_lock);      
        OV5645MIPISensor.manualAEStart = 1;  
        spin_unlock(&ov5645mipi_drv_lock);  
    }  
    totalGain = OV5645MIPISensor.currentAxDGain;  
    exposureTime = OV5645MIPISensor.currentExposureTime;  
    switch (para)  
    {  
       case AE_EV_COMP_20:  //+2 EV  
       case AE_EV_COMP_10:  // +1 EV  
           totalGain = totalGain<<1;  
           exposureTime = exposureTime<<1;  
           OV5645MIPISENSORDB("[4EC] HDR AE_EV_COMP_20\n");  
         break;  
       case AE_EV_COMP_00:  // +0 EV  
           OV5645MIPISENSORDB("[4EC] HDR AE_EV_COMP_00\n");  
         break;  
       case AE_EV_COMP_n10:  // -1 EV  
       case AE_EV_COMP_n20:  // -2 EV  
           totalGain = totalGain >> 1;  
           exposureTime = exposureTime >> 1;  
           OV5645MIPISENSORDB("[4EC] HDR AE_EV_COMP_n20\n");  
         break;  
       default:  
         break;//return FALSE;  
    }  
    totalGain = (totalGain > OV5645MIPI_MAX_AXD_GAIN) ? OV5645MIPI_MAX_AXD_GAIN : totalGain;  
    //exposureTime = (exposureTime > OV5645MIPI_MAX_EXPOSURE_TIME) ? OV5645MIPI_MAX_EXPOSURE_TIME : exposureTime;  
    OV5645MIPIWriteSensorGain(totalGain);     
    OV5645MIPIWriteShutter(exposureTime);     
    OV5645MIPISENSORDB("[OV5645MIPI]exit OV5645MIPI_set_param_exposure_for_HDR function:\n ");  
    return TRUE;  
}  

此函数会执行三次,分别跑了 AE_EV_COMP_00, AE_EV_COMP_20, AE_EV_COMP_n20 这三个 case, 这三个 case 中分别以三组 totalGain 和 exposureTime 值来进行曝光的。
可以看到这三组值所呈现的0.5,1,2倍的关系。

参考文档:
http://bbs.fengbao.com/thread-236103-1-1.html
注:此篇文章中将 HDR 拍摄技巧描述得很好,有需要的可以详细看下

 

 

tone mapping

一张HDR图片,它记录了远远超出256个级别的实际场景的亮度值,超出的部分在屏幕上是显示不出来的。所以线性解码,总是导致图像一部分区域过于明亮,或者另一部分过于暗淡。 


解决的方法就是tone mapping。这里我们将图像分解为两个层,一个基层(base layer or large-scale features)和一个细节层(detail layer)。只对基层进行对比度压缩,保持细节层不变。这里为将图像分解成两层,且保持边缘特性,就需要采取一些快速健壮的保边去噪的滤波器。比如说双边滤波(BF)等。
算法流程

根据《Fast Bilateral Filtering for the Display of High-Dynamic-Range Images 》给出了对比度缩减的流程:

input intensity= 1/61*(R*20+G*40+B)
r=R/(input intensity), g=G/input intensity, B=B/input intensity
log(base)=Bilateral(log(input intensity))
log(detail)=log(input intensity)-log(base)
log (output intensity)=log(base)*compressionfactor+log(detail) - log_absolute_scale
R output = r*10^(log(output intensity)), etc.
注:第一步是将原图像转换成其灰度图像,你可以使用其他你喜欢的转换公式。compressionfactor是对基层的压缩系数,log_absolute_scale是一个偏置参数,以确保基层压缩后最大像素值为1,这两个参数都与图像相关。这里作者建议取值 
compressionfactor = targetContrast/(max(log(base)) - min(log(base))),log_absolute_scale= max(log(base))*compressionfactor。
原文链接:https://blog.csdn.net/bluecol/article/details/45419817

你可能感兴趣的:(android,Camera)