项目实训课程 第十周

  • HDR高动态范围图像处理
  • 完成UI界面

一、HDR原理

大多数数码相机和显示器都将彩色图像捕获或显示为24位矩阵。 每个颜色通道有8位,因此每个通道的像素值在0-255范围内。 换句话说,普通的相机或显示器的动态范围是有限的。但通过改变快门速度,我们可以在不同的曝光条件下拍摄多个场景图像,从而合成HDR图像。

HDR——即高动态范围图像(High-Dynamic Range,简称HDR),相比普通的图像,可以提供更多的动态范围和图像细节,根据不同的曝光时间的LDR(Low-Dynamic Range)图像,利用每个曝光时间相对应最佳细节的LDR图像来合成最终HDR图像,能够更好的反映出真实环境中的视觉效果。

简而言之,就是尽可能地同时显示一张图片最亮和最暗的地方。

二、代码实现

(一)从读取图像开始分配曝光时间

 # Read images and exposure times
    print("Reading images ... ")

    #需要小窗口输入数值
    times = np.array([1 / 30.0, 0.25, 2.5, 15.0], dtype=np.float32)

    filenames = ["img_0.033.jpg", "img_0.25.jpg", "img_2.5.jpg", "img_15.jpg"]
    images = []

    # for filename in filenames:
    #     im = cv2.imread(instance.root_path+'/part4/images_hdr/'+filename)
    #     images.append(im)

    im1=cv2.imread(instance.hdr1_original[0][0])
    images.append(im1)
    im2=cv2.imread(instance.hdr2_original[0][0])
    images.append(im2)
    im3=cv2.imread(instance.hdr3_original[0][0])
    images.append(im3)
    im4=cv2.imread(instance.hdr4_original[0][0])
    images.append(im4)
  • 曝光时间:1/30s
    在这里插入图片描述

  • 曝光时间:0.25s
    在这里插入图片描述

  • 曝光时间:2.5s
    在这里插入图片描述

  • 曝光时间:15s
    在这里插入图片描述

(二)图片对齐
构成HDR图像时使用的图像未对齐可能会导致严重的伪影。OpenCV提供了一种使用AlignMTB对齐这些图像的简单方法。 该算法将所有图像转换为中值阈值位图(MTB)。 通过将值1分配给比中间亮度更亮的像素来计算图像的MTB,否则为0。

    # Align input images
    print("Aligning images ... ")
    alignMTB = cv2.createAlignMTB()
    alignMTB.process(images, images)

(三)估计相机响应函数
由于典型相机的响应与场景亮度不成线性关系,即曝光时间与像素强度并不构成对应的线性关系。 在不估计相机响应函数(CRF)的情况下,我们将无法将图像合并到一个HDR图像中。我们需要估计CRF来使图像强度成为线性的,然后才能合并它们。

通过每个图像的曝光时间,可以从图像估计CRF,找到CRF的问题被设置为一个优化问题,其目标是使由数据项和平滑项组成的目标函数最小化,可以使用奇异值分解(SVD)来解决,奇异值分解是所有线性代数包的一部分。

在OpenCV中使用CalibrateDebevec来完成CRF。

    # Obtain Camera Response Function (CRF)
    print("Calculating Camera Response Function (CRF) ... ")
    calibrateDebevec = cv2.createCalibrateDebevec()
    responseDebevec = calibrateDebevec.process(images, times)

(四)图片合成
使用MergeDebevec将曝光图像合并成一个HDR图像

    # Merge images into an HDR linear image
    print("Merging images into one HDR image ... ")
    mergeDebevec = cv2.createMergeDebevec()
    hdrDebevec = mergeDebevec.process(images, times, responseDebevec)
    # Save HDR image.
    cv2.imwrite("hdrDebevec.hdr", hdrDebevec)
    print("saved hdrDebevec.hdr ")

(五)色调映射
将高动态范围(HDR)图像转换为8位每通道图像的过程同时保留尽可能多的细节的过程称为色调映射。即在恢复了多个图像的相对亮度信息后,需要将这些信息保存为24位图像。

色调映射没有称之为正确的方法。通常,我们希望在色调映射图像中看到比任何一个曝光图像更多的细节。 有时色调映射的目标是产生逼真的图像,而且往往是产生超现实图像的目标。 在OpenCV中实现的算法倾向于产生现实的,因而较不显著的结果。

以下列出了不同色调映射算法的一些常见参数。
1、gamma:该参数通过应用gamma 校正来压缩动态范围。 当gamma等于1时,不应用修正。 小于1的gamma会使图像变暗,而大于1的gamma会使图像变亮。
2、饱和度:该参数用于增加或减少饱和度。 饱和度高时,色彩更丰富,更浓。 饱和度值接近零,使颜色逐渐消失为灰度。
3、对比度:控制输出图像的对比度(即log(maxPixelValue / minPixelValue))。

