'Check if an image contains blue pixels
I have this image:
And I'm trying to write a function in Python that will return True
if the image contains blue pixels, or False
otherwise.
That image is just an example. I will have others were the blue colour can be slightly different. But they will always be blue letters over a black background.
So far I have this:
def contains_blue(img):
# Convert the image to HSV colour space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Define a range for blue color
hsv_l = np.array([100, 150, 0])
hsv_h = np.array([140, 255, 255])
# Find blue pixels in the image
#
# cv2.inRange will create a mask (binary array) where the 1 values
# are blue pixels and 0 values are any other colour out of the blue
# range defined by hsv_l and hsv_h
return 1 in cv2.inRange(hsv, hsv_l, hsv_h)
The function always returns False
because no 1
values are found in the array returned by cv2.inRange
. Maybe the range defined by hsv_l
and hsv_h
is not good? I took it from here: OpenCV & Python -- Can't detect blue objects
Any help is appreciated. Thanks.
Solution 1:[1]
The problem is that you are not reading the documentation of inRange :D
Which tells the following:
That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the specified 1D, 2D, 3D, ... box and 0 otherwise.
and you check for 1
# cv2.inRange will create a mask (binary array) where the 1 values
# are blue pixels and 0 values are any other colour out of the blue
# range defined by hsv_l and hsv_h
return 1 in cv2.inRange(hsv, hsv_l, hsv_h)
So the solution is to change it to:
return 255 in cv2.inRange(hsv, hsv_l, hsv_h)
I tested it with your image and returns true, also with a black and white image (BGR though) and returns false.
In my opinion the blue ranges you have chosen are a little far to the violet side... You may use a hsv colorpicker like this one http://colorizer.org/ and select the ranges you will like. Just rememeber OpenCV uses H -> Hue / 2 and S and V are like percentages (0-100) and you just divide them by 100 (0-1.) and multiply them by 255.
Solution 2:[2]
You could have just used np.any()
instead. It will return True
if any one pixel has a value of 255.
So instead of
return 1 in cv2.inRange(hsv, hsv_l, hsv_h)
,
you can just add the following:
return np.any(cv2.inRange(hsv, hsv_l, hsv_h))
Update:
As @AKX mentioned in the comments you could rather try out the following:
return cv2.inRange(hsv, hsv_l, hsv_h).any()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | api55 |
Solution 2 |