Как правильно использовать `cv2.imshow` для изображения с плавающей точкой, возвращаемого`cv2.distanceTransform`?

Что-то странное происходит с cv2.imshow. Я писал фрагмент кода и удивлялся, почему одна из моих операций не работала (что было выявлено при наблюдении cv2.imshow). В раздражении я записал то же самое изображение в файл, в котором оно выглядит хорошо. Почему cv2.imshow показывает двоичное изображение (первое изображение ниже), а cv2.imwrite записывает изображение в градациях серого как задумано (второе изображение)? У меня никогда не было проблем с отображением изображений в градациях серого!

cv2.imshow('Latest', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

distTransform = cv2.distanceTransform(src=image,distanceType=cv2.DIST_L2,maskSize=5)
cv2.imwrite('distanceTransform.png', distTransform)

cv2.imshow('Latest', distTransform)
cv2.waitKey(0)
cv2.destroyAllWindows()

Это изображение, отображаемое cv2.imshow: distanceTransform.png как показано cv2.imshow (также как и входное изображение

Это изображение в том виде, в котором оно было сохранено с помощью imwrite: distanceTransform.png как написано imwrite

1 ответ

Решение

При использовании cv2.imshow, ты должен знать:

imshow(winname, mat) -> None
. The function may scale the image, depending on its depth:
. - If the image is 8-bit unsigned, it is displayed as is.
. - If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. 
    That is, the value range [0,255\*256] is mapped to [0,255].
. - If the image is 32-bit or 64-bit floating-point, the pixel values are multiplied by 255. That is, the
.   value range [0,1] is mapped to [0,255].

Функция distaceTransform тип возврата float, Поэтому, когда непосредственно отображается dist, сначала умножается на 255, а затем отображается на [0,255]. Так что результат так же, как двоичное изображение. (0*255=>0, 1*255=>255, ...*255=>255),

Для правильного отображения:

(1) вы можете обрезать float dist до [0,255] и изменить тип данных на np.uint8 от cv2.convertScaleAbs

dist1 = cv2.convertScaleAbs(dist)

(2) вы также можете нормализовать float dist до [0,255] и изменить тип данных на cv2.normalize

dist2 = cv2.normalize(dist, None, 255,0, cv2.NORM_MINMAX, cv2.CV_8UC1)

Вот пример с пандой:

введите описание изображения здесь

Результат:

введите описание изображения здесь


Полный код:

#!/ust/bin/python3
# 2018.01.19 10:24:58 CST
img = cv2.imread("panda.png", 0)
dist = cv2.distanceTransform(src=img,distanceType=cv2.DIST_L2,maskSize=5)
dist1 = cv2.convertScaleAbs(dist)
dist2 = cv2.normalize(dist, None, 255,0, cv2.NORM_MINMAX, cv2.CV_8UC1)

cv2.imshow("dist", dist)
cv2.imshow("dist1", dist1)
cv2.imshow("dist2", dist2)
cv2.waitKey()
Другие вопросы по тегам