NumPy 的 uint8 像素包装解决方案

38

我正在参加一门图像处理课程,对灰度图像进行点操作。像素值是uint8类型的,取值范围为[0,255]。

使用numpy的uint8时,会发生数值溢出。例如,235+30=9。我需要将像素饱和到最大值255或截断到最小值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


在使用MNIST数据集时,我的结果为.png图像显示出了奇怪的方形伪影,而不是实际的手写数字。问题还在于dtype int32。在使用了接受的答案中的numpy.clipastype()转换后,一切都正常了。 - JohnDizzle
3个回答

43

使用numpy.clip函数:

import numpy as np
np.clip(data32, 0, 255, out=data32)
data_u8 = data32.astype('uint8')
请注意,您也可以通过以下方式在不使用numpy的情况下使图像变亮:
import ImageEnhance
enhancer = ImageEnhance.Brightness(img)
outimg = enhancer.enhance(1.2)
outimg.save('out.png')

1
np.clip()正是我一直需要的。谢谢!我也会研究ImageEnhance。作业是关于自己进行点操作,但学习其他方法也是好的。 - David Poole

7
你可以使用OpenCV的addsubtract函数(额外的解释在这里)。
>>> 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)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接