I'm trying to use opencv to grab specific elements out of the image. So far what I have done is reduced the number of colors in the image, and gotten a dictionary of colors with their counts. What I want to do now is replace all colors which do not match this specific color to white, so that I can iterate over the image and create different images where each image only has one object of that particular color.
This is what I've done so far:
def showOnlyOneColor(img, rgb_key):
print("Getting only one color")
rgb_key = rgb_key.split("-")
r = int(rgb_key[0])
g = int(rgb_key[1])
b = int(rgb_key[2])
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
rgb_low = np.array([r,g,b])
rgb_high = np.array([r,g,b])
mask = cv2.inRange(hsv, rgb_low, rgb_high)
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cv2.fillPoly(mask, contours, (255, 255, 255))
result = cv2.bitwise_and(img,img,mask=mask)
return result
Second attempt:
def showOnlyOneColor(img, rgb_key):
print("Getting only one color")
rgb_key = rgb_key.split("-")
r = int(rgb_key[0])
g = int(rgb_key[1])
b = int(rgb_key[2])
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
rgb_low = np.array([r,g,b])
rgb_high = np.array([r,g,b])
mask = cv2.inRange(hsv, rgb_low, rgb_high)
img[mask!=255] = (255, 255, 255)
return img
This results in a white image for all iterations
This is what I'm using to reduce the number of colors in the image:
def reduceNumberOfColors(img):
div = 128
return img // div * div div // 2
Latest attempt:
def showOnlyOneColor(img, rgb_key):
print("Getting only one color")
rgb_key = rgb_key.split("-")
r = int(rgb_key[0])
g = int(rgb_key[1])
b = int(rgb_key[2])
hsv_color = colorsys.rgb_to_hsv(r,g,b)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
rgb_low = np.array(hsv_color)
rgb_high = np.array(hsv_color)
mask = cv2.inRange(hsv, rgb_low, rgb_high)
img[mask!=255] = (255, 255, 255)
return img
One of the resulting images shows something, the rest of the images are white
How I organize rgb:
def getColorCount(img):
color_dict = {}
print("Getting color count")
for i in tqdm(range(img.shape[0])):
for j in range(img.shape[1]):
color = img[i,j]
r = color[0]
g = color[1]
b = color[2]
rgb_askey = str(r) "-" str(g) "-" str(b)
if rgb_askey not in color_dict.keys():
color_dict[rgb_askey] = 1
else:
color_dict[rgb_askey] = 1
return color_dict
CodePudding user response:
Here is one way to do what you want in Python/OpenCV. Note colors are in the order B,G,R.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('corn.jpg')
# do simple color reduction
imgcopy = img.copy()
div = 128
imgcopy = div * ( imgcopy // div ) div // 2
# get list of unique colors
list_bgr_colors = np.unique(imgcopy.reshape(-1, imgcopy.shape[2]), axis=0)
print(list_bgr_colors)
print(list_bgr_colors[1])
# save reduced color image
cv2.imwrite("corn_reduced_colors.png", imgcopy)
# display reduced color image
cv2.imshow("reduced_colors", imgcopy)
cv2.waitKey(0)
# loop over colors in list and change all non-specified colors to white
i = 1
for color in list_bgr_colors:
# threshold on the specified color
lower=np.array((color))
upper=np.array((color))
mask = cv2.inRange(imgcopy, lower, upper)
# change all non-specified color to white
result = imgcopy.copy()
result[mask!=255] = (255, 255, 255)
# save results
cv2.imwrite("corn_color_{0}.png".format(i), result)
# display result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# increment
i = 1
List of Reduced Colors:
[[ 64 64 64]
[ 64 64 192]
[ 64 192 64]
[ 64 192 192]
[192 192 192]]
Reduced Color Image:
Individual Color Images:
CodePudding user response:
Colors in OpenCV are in the order B,G,R.
So try this in Python/OpenCV.
def showOnlyOneColor(img, bgr_key):
print("Getting only one color")
bgr_key = bgr_key.split("-")
b = int(bgr_key[0])
g = int(bgr_key[1])
r = int(bgr_key[2])
bgr_low = np.array((b,g,r))
bgr_high = np.array((b,g,r))
mask = cv2.inRange(img, bgr_low, bgr_high)
img[mask!=255] = (255, 255, 255)
return img
ADDITION
I think your issue is in your assumption that you have RGB colors when you use colorsys to convert from RGB to HSV. Your colors are actually B, G, R. So to use colorsys you need to convert your image to RGB first or better reverse the order of the colors that you extract from B,G,R to R,G,B before using colorsys.
Your dictionary colors are actually B, G, R not R, G, B. So reverse them or reverse them later when using colorsys.
CodePudding user response:
This works for me in Python/OpenCV. Note that OpenCV colors are in the order B,G,R.
import cv2
import numpy as np
# read image
img = cv2.imread('corn.jpg')
# threshold on yellow color
lower=(0,170,215)
upper=(70,255,255)
mask = cv2.inRange(img, lower, upper)
# change all non-yellow to white
result = img.copy()
result[mask!=255] = (255, 255, 255)
# save results
cv2.imwrite('corn_yellow.jpg',result)
# display result
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()