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
When I transform the array into an image and look at it, the image, that have been inverted by first method, has better quality then inverted by second one. And I cannot understand why. Can you help me?
One bug to look out for performing both methods on the same data
object. However, I've tried your methods on my own images, and the results were incorrect.
You can fix the behavior in method two by rephrasing the calculation to 255 - data[:,:,:3]
. This solution assumes that your images have a max values of (255, 255, 255) for (R,G,B).
# old method
data[:,:,:3] = np.abs(data[:,:,:3] - 255)
# new method
data[:,:,:3] = 255 - data[:,:,:3]
You can verify this method by running the code
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))
If you want to understand why the code is behaving this way, it's because your code data_origin
array is datatype np.uint8
. uint8
is an unsigned integer with 8 bits meaning it can only be values from [0,255]. Subtracting a uint8 by 255 doesn't result in a negative number, but an overflow of x - 255.
For example,
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)
Even though np.abs(data[:,:,:3] - 255)
should behave like 255 - data[:,:,:3]
(because f(x) = abs(x-255)
equals f(x) = 255 -x
for domain in range [0, 255]), the datatype makes this conversion incorrect.
Another fix to this code would be to replace dtype='uint8'
to dtype='int32'
(because int32 allows for negative values). However, I don't recommend this solution because int32 is much larger than uint8.