Поиск красного цвета с помощью Python & OpenCV

Я пытаюсь извлечь красный цвет из изображения. У меня есть код, который применяет порог, чтобы оставить только значения из указанного диапазона:

img=cv2.imread('img.bmp')
img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_red = np.array([0,50,50]) #example value
upper_red = np.array([10,255,255]) #example value
mask = cv2.inRange(img_hsv, lower_red, upper_red)
img_result = cv2.bitwise_and(img, img, mask=mask)

но, как я проверил, красный может иметь значение оттенка в диапазоне, скажем, от 0 до 10, а также в диапазоне от 170 до 180. Поэтому я хотел бы оставить значения из любого из этих двух диапазонов. Я попытался установить порог от 10 до 170 и использовать cv2.функция bitwise_not, но затем я получаю весь белый цвет. Я думаю, что лучший вариант создать маску для каждого диапазона и использовать их оба, поэтому я как-то должен соединить их вместе, прежде чем продолжить.

есть ли способ присоединиться к двум маскам с помощью OpenCV? Или есть какой-то другой способ достичь своей цели?

правка. Я пришел с не очень изящное, но рабочее решение:

image_result = np.zeros((image_height,image_width,3),np.uint8)

for i in range(image_height):  #those are set elsewhere
    for j in range(image_width): #those are set elsewhere
        if img_hsv[i][j][1]>=50 
            and img_hsv[i][j][2]>=50 
            and (img_hsv[i][j][0] <= 10 or img_hsv[i][j][0]>=170):
            image_result[i][j]=img_hsv[i][j]

это в значительной степени удовлетворяет моим потребностям, и функции OpenCV, вероятно, делают почти то же самое, но если есть лучший способ сделать это(используя некоторую выделенную функцию и писать меньше кода), пожалуйста, поделитесь им со мной. :)

1 ответов


Я бы просто добавил маски вместе и использовал np.where для маскировки исходного изображения.

img=cv2.imread("img.bmp")
img_hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# lower mask (0-10)
lower_red = np.array([0,50,50])
upper_red = np.array([10,255,255])
mask0 = cv2.inRange(img_hsv, lower_red, upper_red)

# upper mask (170-180)
lower_red = np.array([170,50,50])
upper_red = np.array([180,255,255])
mask1 = cv2.inRange(img_hsv, lower_red, upper_red)

# join my masks
mask = mask0+mask1

# set my output img to zero everywhere except my mask
output_img = img.copy()
output_img[np.where(mask==0)] = 0

# or your HSV image, which I *believe* is what you want
output_hsv = img_hsv.copy()
output_hsv[np.where(mask==0)] = 0

Это должно быть намного быстрее и гораздо более читаемым, чем цикл через каждый пиксель вашего изображения.