OpenCV MergeMertens 在 Python Vs 中给出了不同的结果。 C++
OpenCV MergeMertens gives different results in Python Vs. C++
当我 运行 Python 中的 HDR Mertens 曝光融合时,我得到了奇怪的颜色伪像,当我 运行 在 c++ 中完全相同的函数时,我没有得到。 (我只是运行 HDR Tutorial)
在我看来,数据类型有问题,但我尝试了所有选项,但没有任何效果。我做错了什么吗?
我 运行宁 Python 3.5 64 位与 OpenCV 3.0.0。
曝光图片取自维基百科: 1/30 sec, 1/4 sec, 2.5 sec, 15 sec.
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++得到的结果:
这里发生的事情是由一些 R、G、B 子像素的 8 位上溢和下溢引起的。有的融合后在区间[0.0 .. 1.0]
之外,乘以255,结果为负数或大于255。
np.uint8
将截断结果,只保留最低有效的 8 位,例如:
-2
的值将存储为 254
257
的值将存储为 1
这可以通过裁剪 运行ge [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
替换了文件扩展名 - 大写,因为这是维基百科上的原始名称,我在 Linux 上 运行 这个文件名是区分大小写。)
当我 运行 Python 中的 HDR Mertens 曝光融合时,我得到了奇怪的颜色伪像,当我 运行 在 c++ 中完全相同的函数时,我没有得到。 (我只是运行 HDR Tutorial)
在我看来,数据类型有问题,但我尝试了所有选项,但没有任何效果。我做错了什么吗?
我 运行宁 Python 3.5 64 位与 OpenCV 3.0.0。
曝光图片取自维基百科: 1/30 sec, 1/4 sec, 2.5 sec, 15 sec.
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++得到的结果:
这里发生的事情是由一些 R、G、B 子像素的 8 位上溢和下溢引起的。有的融合后在区间[0.0 .. 1.0]
之外,乘以255,结果为负数或大于255。
np.uint8
将截断结果,只保留最低有效的 8 位,例如:
-2
的值将存储为254
257
的值将存储为1
这可以通过裁剪 运行ge [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
替换了文件扩展名 - 大写,因为这是维基百科上的原始名称,我在 Linux 上 运行 这个文件名是区分大小写。)