简体   繁体   English

OpenCV MergeMertens在Python Vs中给出不同的结果。 C ++

[英]OpenCV MergeMertens gives different results in Python Vs. C++

When I run the HDR Mertens exposure fusion in Python I get weird colors artifact, that I don't get when I run the exact same function in c++. 当我在Python中运行HDR Mertens曝光融合时,我得到了奇怪的颜色伪影,而在c ++中运行完全相同的函数却没有。 (I just run the HDR Tutorial ) (我只是运行HDR教程

Seems to me like some problem with the data types, but I tried every option and nothing works. 在我看来,数据类型有些问题,但是我尝试了所有选项,但没有任何效果。 Am I doing something wrong? 难道我做错了什么?

I'm running Python 3.5 64-bit with OpenCV 3.0.0. 我正在运行带有OpenCV 3.0.0的Python 3.5 64位。

The exposures images were taken from Wikipedia: 1/30 sec , 1/4 sec , 2.5 sec , 15 sec . 曝光图像来自Wikipedia: 1/30秒1/4秒2.5秒15秒

The Python code: 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)

The result I get in Python: 我在Python中得到的结果:

在此处输入图片说明

The result I get in C++: 我在C ++中得到的结果:

在此处输入图片说明

What happens here is caused by 8 bit overflow and underflow for some of the R, G, B subpixels. 这里发生的是由某些R,G,B子像素的8位上溢和下溢引起的。 Some of them are outside of the interval [0.0 .. 1.0] after the fusion, and when multiplied with 255, the result will be negative or above 255. 其中一些超出融合后的间隔[0.0 .. 1.0] ,并且与255相乘时,结果将为负或大于255。

np.uint8 will truncate the results, and keep only the least significant 8 bits, so for example: np.uint8将截断结果,并仅保留最低有效8位,因此例如:

  • a value of -2 will be stored as 254 -2将存储为254

  • a value of 257 will be stored as 1 257将被存储为1

This can be solved by clipping the results in the range [0 .. 255] , replacing 这可以通过将结果剪切到[0 .. 255]范围内,替换为

resFusion_8bit = np.uint8(resFusion*255)

with

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

Or, it is possible to pass directly the values multiplied with 255 to imwrite , without converting them first to uint8 and it will take care of the clipping. 或者,可以直接将乘以255的值传递给imwrite ,而无需先将它们转换为uint8 ,这样就可以处理剪切。 It would be the same as it is done in the provided C++ example. 与提供的C ++示例中的操作相同。 So, the script can be rewritten as: 因此,脚本可以重写为:

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)

(Note that I replaced the file extensions with .JPG - uppercase, as this is the original name on Wikipedia and I've ran this on Linux, where filenames are case sensitive.) (请注意,我用.JPG替换了文件扩展名-大写,因为这是Wikipedia的原始名称,并且我已经在Linux上运行了此扩展名,文件名区分大小写。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM