I have an image of a coffee can with an orange lid position of which I want to find. Here is it .
gcolor2 utility shows HSV at the center of the lid to be (22, 59, 100). The question is how to choose the limits of the color then? I tried min = (18, 40, 90) and max = (27, 255, 255), but have got unexpected
Here is the Python code:
import cv
in_image = 'kaffee.png'
out_image = 'kaffee_out.png'
out_image_thr = 'kaffee_thr.png'
ORANGE_MIN = cv.Scalar(18, 40, 90)
ORANGE_MAX = cv.Scalar(27, 255, 255)
COLOR_MIN = ORANGE_MIN
COLOR_MAX = ORANGE_MAX
def test1():
frame = cv.LoadImage(in_image)
frameHSV = cv.CreateImage(cv.GetSize(frame), 8, 3)
cv.CvtColor(frame, frameHSV, cv.CV_RGB2HSV)
frame_threshed = cv.CreateImage(cv.GetSize(frameHSV), 8, 1)
cv.InRangeS(frameHSV, COLOR_MIN, COLOR_MAX, frame_threshed)
cv.SaveImage(out_image_thr, frame_threshed)
if __name__ == '__main__':
test1()
Problem 1 : Different applications use different scales for HSV. For example gimp uses H = 0-360, S = 0-100 and V = 0-100
. But OpenCV uses H: 0-179, S: 0-255, V: 0-255
. Here i got a hue value of 22 in gimp. So I took half of it, 11, and defined range for that. ie (5,50,50) - (15,255,255)
.
Problem 2: And also, OpenCV uses BGR format, not RGB. So change your code which converts RGB to HSV as follows:
cv.CvtColor(frame, frameHSV, cv.CV_BGR2HSV)
Now run it. I got an output as follows:
Hope that is what you wanted. There are some false detections, but they are small, so you can choose biggest contour which is your lid.
EDIT:
As Karl Philip told in his comment, it would be good to add new code. But there is change of only a single line. So, I would like to add the same code implemented in new cv2
module, so users can compare the easiness and flexibility of new cv2
module.
import cv2
import numpy as np
img = cv2.imread('sof.jpg')
ORANGE_MIN = np.array([5, 50, 50],np.uint8)
ORANGE_MAX = np.array([15, 255, 255],np.uint8)
hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
frame_threshed = cv2.inRange(hsv_img, ORANGE_MIN, ORANGE_MAX)
cv2.imwrite('output2.jpg', frame_threshed)
It gives the same result as above. But code is much more simpler.