web-dev-qa-db-fra.com

Comment utiliser correctement `cv2.imshow` pour l'image flottante renvoyée par` cv2.distanceTransform`?

Il se passe quelque chose de bizarre avec cv2.imshow. J'écrivais un morceau de code et je me demandais pourquoi une de mes opérations ne fonctionnait pas (comme diagnostiqué en observant cv2.imshow). Exaspéré, j'ai fini par écrire la même image dans un fichier où elle avait l'air bien. Pourquoi cv2.imshow affiche-t-il une image binaire (première image ci-dessous) tandis que cv2.imwrite écrit l'image en niveaux de gris comme prévu (deuxième image)? Je n'ai jamais eu de problème avec l'affichage d'images en niveaux de gris auparavant!

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()

Voici l'image telle qu'elle est affichée par cv2.imshow: distanceTransform.png as displayed by cv2.imshow (also the same as the input image)

Voici l'image telle qu'elle est enregistrée par imwrite: distanceTransform.png as written by imwrite

7
vheissu

Lorsque vous utilisez cv2.imshow, tu devrais savoir:

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].

La fonction distaceTransform renvoie le type float. Ainsi, lorsque vous affichez directement la dist, il multiplie d'abord 255, puis mappe sur [0,255]. Donc, le résultat, tout comme l'image binaire. (0*255=>0, 1*255=>255, ...*255=>255).

Pour afficher correctement :

(1) vous pouvez découper la dist flottante en [0,255] et changer le type de données en np.uint8 par cv2.convertScaleAbs

dist1 = cv2.convertScaleAbs(dist)

(2) vous pouvez également normaliser dist flottant à [0,255] et modifier le type de données par cv2.normalize

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

Voici un exemple avec panda:

enter image description here

Le résultat:

enter image description here


Code complet:

#!/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()
14
Kinght 金