OpenCV+Python3.5 簡易手勢識別
- OpenCV+Python3.5 簡易手勢識別任務
- OpenCV用攝像頭捕獲視頻
- 膚色識別——橢圓膚色檢測模型
- 去噪——濾波、腐蝕和膨脹
- Canny邊緣檢測
- 識別——輪廓匹配
OpenCV+Python3.5 簡易手勢識別任務
檢測剪刀石頭布三種手勢,通過攝像頭輸入,方法如下:
- 選用合適顏色空間及閾值提取皮膚部分
- 使用濾波腐蝕膨脹等方法去噪
- 邊緣檢測
- 尋用合適方法分類
OpenCV用攝像頭捕獲視頻
采用方法:呼叫OpenCV——cv2.VideoCapture()
def video_capture():
cap = cv2.VideoCapture(0)
while True:
# capture frame-by-frame
ret, frame = cap.read()
# our operation on the frame come here
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 可選擇灰度化
# display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'): # 按q鍵退出
break
# when everything done , release the capture
cap.release()
cv2.destroyAllWindows()
效果如下

膚色識別——橢圓膚色檢測模型
參考下述博文
https://blog.csdn.net/weixin_40893939/article/details/84527037
代碼如下
def ellipse_detect(img):
# 橢圓膚色檢測模型
skinCrCbHist = np.zeros((256, 256), dtype=np.uint8)
cv2.ellipse(skinCrCbHist, (113, 155), (23, 15), 43, 0, 360, (255, 255, 255), -1)
YCRCB = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
(y, cr, cb) = cv2.split(YCRCB)
skin = np.zeros(cr.shape, dtype=np.uint8)
(x, y) = cr.shape
for i in range(0, x):
for j in range(0, y):
CR = YCRCB[i, j, 1]
CB = YCRCB[i, j, 2]
if skinCrCbHist[CR, CB] > 0:
skin[i, j] = 255
dst = cv2.bitwise_and(img, img, mask=skin)
return dst
效果如下,可見與膚色相近的物體全被提取出來,包括桌子,,,
識別時需尋找一無干擾環境

去噪——濾波、腐蝕和膨脹
參考下述博文
https://blog.csdn.net/qq_43660987/article/details/91347820
采用方法:高斯濾波 cv2.GaussianBlur() + 膨脹 cv2.dilate(),代碼如下
# 膨脹
def dilate_demo(image):
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 定義結構元素的形狀和大小
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 膨脹操作
dst = cv2.dilate(binary, kernel)
return dst
# 腐蝕
def erode_demo(image):
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 定義結構元素的形狀和大小
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
# 腐蝕操作
dst = cv2.erode(binary, kernel)
return dst
# 濾波
def img_blur(image):
# 腐蝕操作
# img_erode = erode_demo(image)
# 膨脹操作
img_dilate = dilate_demo(image)
# 均值濾波
# blur = cv2.blur(image, (5, 5))
# 高斯濾波
blur = cv2.GaussianBlur(img_dilate, (3, 3), 0)
return blur
Canny邊緣檢測
參考OpenCV中文教程
https://www.kancloud.cn/aollo/aolloopencv/271603
代碼如下
# Canny邊緣檢測v
def canny_detect(image):
edges = cv2.Canny(image, 50, 200)
return edges
識別——輪廓匹配
Tensorflow框架實在太難搭,搭了半天沒搭出來,還一堆錯誤,,,所以采用輪廓匹配 cv2.matchShapes() ,方案如下:
- 劃分出了一個手勢識別區域,可避免周圍環境的干擾,也可簡化影像處理程序
- 尋找輪廓時采用尋找矩形框架 cv2.boundingRect()的方法找到最大輪廓,即手勢的輪廓
- 將找到的輪廓直接與標準圖片進行匹配,簡化識別程序
但在匹配時發現“剪刀”的手勢常與“石頭”、“布”的手勢匹配到一起,,,所以另辟蹊徑,在匹配時加上了對于矩形框架面積的判斷,一般來說有如下規律,石頭<剪刀<布,代碼如下
# 輪廓匹配
value = [0, 0, 0]
value[0] = cv2.matchShapes(img_contour, img1, 1, 0.0)
value[1] = cv2.matchShapes(img_contour, img2, 1, 0.0)
value[2] = cv2.matchShapes(img_contour, img3, 1, 0.0)
min_index = np.argmin(value)
if min_index == 0: # 剪刀
print(text[int(min_index)], value)
elif min_index == 1 and w*h < 25000: # 石頭
print(text[int(min_index)], value)
elif min_index == 1 and w*h >= 25000: # 剪刀
print(text[0], value)
elif min_index == 2 and w * h > 30000: # 布
print(text[int(min_index)], value)
elif min_index == 2 and w * h <= 30000: # 剪刀
print(text[0], value)
程式會根據匹配值和面積大小來決定識別結果,例如,下述結果,1.179515828609219, 0.9604643714904955, 0.9896353720020925分別對應剪刀、石頭、布的匹配值,越小說明越吻合;結合最終識別情況來看,在三種手勢中,石頭的識別成功率最高,約98%;布其次,約88%;剪刀最低,約80%,而且結果易受環境亮度影響,環境過暗或過亮,有時候手勢輪廓都出不來,,,看來仍有待改進,還是得用機器學習的方法
石頭 [1.179515828609219, 0.9604643714904955, 0.9896353720020925]
程式效果如下,黃色矩形框為識別區域,gesture視窗為用于輪廓匹配的手勢圖



轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/238064.html
標籤:python
上一篇:python《紅樓夢》人物統計
下一篇:淘寶商品資訊爬取
