Как определить HSV цвет в OpenCV (python)

Одной из важных задач машинного зрения является детектирование объекта. В общем случае решение найти очень проблематично или почти невозможно, поэтому часто прибегают к вспомогательным возможностям. Например раскрашивают объект в определенный цвет. Это позволяет очень простыми методами подсветить область, в которой находится предполагаемый объект. Так функция

cv2.inRange(src, lowerb, upperb[, dst])

позволяет выделить маску области. Однако резко встает вопрос корректного определения верхней и нижней границы (lowerb и upperb). А в этом как раз и прелесть и сложность пространства HSV. Кодировка цвета в модели HSV расшифровывается так: H — цветовой тон, S — насыщенность, V — яркость. Поэтому для выделения по цвету, достаточно указать диапазон H, а насыщенность и яркость будет сильно варьироваться (из-за разной освещенности, углов скоса объекта и.т.д.) На практике обычно делают примерно так: если H соcтавляющая 80 (зеленый цвет), берут нижнюю границу H=80-10 [70, 50, 50], а верхнюю H=80+10 [90,255,255]. Кажется что вот, все просто, посмотрим HSV цвет в фотошопе или пейнте и установим нужную границу… Но, в отличии от цветовой модели RGB, диапазон значений H в разных программах может задаваться по разному и его необходимо пересчитывать. Чтобы облегчить и на лету определять HSV цвет в OpenCV написал следующий небольшой скрипт:

import cv2
import cv2.cv as cv

cap = cv2.VideoCapture(0)

#set camera width and height
CAM_WIDTH = 640
CAM_HEIGHT = 480
cap.set(cv.CV_CAP_PROP_FRAME_WIDTH, CAM_WIDTH)
cap.set(cv.CV_CAP_PROP_FRAME_HEIGHT, CAM_HEIGHT)

selected_color = None
image_origin = None


def onmouse(event, x, y, flags, param):
    global image_origin, selected_color
    if flags & cv2.EVENT_FLAG_LBUTTON:
        #taking squire cur 4x4 and scale it to 1x1
        cut = image_origin[y-1:y+2, x-1:x+2]
        cut = cv2.pyrDown(cut)
        cut = cv2.pyrDown(cut)

        selected_color = (int(cut[0][0][0]), int(cut[0][0][1]), int(cut[0][0][2]))
        #conveting to HSV and printing result
        selected_color_HSV = cv2.cvtColor(cut, cv2.COLOR_BGR2HSV)
        print(selected_color_HSV)

while(1):

    # Take each frame
    _, frame = cap.read()
    image_origin = frame.copy()


    #drawing selected colors
    if selected_color is not None:
        cv2.circle(frame, (CAM_WIDTH-20,20), 20, selected_color, -1)

    #show image and set callback
    cv2.imshow('img', frame)
    cv2.setMouseCallback('img', onmouse)

    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

В данном пример изображение берется из видео-потока. Идея состоит в том, что после клика по видео изображению, выделяется квадрат 4 на 4, этот квадрат уменьшаем до размера 1 на 1 (усредняем значения цвета) и с помощью функции cv2.cvtColor(img, cv2.COLOR_BGR2HSV) переводим изображение в режим HSV.

Надеюсь этот скрипт поможет вам для работы в приложениях с OpenCV.