How to detect black and gray from an image
Asked Answered
O

1

7

I am trying to get a program to detect any hue of black (and some slight gray), but am currently having difficulties trying to find a good upper hue vector (the upper_hue variable) that would allow me extract most hues of black with out extracting other colors. It seems to work well with pictures like the black shoes or umbrella, but there it has problems with photos of roads where the brightness varies.

I am trying to find a good upper hue range that would allow the program to be robust against this, however it risks getting non-black colors.

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

What would be a good upper hue vector of values for black and gray. If that isn't the issue, what would be a good way to solve this?

Code:

import cv2
import numpy as np
import imutils

def color_seg(choice):
    if choice == 'blue':
        lower_hue = np.array([100,30,30])
        upper_hue = np.array([150,148,255])
    elif choice == 'white':
        lower_hue = np.array([0,0,0])
        upper_hue = np.array([0,0,255])
    elif choice == 'black':
        lower_hue = np.array([0,0,0])
        upper_hue = np.array([50,50,100])
    return lower_hue, upper_hue


# Take each frame
frame = cv2.imread('images/black0.jpg')
#frame = cv2.imread('images/road_1.jpg')

frame = imutils.resize(frame, height = 300)
chosen_color = 'black'


# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

# define range of a color in HSV
lower_hue, upper_hue = color_seg(chosen_color)


# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_hue, upper_hue)


cv2.imshow('frame',frame)
cv2.imshow('mask',mask)

cv2.waitKey(0)
Olatha answered 29/10, 2015 at 1:20 Comment(5)
Hint: black is not a hue. Just keep low value, any hue, and not too low saturationHui
what about histogram ... if you got lot of black and gray then they should be distinct in histogram .... so try to find peaks or just levels and use that as treshold ....Hornbook
Histogram sounds good, but I am trying to find a general upper hue range so that I wouldn't have to keep analyzing the histogram and tune the hue values just for that specific pictureOlatha
I think that the histogram will work accurately only for objects images. For the road, it will not be stable, because the road can have many different colors and represent only fraction of the image (see your last example).Contrition
Did you manage to find your answer? Would you mind sharing it?Retraction
A
5

In hsv color space, it's pretty simple.

img = cv2.imread(img_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_gray = np.array([0, 5, 50], np.uint8)
upper_gray = np.array([179, 50, 255], np.uint8)
mask_gray = cv2.inRange(hsv, lower_gray, upper_gray)
img_res = cv2.bitwise_and(img, img, mask = mask_gray)

H is the hue, so the gray detector needs all the H values(0 -> 360°, represented by OpenCV in the integer range 0 to 179 to fit in 8 bits). S is the saturation (0 -> 255). The gray scales are between 0 and 50. If we don't want to keep the white values we can take 5 as minimal value. V is the brightness value (0=dark -> 255=bright).

Audio answered 16/4, 2019 at 14:23 Comment(2)
My understanding is that OpenCV represents hue with integers from 0 to 179 only, so upper_gray's first value should be 179 instead of 360, right? In any case, this should not be an issue in this example because all hues will be accepted anyway.Stirps
Correction: OpenCV represents hue with integers from 0 to 179 only, so upper_gray's first value should be 179 instead of 360. At first I thought this would not matter since using 360 would select all hues anyway, but because 360 is greater than 255, it requires more than the 8 bits supported by uint8. This causes the actual hue for upper_gray to be the lower 8 bits of 360, which becomes 360 - 2^8 = 104. Therefore it does not select all hues.Stirps

© 2022 - 2024 — McMap. All rights reserved.