Search code examples
arraysnumpytuplesuniquewhere-clause

Find unique tuples inside a numpy array with np.where


I want to find unique color tuples inside a numpy array with np.where. My code so far is:

from __future__ import print_function
import numpy as np 

a = range(10)
b = range(10,20)
c = range(20,30)
d = np.array(zip(a, b, c))
print(d)
e = np.array(zip(c, b, a))
print(e)
search = np.array((1,11,21))
search2 = np.array((0,11,21))
print(search, search2)
f = np.where(d == search, d, e)
g = np.where(d == search2, d, e)
print(f)
print(g)

When I run the code it finds correctly the tuple search on the second position. But the tuple search2 is also found on the first position although it is not contained as unique tuple inside the array. How can I define in numpy that only unique tuples are to be found inside the array so it gives some for g the value

[[20 10  0]  [21 11  1]  [22 12  2]  
 [23 13  3]  [24 14  4]  [25 15  5]  
 [26 16  6]  [27 17  7]  [28 18  8]  [29 19  9]]

but still finds the unique tuple search and gives for f

[[20 10  0]  [ 1 11 21]  [22 12  2]  
 [23 13  3]  [24 14  4]  [25 15  5]  
 [26 16  6]   [27 17  7]  [28 18  8]  [29 19  9]]

?

EDIT:

OK, so the current problem is to write a GIF decoder in python. I have a previous frame called image_a and a following frame called image_b. image_b contains pixels with a certain transparency color tuple, called transp_color in this specific case for the uploaded images it is (0, 16, 8). The routine is supposed to replace all these entries with that color tuple with pixel values from image_a but leaving other pixels unchanged. My code is:

from __future__ import print_function
import numpy as np 
import cv2

image_a = cv2.imread("old_frame.png")
image_b = cv2.imread("new_frame.png")
cv2.imshow("image_a", image_a)
cv2.imshow("image_b", image_b)
transp_color = (0, 16, 8)
new_image = np.where(image_b == transp_color, image_a, image_b)
cv2.imshow("new_image", new_image)
cv2.waitKey()

old_frame.png new_frame.png new_image.png

Trying to solve this with np.where leads to wrong colors in the resulting image as seen above in the 3rd picture. So any idea how to solve this?


Solution

  • OK, finally found the solution myself, here is the code for doing it:

    import numpy as np
    import cv2
    
    image_a = cv2.imread("old_frame.png")
    image_b = cv2.imread("new_frame.png")
    cv2.imshow("image_a", image_a)
    cv2.imshow("image_b", image_b)
    transp_color = (0, 16, 8)[::-1]
    channels = 3
    f = np.all((image_b==transp_color), axis=-1)
    flattened_image = np.reshape(image_b, (image_b.shape[0]*image_b.shape[1], channels))
    old_flattened_image = np.reshape(image_a, (image_a.shape[0]*image_a.shape[1], channels))
    f = np.reshape(f, (image_a.shape[0]*image_a.shape[1], 1))
    np_image = np.array([old_flattened_image[i] if j else flattened_image[i] for i, j in enumerate(f)])
    new_image = np.reshape(np_image, (image_a.shape[0], image_a.shape[1], channels))
    
    # new_image = np.where(image_b == transp_color, image_a, image_b)
    
    cv2.imshow("new_image", new_image)
    cv2.waitKey()