web-dev-qa-db-fra.com

Conversion de np.array de type float64 en types de mise à l'échelle uint8

J'ai un np.array data qui représente une image particulière en niveaux de gris . Je dois utiliser SimpleBlobDetector () qui, malheureusement, n'accepte que les images 8 bits. .

J'ai déjà essayé:

import numpy as np
import cv2
[...]
data = data / data.max() #normalizes data in range 0 - 255
data = 255 * data
img = data.astype(np.uint8)
cv2.imshow("Window", img)

Mais cv2.imshow ne donne pas l'image comme prévu, mais avec une distorsion étrange ...

En fin de compte, il me suffit de convertir un fichier np.float64 en fichier np.uint8 en mettant à l'échelle toutes les valeurs et en tronquant le reste, par exemple. 65535 devient 255, 65534 devient 254 et ainsi de suite ... Une aide?

Merci.

7
decadenza

Une meilleure façon de normaliser votre image est de prendre chaque valeur et de la diviser par la plus grande valeur rencontrée par le type de données. Cela garantit que les images qui ont une petite plage dynamique dans votre image restent petites et ne sont pas normalisées par inadvertance de sorte qu'elles deviennent grises. Par exemple, si votre image avait une plage dynamique de [0-2], le code actuel l’intensifierait pour avoir des intensités de [0, 128, 255]. Vous voulez que ceux-ci restent petits après la conversion en np.uint8

Par conséquent, divisez chaque valeur par la valeur la plus grande possible par l'image type, et non par l'image elle-même. Vous devez ensuite redimensionner cette valeur de 255 pour obtenir le résultat normalisé. Utilisez numpy.iinfo et fournissez-lui le type (dtype) de l'image et vous obtiendrez une structure d'informations pour ce type. Vous accéderiez ensuite au champ max à partir de cette structure pour déterminer la valeur maximale. 

Donc, avec ce qui précède, apportez les modifications suivantes à votre code:

import numpy as np
import cv2
[...]
info = np.iinfo(data.dtype) # Get the information of the incoming image type
data = data.astype(np.float64) / info.max # normalize the data to 0 - 1
data = 255 * data # Now scale by 255
img = data.astype(np.uint8)
cv2.imshow("Window", img)

Notez que j'ai également converti l'image en np.float64 au cas où le type de données entrant ne le serait pas et pour conserver la précision en virgule flottante lors de la division.

14
rayryeng

vous pouvez utiliser skimage.img_as_ubyte(yourdata), votre tableau numérique sera compris entre 0 et 255

from skimage import img_as_ubyte

img = img_as_ubyte(data)
cv2.imshow("Window", img)
0
Ali Farouk