Ive generated a scatter plot of my image in RGB and HSV format and am using inRange()
to threshold a single color from eyeballing the plot.
To get exact RGB and HSV values I'm using paint.net's color picker to get the RGB value and then an RGB to HSV converter to get the HSV values.
The pixel colors and the scatter plot are generated by:
img = cv2.imread('C:\\b_.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pixel_colors = img.reshape((np.shape(img)[0]*np.shape(img)[1], 3))
norm = colors.Normalize(vmin=-1., vmax=1.)
norm.autoscale(pixel_colors)
pixel_colors = norm(pixel_colors).tolist()
h, s, v = cv2.split(img_hsv)
fig = plt.figure()
axis = fig.add_subplot(1, 1, 1, projection="3d")
axis.scatter(h.flatten(), s.flatten(), v.flatten(), facecolors=pixel_colors, marker=".")
axis.set_xlabel("Hue")
axis.set_ylabel("Saturation")
axis.set_zlabel("Value")
plt.show()
I need to extract the yellow from my image. As mentioned I am using paint.net color picker to get the RGB values of light yellow and dark yellow. And then use the converter to get the HSV values for the inRange()
function.
light_yellow = (60, 89, 97) # HSV VALUES
dark_yellow = (61, 36.6, 43.9)
mask = cv2.inRange(img_hsv, light_yellow, dark_yellow)
result = cv2.bitwise_and(img, img, mask=mask)
but the result generated is a black image, however if I use the RGB values directly of light and dark yellow and use the RGB image, not the HSV converted image, the segmentation works.
light_yellow = (249, 249, 125) # RGB VALUES
dark_yellow = (111, 112, 71)
mask = cv2.inRange(img, light_yellow, dark_yellow)
result = cv2.bitwise_and(img, img, mask=mask)
Although the above is RGB segmentation, I feel it may be improved in HSV. Why is my HSV range not giving an output?
As it is expressed in the documentation of cvtColor. When it is CV_8U the H value which normally goes from 0 to 360, it is divided by 2 and goes from 0-180. The S and V values are usually percentage (0-100%) and they go from 0-255.
So your value:
light_yellow = (60, 89, 97) # HSV VALUES
dark_yellow = (61, 36.6, 43.9)
Should be more like:
# (H/2, (S/100) * 255, (V/100) * 255)
light_yellow = (30, 227, 247) # HSV VALUES
dark_yellow = (31, 93, 112)
Now you have another problem, inRanges looks for valus inside the low and high range, not by light and dark yellow. So your limits should be:
low = (30,93,112)
high = (31, 227,247)
mask = cv2.inRange(img_hsv, low, high)
One more thing, I would use a bigger range for the H color... 30-31 is quite small, maybe 20-32 is better?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With