Reputation: 67
I'm trying to unpremultiply my png image by accessing values via logical indexing. Made it work in python for loop before but I can't get it done right by using logical indexing. (for loop takes up to 1 minute)
Getting my image in numpy array
img = Image.open('test.png')
matrix = numpy.array(img)
Changing values using common for loops
for line in matrix:
for v in line:
if v[3]:
v[0] = (255 * v[0] + (v[3] / 2)) / v[3]
v[1] = (255 * v[1] + (v[3] / 2)) / v[3]
v[2] = (255 * v[2] + (v[3] / 2)) / v[3]
It ended up looking like this using logical indexing
height, width, depth = matrix.shape
r = matrix[0:height, 0:width//4, 0:1]
g = matrix[0:height, 0:width//4, 1:2]
b = matrix[0:height, 0:width//4, 2:3]
a = matrix[0:height, 0:width//4, 3:4]
matrix[0:height, 0:width//4, 0:1] = (255 * r + (a / 2)) / a
matrix[0:height, 0:width//4, 1:2] = (255 * g + (a / 2)) / a
matrix[0:height, 0:width//4, 2:3] = (255 * b + (a / 2)) / a
How do I change the desired values correctly? If there is a better than doing it with logical indexing, please enlighten me.
EDIT: Added example images
what it looks like with for loop (desired result)
what it looks like using indexing
Upvotes: 1
Views: 331
Reputation: 221614
Here's one approach -
matrix_out = matrix.astype(float)
vals = (255 * matrix_out[...,:3] + matrix_out[...,[3]]/2)/matrix_out[...,[3]]
mask = matrix[...,3]!=0
matrix[mask,:3] = vals[mask]
Thus, the updated values would be in matrix
.
Upvotes: 1
Reputation: 9820
If I understand your problem correctly, this should do the job:
r = matrix[:,:,0]
g = matrix[:,:,1]
b = matrix[:,:,2]
a = matrix[:,:,3]
r[a>0] = ((255*r + (a/2))/a)[a>0]
g[a>0] = ((255*g + (a/2))/a)[a>0]
b[a>0] = ((255*b + (a/2))/a)[a>0]
EDIT:
This must be because of the dtype
of your matrix. If you first change your matrix to float
values, it should work:
matrix2 = matrix.astype(np.float)
r = matrix2[:,:,0]
g = matrix2[:,:,1]
b = matrix2[:,:,2]
a = matrix2[:,:,3]
r[a>0] = ((255*r + (a/2))/a)[a>0]
g[a>0] = ((255*g + (a/2))/a)[a>0]
b[a>0] = ((255*b + (a/2))/a)[a>0]
matrix_out = matrix2.astype(np.uint8)
The final result can then be found in matrix_out
.
Upvotes: 1