I try to replace the turquoise part (words) from the image with white background to have a clear source for tesseract-ocr. The picture is loaded ok, image mask is created ok. My question is how to calculate (bidwise_and/or/xor) the right way, to have the turquoise part replaced with white. My code replace best case the turquoise part with black. Any idea is welcome and thank you for looking into.
import cv2
import numpy as np
# Read image
image = cv2.imread('pic1.png')
# Show Image
cv2.imshow('Pic1', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Create white image
whtimg = np.zeros([image.shape[0],image.shape[1],image.shape[2]],dtype=np.uint8)
whtimg.fill(255)
# Convert to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
whtimg = cv2.cvtColor(whtimg, cv2.COLOR_BGR2HSV)
# Color Range - turquoise (color pick HSV: 165/77/87)
lower_color = np.array([int(165/360*255-100), int(77/100*255*0.1), int(87/100*255-10)])
upper_color = np.array([int(165/360*255+100), int(77/100*255*3.0) , int(87/100*255+10)])
# Create mask to only select white
mask1 = cv2.inRange(hsv, lower_color, upper_color)
# mask1 = 255 - mask1 # invert mask
# Show Mask
cv2.imshow('Mask', mask1)
cv2.waitKey(0)
cv2.destroyAllWindows()
# replace with white
res = cv2.bitwise_or(hsv,whtimg,mask=mask1) # or bitwise_and, bitwise_xor
# Convert to BGR
res = cv2.cvtColor(res, cv2.COLOR_HSV2BGR)
# Show Result
cv2.imshow('Result', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
Why not simply:
import cv2
import numpy as np
image_in = cv2.imread("pic1.png")
image_hsv = cv2.cvtColor(image_in, cv2.COLOR_BGR2HSV)
# make a condition where saturation is > 30
cond = image_hsv[:, :, 1] > 30
# and use it to replace colors in the original BGR image
image_in[cond] = (255, 255, 255)
There are still artifacts, but with the color ranges you used they seem to be even worse (see below). If, however, you insist on using those color ranges for reasons outside of the scope of this example, then:
import cv2
import numpy as np
image_in = cv2.imread("pic1.png")
image_hsv = cv2.cvtColor(image_in, cv2.COLOR_BGR2HSV)
lower_color = np.array([int(165/360*255-100), int(77/100*255*0.1), int(87/100*255-10)])
upper_color = np.array([int(165/360*255+100), int(77/100*255*3.0) , int(87/100*255+10)])
mask1 = cv2.inRange(image_hsv, lower_color, upper_color)
# replace the color in the original image
image_in[mask1 > 0] = (255, 255, 255)
If you really prefer bitwise operations (I'd imagine, they might be faster than conditionals under some... conditions, not sure about this particular case), then you can also apply them to the original image (as, I assume, @beaker was advising in his answer), but you would need to stack your mask three times to mimic the BGR structure of your original image:
mask1 = cv2.inRange(image_hsv, lower_color, upper_color)
mask_rgb = np.stack([mask1] * 3, axis = -1)
res = cv2.bitwise_or(image_in, mask_rgb)
(the resulting image is identical to the one above)