Vectorize Creating logical replacement along color channel

Question:

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.

Asked By: theastronomist

||

Answers:

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)

Another solution that is similar in efficiency but slightly less efficient than the accepted solution (@Damian S.).

r = arr[:,:,0]
g = arr[:,:,1]
b = arr[:,:,2]

mask=(r+g+b>=744) & (np.maximum.reduce([r,g,b])-np.minimum.reduce([r,g,b]) <= 2)
arr[mask]=255

I compared the efficiency of this solution on arrays of 1000x1000x3 and the accepted one with 1,000 iterations and averaging the time to complete:

@Damian: Average: 0.0081s
My answer: Average: 0.0117

Answered By: theastronomist
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.