Reputation: 347
I have this image:
And I would like to change the group of pixels(greem colour) between or in contact with red and yellow pixels, by red color, this way:
Sorry, I don't have any one code, because I don't know how to start this, and I did not find an approach to do this. I think a similar logic related to PIL
, like this:
import numpy as np
from PIL import Image
im = Image.open('image.png')
data = np.array(im)
r1, g1, b1 = 255, 255, 255 # Original value
r2, g2, b2 = 0, 0, 0 # Value that we want to replace it with
red, green, blue = data[:,:,0], data[:,:,1], data[:,:,2]
mask = (red == r1) & (green == g1) & (blue == b1)
data[:,:,:3][mask] = [r2, g2, b2]
im = Image.fromarray(data)
But with a condition.
Upvotes: 2
Views: 918
Reputation: 32144
We may start the solution by using cv2.floodFill method.
Main stages:
floodFill
(assume only yellow and green pixels).floodFill
(assume only red and green pixels).Code sample:
import cv2
import numpy as np
img = cv2.imread('red_yellow_green.jpg')
cols, rows = img.shape[0], img.shape[1]
red = img[0, 0, :].tolist() # Get the red color from the top left corner
# Make the green a "true green"
img2 = img.copy()
green_ch = img2[:, :, 1]
green_ch[green_ch > 100] = 255
# Fill the lower part with black (assume only yellow and green pixels)
bot_black = img2
cv2.floodFill(bot_black, None, seedPoint=(rows-1, cols-1), newVal=(0, 0, 0), loDiff=(255, 20, 255), upDiff=(255, 20, 255))
# Fill the top part with black (assume only red and green pixels)
top_black = img.copy()
cv2.floodFill(top_black, None, seedPoint=(0, 0), newVal=(0, 0, 0), loDiff=(50, 255, 50), upDiff=(50, 255, 50))
# Find pixels where both top and bottom are zeros
both_black = np.logical_and(np.all(bot_black[:, :, 0:3] == (0, 0, 0), 2), np.all(top_black[:, :, 0:3] == (0, 0, 0), 2))
# Convert to uint8 and dilate (this part is just for aesthetics).
both_black = both_black.astype(np.uint8)*255
both_black = cv2.dilate(both_black, np.ones((5,5)))
# Replace the pixels that are both black with red color
img[both_black == 255] = red
# Show images for testing:
cv2.imshow('bot_black', bot_black)
cv2.imshow('top_black', top_black)
cv2.imshow('both_black', both_black)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
Results:
The above solution is not the most general solution.
There is also an option to find all the green contours, create a mask of the contours perimeter, and analyze the colors of the perimeter of each contour (and fill contours with mixed perimeter colors with red color).
Upvotes: 2