使用 'abs' 和 numpy 反转图像

inverting an image with 'abs' and numpy

img = Image.open(path)
data_origin = np.asarray( img, dtype='uint8' )
data = np.array(data_origin) # 300 x 300 x 4

1)for i in range(data.shape[0]): # invert colors
    for j in range(data.shape[1]):
        for k in range(3): # only first three dims r g b
            data[i,j,k] = abs(data[i,j,k] - 255)

2)data[:,:,:3] = np.abs(data[:,:,:3] - 255) # why does it work worse?
''''
applying max pooling
...
end

当我将数组转换成图像并查看它时,用第一种方法反转的图像比用第二种方法反转的图像质量更好。我不明白为什么。你能帮帮我吗?

first method

second method

在同一 data 对象上执行这两种方法时需要注意一个错误。但是,我已经在自己的图像上尝试了您的方法,但结果不正确。

您可以修复方法二中的行为,方法是将计算改写为255 - data[:,:,:3]。此解决方案假定您的图像 (R,G,B) 的最大值为 (255, 255, 255)。

# old method
data[:,:,:3] = np.abs(data[:,:,:3] - 255) 

# new method
data[:,:,:3] = 255 - data[:,:,:3]

您可以通过运行代码验证此方法

img = Image.open(path)
data = np.asarray(img, dtype='uint8' )
experiment_1 = np.copy(data)
experiment_2 = np.copy(data)

# Perform method 1 on experiment_1
# ...
# Perform method 2 on experiment_2
# ...

print(np.all(experiment_1 == experiment_2))

如果您想了解 为什么 代码会这样,那是因为您的代码 data_origin 数组的数据类型是 np.uint8uint8 is an unsigned integer with 8 bits 意味着它只能是 [0,255] 中的值。将 uint8 减去 255 不会得到负数,而是 x - 255 的溢出。

例如,

a = np.array([10, 100, 125, 250], dtype='uint8')
print(a - 255) # incorrect
>> array([ 11, 101, 126, 251], dtype=uint8)

print(255 - a) # correct
>> array([245, 155, 130,   5], dtype=uint8)

即使 np.abs(data[:,:,:3] - 255) 应该表现得像 255 - data[:,:,:3](因为 f(x) = abs(x-255) 等于 f(x) = 255 -x 范围 [0, 255] 中的域),数据类型使此转换不正确.

此代码的另一个修复方法是将 dtype='uint8' 替换为 dtype='int32'(因为 int32 允许负值)。但是,我不推荐这种解决方案,因为 int32 比 uint8 大得多。