简体   繁体   中英

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++. (I just run the HDR Tutorial )

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.

The exposures images were taken from Wikipedia: 1/30 sec , 1/4 sec , 2.5 sec , 15 sec .

The Python code:

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:

在此处输入图片说明

The result I get in C++:

在此处输入图片说明

What happens here is caused by 8 bit overflow and underflow for some of the R, G, B subpixels. 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.

np.uint8 will truncate the results, and keep only the least significant 8 bits, so for example:

  • a value of -2 will be stored as 254

  • a value of 257 will be stored as 1

This can be solved by clipping the results in the range [0 .. 255] , replacing

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. It would be the same as it is done in the provided C++ example. 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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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