2015-12-06 1 views
2

Когда я запускаю HDR Mertens fusion в Python, я получаю странный цветной артефакт, который я не получаю, когда я запускаю ту же самую функцию в C++. (Я просто запустил HDR Tutorial)OpenCV MergeMertens дает разные результаты в Python Vs. C++

Мне кажется, что некоторые проблемы с типами данных, но я пробовал каждый вариант и ничего не работает. Я делаю что-то неправильно?

Я запускаю Python 3.5 64-bit с OpenCV 3.0.0.

экспозиции изображения были взяты из Википедии:1/30 sec, 1/4 sec, 2.5 sec, 15 sec. Код

Питон:

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:

enter image description here

В результате я получаю в C++:

enter image description here

ответ

3

Что происходит здесь, вызвано 8-разрядным переполнением и недостаточным потоком для некоторых субпикселей R, G, B. Некоторые из них находятся за пределами интервала [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 - заглавными буквами, так как это первоначальное название в Википедии, и я побежал это на Linux, где Имена файлов чувствительный.)