solution d'emballage de pixels numpy uint8
Pour une classe de traitement d'image, je fais des opérations ponctuelles sur des images monochromes. Les Pixels sont uint8 [0,255].
Numpy uint8 va envelopper. Par exemple, 235+30 = 9. J'ai besoin des pixels pour saturer (max=255) ou tronquer (min=0) au lieu d'envelopper.
Ma solution utilise int32 pixels pour le calcul des points puis convertit en uint8 pour enregistrer l'image.
Est-ce la meilleure façon de faire? Ou est-il un moyen plus rapide?
#!/usr/bin/python
import sys
import numpy as np
import Image
def to_uint8( data ) :
# maximum pixel
latch = np.zeros_like( data )
latch[:] = 255
# minimum pixel
zeros = np.zeros_like( data )
# unrolled to illustrate steps
d = np.maximum( zeros, data )
d = np.minimum( latch, d )
# cast to uint8
return np.asarray( d, dtype="uint8" )
infilename=sys.argv[1]
img = Image.open(infilename)
data32 = np.asarray( img, dtype="int32")
data32 += 30
data_u8 = to_uint8( data32 )
outimg = Image.fromarray( data_u8, "L" )
outimg.save( "out.png" )
Image d'Entrée:
Sortie image:
3 réponses
Utilisez numpy.clip :
import numpy as np
np.clip(data32, 0, 255, out=data32)
data_u8 = data32.astype('uint8')
Notez que vous pouvez également égayer les images sans numpy de cette façon:
import ImageEnhance
enhancer = ImageEnhance.Brightness(img)
outimg = enhancer.enhance(1.2)
outimg.save('out.png')
Vous pouvez utiliser OpenCV add
ou subtract
fonctions supplémentaires (explication ici).
>>> import numpy as np
>>> import cv2
>>> arr = np.array([100, 250, 255], dtype=np.uint8)
>>> arr
Out[1]: array([100, 250, 255], dtype=uint8)
>>> cv2.add(arr, 10, arr) # Inplace
Out[2]: array([110, 255, 255], dtype=uint8) # Saturated!
>>> cv2.subtract(arr, 150, arr)
Out[3]: array([ 0, 105, 105], dtype=uint8) # Truncated!
Malheureusement, il est impossible d'utiliser des index pour le tableau de sortie, Donc les calculs inplace pour chaque canal d'image peuvent être effectués de cette manière, moins efficace:
arr[..., channel] = cv2.add(arr[..., channel], 40)
Fondamentalement, il s'agit de vérifier avant d'ajouter. Par exemple, vous pouvez définir une fonction comme ceci:
def clip_add(arr, amt):
if amt > 0:
cutoff = 255 - amt
arr[arr > cutoff] = 255
arr[arr <= cutoff] += amt
else:
cutoff = -amt
arr[arr < cutoff] = 0
arr[arr >= cutoff] += amt