給一個(gè)覺得比較好的數(shù)據(jù)集(http://www.nada.kth.se/cvap/actions/)
手勢(shì)識(shí)別之手勢(shì)檢測(cè)
代碼參考于(https://github.com/rainyear/lolita/issues/8)
import cv2
import numpy as np
def main():
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret, img = cap.read()
skinMask = HSVBin(img)
contours = getContours(skinMask)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
cv2.imshow('capture', img)
k = cv2.waitKey(10)
if k == 27:
break
def getContours(img):
kernel = np.ones((5,5),np.uint8)
closed = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closed = cv2.morphologyEx(closed, cv2.MORPH_CLOSE, kernel)
_,contours, h = cv2.findContours(closed, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
validContours = [];
for cont in contours:
if cv2.contourArea(cont) > 9000:
# x,y,w,h = cv2.boundingRect(cont)
# if h/w > 0.75:
validContours.append(cv2.convexHull(cont))
# rect = cv2.minAreaRect(cont)
# box = cv2.cv.BoxPoints(rect)
# validContours.append(np.int0(box))
return validContours
# 皮膚檢測(cè),皮膚顏色在HSV顏色空間下與周圍環(huán)境區(qū)分度更高
# 所以把RGB轉(zhuǎn)換到HSV顏色空間下針對(duì)皮膚顏色進(jìn)行二值化,得到mask
def HSVBin(img):
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
lower_skin = np.array([100, 50, 0])
upper_skin = np.array([125, 255, 255])
mask = cv2.inRange(hsv, lower_skin, upper_skin)
# res = cv2.bitwise_and(img, img, mask=mask)
return mask
if __name__ == '__main__':
main()
ctvColor:顏色空間轉(zhuǎn)換
inRange: lower..指圖像中低于這個(gè)值,圖像值變?yōu)?,upper:指圖像中高于這個(gè)值庸论,圖像值變?yōu)?,而在之間的值變?yōu)?55
bitwise_and是對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行“與”操作,即對(duì)圖像(灰度圖像或彩色圖像均可)每個(gè)像素值進(jìn)行二進(jìn)制“與”操作梅肤,1&1=1,1&0=0邑茄,0&1=0姨蝴,0&0=0
不太懂?肺缕?-
去除一些噪點(diǎn)--腐蝕與膨脹左医,得到更完整的白色(皮膚)色塊授帕,最后找出色塊的輪廓,并通過色塊大小排除一些面積較小的噪點(diǎn)浮梢。
膨脹:dilate跛十,進(jìn)行膨脹操作時(shí),將內(nèi)核 B劃過圖像秕硝,將內(nèi)核B覆蓋區(qū)域的最大像素值提取芥映,并代替錨點(diǎn)位置的像素,這一最大化操作會(huì)導(dǎo)致圖像中的亮區(qū)開始“擴(kuò)展”
-
腐蝕:erode远豺,將最小像素值提取
原始圖片里的一個(gè)像素(1或者0)只有在核下的所有像素都是1的時(shí)候才被認(rèn)為是1.否則它就被腐蝕掉了(變成0)根據(jù)核的大小來決定在邊界附近的多少像素會(huì)被丟棄掉奈偏,所以前景物體的厚度或大小會(huì)縮小,或者說白色區(qū)域會(huì)減小躯护。這個(gè)在移除小的白色噪點(diǎn)時(shí)很有用惊来。
- ones(shape[,dtype,order]) 依據(jù)一個(gè)給定的形狀和類型返回一個(gè)新的元素全部為1的數(shù)組。
- data type :uint8 -->range:0~255棺滞,一張圖片的數(shù)據(jù)類型默認(rèn)為unit8
kernel = np.ones((5,5), np.uint8)裁蚁,
,給一個(gè)5x5的核,
- data type :uint8 -->range:0~255棺滞,一張圖片的數(shù)據(jù)類型默認(rèn)為unit8
- 開:腐蝕之后再膨脹的另一個(gè)名字检眯。我們使用函數(shù)cv2.morphologyEx()
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
- 閉:膨脹之后再腐蝕厘擂,在用來關(guān)閉前景對(duì)象里的小洞或小黑點(diǎn)很有用。
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
- 輪廓檢測(cè) cv2.findContours
接收參數(shù)為二值圖锰瘸,所以可以考慮先轉(zhuǎn)換成灰度刽严,再轉(zhuǎn)成二值,如下:
import cv2
img = cv2.imread('D:\\test\\contour.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv2.imshow("img", img)
函數(shù)原型:
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
參數(shù)說明:
- mode:輪廓檢索模式避凝。RETR_TREE: 建立一個(gè)等級(jí)樹結(jié)構(gòu)的輪廓
- method:輪廓的近似辦法舞萄。cv2.CHAIN_APPROX_SIMP:壓縮水平方向、垂直方向管削、對(duì)角線方向的元素倒脓,只保留該方向的終點(diǎn)坐標(biāo)。例如一個(gè)矩形輪廓只需要 4 個(gè)點(diǎn)來保存輪廓信息
- contours-返回的輪廓含思,返回一個(gè)list崎弃,list中每個(gè)元素是圖像中一個(gè)輪廓
4.hierarchy-每條輪廓對(duì)應(yīng)的屬性
5.cv2.drawContours()繪制輪廓
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
- coutourIdx:指定繪制哪條輪廓,如果為-1則所有含潘,
7.(0饲做,0,225)表顏色
- cv.contourArea-計(jì)算面積
8.cv2.waitKey()--waitKey()函數(shù)的功能是不斷刷新圖像遏弱,頻率時(shí)間為delay盆均,單位為ms。返回值為當(dāng)前鍵盤按鍵值漱逸。