Проблема с BackProjection и Opencv
Я пытаюсь реализовать алгоритм обратного проецирования с opencv для обнаружения рук. Этот алгоритм состоит из нескольких источников. Я попробовал несколько методов, таких как морфология и добавление backgroundSubtraction к проекции, чтобы попытаться получить лучший результат. Я тоже смотрел онлайн. Тем не менее, я продолжаю получать фото ниже. У кого-нибудь есть предложения по поводу того, что я, возможно, делаю неправильно?
-Спасибо
Вот мой код только с обратной проекцией:
import cv2
import numpy as np
#module for esc keyMap on my computer
import keyMappings as kM
#set up webcam
cap = cv2.VideoCapture(0)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 1000)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600)
#read a picture of a hand from my desktop
Hand = cv2.imread('/home/lie/Desktop/handPic.jpg')
#convert HSV and calc Histogram of this Pic
hsvHand = cv2.cvtColor(Hand, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsvHand)
roihist = cv2.calcHist([hsvHand], [0,1], None, [180,256],[0,180,0,256])
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
#while not pressing esc
while cv2.waitKey(30) != kM.esc:
#take pic convert HSV
_,frame = cap.read()
hsvt = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#backproject
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
#filtering
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(dst,-1,disc,dst)
#threshold
ret,thresh = cv2.threshold(dst,50,255,0)
#find contours in thresholded pic
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
ci =0
max_area =0
if len(contours)!=0:
#find max contour
for i in range(len(contours)):
cnt = contours[i]
area = cv2.contourArea(cnt)
if(area>max_area):
max_area = area
ci =i
#create hull around contour
cnt = contours[ci]
hull = cv2.convexHull(cnt)
#Code to draw contours and show pic is ommited
Это изображение используется для распознавания руки:
Это изображение с порогом:
На снимке явно не много руки и много шума.
1 ответ
После этого поста прошло очень и очень много времени, и, честно говоря, я немного удивлен, что никто не ответил вам. Хотя я совершенно уверен, что вы нашли ответ / альтернативное решение, для блага других я отвечу на это.
То, что вы наблюдаете, напрямую связано с количеством бинов, которые вы используете в своей гистограмме HS. Большее количество бинов означает, что вы будете более точно представлять скин, а это означает, что ваша возможная гистограмма не сможет создать "тренд" кожи. Вы должны абсолютно уменьшить количество корзин. По моему опыту, все, что между 8 и 12 для каналов Hue и Saturation работает хорошо.
Однако выполнение этого не гарантирует очень хорошее изображение с обратной проекцией. У вас все еще есть серьезная проблема, и вы используете весь шаблон руки для создания своей гистограммы. Как таковой, шаблон содержит много кожи, но много области вокруг руки, которая не является кожей. Конечная гистограмма, которую вы сгенерируете, также будет представлять фон. По моему опыту с этим (и у меня его много), даже относительно небольшое количество фильтрации шума в возможной гистограмме вызовет большое количество шума в вашем обратно спроецированном изображении. Ключевым является поддержание фона в вашей гистограмме до минимума. Так что лучше подумайте о том, чтобы взять небольшую область внутри своего шаблона руки и генерировать свою гистограмму только на этом. Я изменил ваш код, как показано ниже, и он работает как сон в моей конфигурации.
Обратите внимание, что я сделал несколько изменений, например, для выхода просто используется кнопка "q", изменен путь к шаблону и т. Д. Он в основном такой же.
import cv2
import numpy as np
#set up webcam
cap = cv2.VideoCapture(0)
#cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 640)
#cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 480)
#read a picture of a hand from my desktop
Hand = cv2.imread('handPic.jpg')
hh,hw, __ = Hand.shape
#convert HSV and calc Histogram of this Pic
hsvHand = cv2.cvtColor(Hand[220:292, 110:220], cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsvHand)
roihist = cv2.calcHist([hsvHand], [0,1], None, [12,12],[0,181,0,256])
#cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
#while not pressing esc
while cv2.waitKey(30) & 0xFF != ord('q'):
#take pic convert HSV
_,frame = cap.read()
hsvt = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#backproject
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
#filtering
# ret, dst = cv2.threshold(dst,0,255,cv2.THRESH_OTSU)
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(dst,-1,disc,dst)
cv2.imshow("Skin Areas", dst)