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.