Получите средний цвет внутри контура с помощью Open CV - PullRequest
0 голосов
/ 23 января 2019

Поэтому я решил начать изучать Open CV и Python вместе!

Мой первый проект - обнаружение движущихся объектов на относительно неподвижном фоне, а затем определение их среднего цвета для сортировки.Есть как минимум 10 объектов для обнаружения, и я обрабатываю цветное видео.

До сих пор мне удавалось удалить фон, идентифицировать контуры (опционально получить центр каждого контура), но сейчас я изо всех сил пытаюсь получитьсредний или средний цвет внутри каждого контура.Есть несколько тем об этом типе вопросов, но большинство из них написаны на C. Очевидно, я мог бы использовать cv.mean(), но я не могу получить рабочую маску для подачи в эту функцию.Я думаю, это не так сложно, но я застрял там ... Ура!

import numpy as np
import cv2

video_path = 'test.h264'

cap = cv2.VideoCapture(video_path)
fgbg = cv2.createBackgroundSubtractorMOG2()


while (cap.isOpened):

    ret, frame = cap.read()
    if ret==True:
        fgmask = fgbg.apply(frame)
        (contours, hierarchy) = cv2.findContours(fgmask, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

        for c in contours:
            if cv2.contourArea(c) > 2000:
                cv2.drawContours(frame, c, -1, (255,0,0), 3)
        cv2.imshow('foreground and background',fgmask)
        cv2.imshow('rgb',frame)

    key = cv2.waitKey(1) & 0xFF

    if key == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

Ответы [ 2 ]

0 голосов
/ 23 января 2019

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

Затем вы рисуете контур (ы) на этом изображении со значением пикселя 255Полученное изображение можно использовать в качестве маски.

mask = np.zeros(frame.shape, np.uint8)
cv2.drawContours(mask, c, -1, 255, -1)

Затем можно использовать маску в качестве параметра для cv.mean, например

mean = cv.mean(frame, mask=mask)

Только одно слово предостережения, среднееиз цветов RGB не всегда имеет смысл.Возможно, попробуйте преобразовать в цветовое пространство HSV и использовать только канал H для определения цвета ваших объектов.

0 голосов
/ 23 января 2019

Раствор на изображении

1) найти контур (в данном случае прямоугольник, контур, который не является прямоугольником, сделать намного сложнее)

2) найти координаты контура

3) вырезать изображение из контура

4) суммировать отдельные каналы и делить их на количество пикселей в нем (или со средней функцией)

import numpy as np
import cv2
img = cv2.imread('my_image.jpg',1)
cp = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(cp,150,255,0)
cv2.imshow('img',thresh) 
cv2.waitKey(0)
im2,contours,hierarchy = cv2.findContours(thresh.astype(np.uint8), 1, 2)
cnts = contours
for cnt in cnts:
    if cv2.contourArea(cnt) >800: # filter small contours
        x,y,w,h = cv2.boundingRect(cnt) # offsets - with this you get 'mask'
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
        cv2.imshow('cutted contour',img[y:y+h,x:x+w])
        print('Average color (BGR): ',np.array(cv2.mean(img[y:y+h,x:x+w])).astype(np.uint8))
        cv2.waitKey(0)
cv2.imshow('img',img) 
cv2.waitKey(0)
cv2.destroyAllWindows()

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

Для непрямоугольных контуров, посмотрите на функцию cv2.fillPoly -> Обрезка не прямоугольных контуров . Но это немного медленный алгоритм (но ничего не ограничивает)

Если вы заинтересованы в непрямоугольном контуре, вам нужно быть осторожным при работе со средним, потому что вам понадобится маска, а маска / фон всегда будут прямоугольными, поэтому вы будете делать что-то среднее с тем, что вам не нужно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...