2

当我在 Python 中运行 HDR Mertens 曝光融合时,我得到了奇怪的颜色伪影,当我在 c++ 中运行完全相同的函数时,我没有得到。(我只是运行HDR 教程

在我看来,数据类型存在一些问题,但我尝试了所有选项,但没有任何效果。难道我做错了什么?

我正在使用 OpenCV 3.0.0 运行 Python 3.5 64 位。

曝光图像取自维基百科: 1/30 秒1/4 秒2.5 秒15 秒

Python代码:

import cv2
import numpy as np

img_fn = ["640px-StLouisArchMultExpEV+4.09.jpg",
          "640px-StLouisArchMultExpEV+1.51.jpg",
          "640px-StLouisArchMultExpEV-1.82.jpg",
          "640px-StLouisArchMultExpEV-4.72.jpg"]
img_list = [cv2.imread(fn) for fn in img_fn]

# Exposure fusion using Mertens
mergeMertens = cv2.createMergeMertens()
resFusion = mergeMertens.process(img_list)

# Convert datatype to 8-bit and save
resFusion_8bit = np.uint8(resFusion*255)
cv2.imwrite("fusion.png", resFusion_8bit)

我在 Python 中得到的结果:

在此处输入图像描述

我在 C++ 中得到的结果:

在此处输入图像描述

4

1 回答 1

3

这里发生的情况是由某些 R、G、B 子像素的 8 位上溢和下溢引起的。[0.0 .. 1.0] 其中一些在融合后的区间之外,乘以255,结果为负数或大于255。

np.uint8将截断结果,并仅保留最低有效 8 位,例如:

  • 的值-2将存储为254

  • 的值257将存储为1

这可以通过裁剪范围内的结果来解决[0 .. 255],替换

resFusion_8bit = np.uint8(resFusion*255)

np.clip(resFusion*255, 0, 255, out=resFusion)
resFusion_8bit = resFusion.astype('uint8')

或者,可以直接将乘以 255 的值传递给imwrite,而无需先将它们转换为uint8,它会处理裁剪。这与在提供的 C++ 示例中所做的相同。因此,脚本可以重写为:

import cv2

img_fn = ["640px-StLouisArchMultExpEV+4.09.JPG",
          "640px-StLouisArchMultExpEV+1.51.JPG",
          "640px-StLouisArchMultExpEV-1.82.JPG",
          "640px-StLouisArchMultExpEV-4.72.JPG"]
img_list = [cv2.imread(fn) for fn in img_fn]

# Exposure fusion using Mertens
mergeMertens = cv2.createMergeMertens()
resFusion = mergeMertens.process(img_list)

# Save
cv2.imwrite("fusion.png", resFusion*255)

(请注意,我将文件扩展名替换为.JPG- 大写,因为这是 Wikipedia 上的原始名称,并且我在 Linux 上运行过它,其中文件名区分大小写。)

于 2015-12-06T13:00:24.167 回答