2011-09-25 119 views
20

對於圖像處理類,我在單色圖像上進行點操作。像素是uint8 [0,255]。numpy uint8像素環繞解決方案

numpy uint8將包裝。例如,235 + 30 = 9。我需要像素飽和(max = 255)或截斷(min = 0)而不是纏繞。

我的解決方案使用int32像素點數學然後轉換爲uint8保存圖像。

這是最好的方法嗎?還是有更快的方法?

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

輸入圖像:
Riemann

輸出圖像:
Output

回答

27

使用numpy.clip

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

請注意,您也可以使用這種方式使圖像變亮而不出現顛簸:

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

np.clip()正是我一直需要。謝謝! 我也會閱讀ImageEnhance。作業是要自己做點操作,但是學習其他方法會很好。 –

1

基本上,它歸結爲添加之前的檢查。例如,你可以定義一個函數是這樣的:

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

您可以使用OpenCV的addsubtract功能(補充說明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! 

不幸的是,這是不可能使用索引爲輸出陣列,對於每個圖像通道,以便就地計算可以在此進行,效率較低,方式:

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