以下三种算法有不同的参数设置。

  • Durand Tonemap
createTonemapDurand 
(   
  float     gamma = 1.0f, 
  float     contrast = 4.0f,
  float     saturation = 1.0f,
  float     sigma_space = 2.0f,
  float     sigma_color = 2.0f 
); 

在这里插入图片描述

  • Reinhard Tonemap
createTonemapReinhard
(
float   gamma = 1.0f,
float   intensity = 0.0f,
float   light_adapt = 1.0f,
float   color_adapt = 0.0f 
)   

在这里插入图片描述

  • Mantiuk Tonemap
createTonemapMantiuk
(   
float   gamma = 1.0f,
float   scale = 0.7f,
float   saturation = 1.0f 
)   

在这里插入图片描述

代码如下:

 # Tonemap using Drago's method to obtain 24-bit color image
    print("Tonemaping using Drago's method ... ")
    tonemapDrago = cv2.createTonemapDrago(1.0, 0.7)
    ldrDrago = tonemapDrago.process(hdrDebevec)
    ldrDrago = 3 * ldrDrago
    cv2.imwrite(instance.root_path+'/part4/images_hdr/'+"ldr-Drago.jpg", ldrDrago * 255)
    print("saved ldr-Drago.jpg")


    # Tonemap using Reinhard's method to obtain 24-bit color image
    print("Tonemaping using Reinhard's method ... ")
    tonemapReinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
    ldrReinhard = tonemapReinhard.process(hdrDebevec)
    cv2.imwrite(instance.root_path+'/part4/images_hdr/'+"ldr-Reinhard.jpg", ldrReinhard * 255)
    print("saved ldr-Reinhard.jpg")

    # Tonemap using Mantiuk's method to obtain 24-bit color image
    print("Tonemaping using Mantiuk's method ... ")
    tonemapMantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
    ldrMantiuk = tonemapMantiuk.process(hdrDebevec)
    ldrMantiuk = 3 * ldrMantiuk
    cv2.imwrite(instance.root_path+'/part4/images_hdr/'+"ldr-Mantiuk.jpg", ldrMantiuk * 255)
    print("saved ldr-Mantiuk.jpg")

三、完成UI界面

# 原图图片路径——HDR——选择第一张图
    instance.hdr1_img=""
    instance_button_choose_original_image=QPushButton("选择原图一",instance.widget_hdr)
    instance_button_choose_original_image.setGeometry(30,10,100,50)
    instance_button_choose_original_image.clicked.connect(instance.open_file_and_change_name_hdr1)

    # 用于显示路径名的label
    instance.label_hdr1_original = QLabel(instance.widget_hdr)
    instance.label_hdr1_original.setGeometry(30,120,500,50)
    instance.label_hdr1_original.setText("文件路径1")

    # 原图图片路径——HDR——选择第二张图
    instance.hdr2_img=""
    instance_button_choose_original_image=QPushButton("选择原图二",instance.widget_hdr)
    instance_button_choose_original_image.setGeometry(150,10,100,50)
    instance_button_choose_original_image.clicked.connect(instance.open_file_and_change_name_hdr2)

    # 用于显示路径名的label
    instance.label_hdr2_original = QLabel(instance.widget_hdr)
    instance.label_hdr2_original.setGeometry(30,180,500,50)
    instance.label_hdr2_original.setText("文件路径2")

    # 原图图片路径——HDR——选择第三张图
    instance.hdr3_img=""
    instance_button_choose_original_image=QPushButton("选择原图三",instance.widget_hdr)
    instance_button_choose_original_image.setGeometry(270,10,100,50)
    instance_button_choose_original_image.clicked.connect(instance.open_file_and_change_name_hdr3)

    # 用于显示路径名的label
    instance.label_hdr3_original = QLabel(instance.widget_hdr)
    instance.label_hdr3_original.setGeometry(30,240,500,50)
    instance.label_hdr3_original.setText("文件路径3")

    # 原图图片路径——HDR——选择第四张图
    instance.hdr4_img=""
    instance_button_choose_original_image=QPushButton("选择原图四",instance.widget_hdr)
    instance_button_choose_original_image.setGeometry(390,10,100,50)
    instance_button_choose_original_image.clicked.connect(instance.open_file_and_change_name_hdr4)

    # 用于显示路径名的label
    instance.label_hdr4_original = QLabel(instance.widget_hdr)
    instance.label_hdr4_original.setGeometry(30,300,500,50)
    instance.label_hdr4_original.setText("文件路径4")


在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值