2011-09-25 10 views
20

Per una classe di elaborazione immagine, eseguo operazioni punto su immagini monocromatiche. I pixel sono uint8 [0,255].numpy soluzione di avvolgimento pixel uint8

numpy uint8 verrà completato. Ad esempio, 235 + 30 = 9. Ho bisogno dei pixel per saturare (max = 255) o troncare (min = 0) invece di avvolgere.

La mia soluzione utilizza int32 pixel per il punto matematico, quindi converte in uint8 per salvare l'immagine.

È questo il modo migliore? O c'è un modo più veloce? immagine

#!/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") 

ingresso: immagine
Riemann

uscita:
Output

risposta

27

Uso numpy.clip:

import numpy as np 
np.clip(data32, 0, 255, out=data32) 
data_u8 = data32.astype('uint8') 

Si noti che è anche possibile illuminare le immagini senza NumPy questo modo:

Import ImageEnhance 
enhancer=ImageEnhance.Brightness(img) 
outimg=enhancer.enhance(1.2) 
outimg.save('out.png') 
+0

np.clip() è esattamente quello che ho avuto bisogno. Grazie! Mi leggerò anche su ImageEnhance. I compiti riguardavano il fare noi stessi, ma sarebbe bello imparare altri modi. –

1

In sostanza, si tratta di controllare prima di aggiungere. Per esempio, è possibile definire una funzione come questa:

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 
3

È possibile utilizzare OpenCV add o subtract funzioni (spiegazione aggiuntiva here).

>>> 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! 

Purtroppo è impossibile utilizzare gli indici di matrice di uscita, calcoli in modo inplace per ciascun canale dell'immagine possono essere eseguite in questo, meno efficiente, così:

arr[..., channel] = cv2.add(arr[..., channel], 40)