Search code examples
pythonnumpyalpha-transparency

Vectorize Creating logical replacement along color channel


I have an image with a subject and a mostly white background. I am trying to create an alpha mask around the subject. Due to image compression artifacts, the white background is not entirely made up of (255,255,255) values for rgb values. I am trying to convert values such as (252,253,252) to (255,255,255).

My logic is as follows:

  • If rgb values are within 2 of each other
  • If minimum rgb value is greater than 244
  • Then set those rgb values to (255,255,255)

Here is my inefficient code

image = cv2.imread('image.png') #400,400,3 in shape
for c_idx, column in enumerate(image):
    for r_idx, row in enumerate(column):
        if min(row) > 244 and max(row)-min(row)<=2:
            image[c_idx, r_idx] = [255,255,255]

I've attempted to make it more efficient by vectorizing with np.where. I've gotten it to check for the second condition but not the first condition.

image = cv2.imread('image.png') #400,400,3 in shape
image2 = np.where(image>=244), 255, image)

I have used this algorithm, but the blending doesn't bring values down all of the way and I end up with integer overflows on the edges of the subject.


Solution

  • I think this ought to work

    MAX_DIFF = 2
    pxl_min = image.min(axis=0)
    pxl_range = image.max(axis=0) - image.min(axis=0)
    img2 = np.where(((pxl_min >= 244) & (pxl_range <= MAX_DIFF)), 255, image)