我想写一个纯Numpy函数来改变RGB图像的对比度(表示为Numpy uint8数组),但是,我写的函数不起作用,我不明白为什么。
以下是一个示例图片:
这是一个使用PIL并且工作正常的函数:
def change_contrast(img, factor):
def contrast(pixel):
return 128 + factor * (pixel - 128)
return img.point(contrast)
from PIL import Image
img = Image.fromarray(img.astype(np.uint8))
img1 = change_contrast(img, factor=2.0)
输出:
现在这里是一个纯粹的Numpy函数,在我看来,它与上面的其他函数完全相同,但它根本不起作用:
def change_contrast2(img, factor):
return 128 + factor * (img - 128)
img1 = change_contrast2(img, factor=2.0)
其中img
是Numpy数组。输出是这样的:
我不明白发生了什么,并且会对任何提示感到高兴!
答案 0 :(得分:4)
你看到的是无符号整数的下溢:
>>> a = np.array((64, 128, 192), dtype=np.uint8)
>>> a
array([ 64, 128, 192], dtype=uint8)
>>> a-128
array([192, 0, 64], dtype=uint8) # note the "wrong" value at pos 0
避免这种情况的一种方法是强制或类型促销:
factor = float(factor)
np.clip(128 + factor * img - factor * 128, 0, 255).astype(np.uint8)
因为因子是浮点数,产品factor * img
的dtype会被提升为浮点数。由于浮点数可以处理负数,因此可以消除下溢。
为了能够转换回uint8
,我们剪辑到此类型可以表示的范围。
答案 1 :(得分:1)
试试这个,创建类型为int32的numpy数组并进行对比操作。然后在绘制图像之前使用以下函数将其转换为uint8。正如保罗在评论中提到的那样,问题在于numpy正在包含过度/下溢。
def as_uint8(img) :
latch = np.zeros_like(img)
latch[:] = 255
zeros = np.zeros_like(img)
d = np.maximum(zeros, img)
d = np.minimum(latch, d)
return np.asarray(d, dtype='uint8')
这可能是一种更有效的方法,但它确实有效。