python+opencvを利用してジェスチャーの識別を実現します.
30313 ワード
先に該当モジュールをインストールしてください.
pip install pyserial //python2
pip3 install pyserial //python3
import cv2 as cv
import numpy as np
import math
import time
import serial
capture = cv.VideoCapture(0)
# video = "http://admin:[email protected]:8081/" # admin :admin
# capture = cv.VideoCapture(video)
#
def _get_eucledian_distance(vect1, vect2):
distant = vect1[0] - vect2[0]
dist = np.sqrt(np.sum(np.square(distant)))
# numpy
# vect1 = list(vect1)
# vect2 = list(vect2)
# dist = np.linalg.norm(vect1 - vect2)
return dist
def gesture_recognition():
while True:
ret, frame = capture.read() #
# frame = cv.flip(frame, 1)
fgbg = cv.createBackgroundSubtractorMOG2() # BackgroundSubtractorMOG2
# fgmask = bgModel.apply(frame)
fgmask = fgbg.apply(frame)
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# res = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
kernel = np.ones((5, 5), np.uint8)
fgmask = cv.erode(fgmask, kernel, iterations=1) #
res = cv.bitwise_and(frame, frame, mask=fgmask)
ycrcb = cv.cvtColor(res, cv.COLOR_BGR2YCrCb) # YUV , CR
(_, cr, _) = cv.split(ycrcb)
cr1 = cv.GaussianBlur(cr, (5, 5), 0) #
_, skin = cv.threshold(cr1, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) # OTSU
# dst = cv.GaussianBlur(frame, (3, 3), 0)
# gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
# ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# cv.imshow("binary_image", binary)
# hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) # hsv
# ycrcb = cv.cvtColor(frame, cv.COLOR_BGR2YCrCb) # Ycrcb
# # lower_hsv = np.array([0, 15, 0])
# # upper_hsv = np.array([17, 170, 255])
# lower_ycrcb = np.array([0, 135, 85])
# upper_ycrcb = np.array([255, 180, 135])
# # mask = cv.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv) # hsv
# mask = cv.inRange(ycrcb, lowerb=lower_ycrcb, upperb=upper_ycrcb) # ycrcb
# dst = cv.GaussianBlur(mask, (11, 11), 0) #
# gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
# edge_output = cv.Canny(gray, 50, 150) #
# kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) #
# # dst = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel) #
# dst = cv.erode(skin, kernel) #
gesture_roi = skin[0:350, 380:700]
cv.imshow("dst_demo", skin)
# cv.imshow("gesture_roi", gesture_roi)
contours, heriachy = cv.findContours(gesture_roi, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # ( )
# if contours[0] < [30, 260]:
# cnt = contours[0]
# elif 270 <= contours[0] < [60, 260]:
# cnt = contours[1]
# else:
# cnt = contours[2]
# cnt = contours[0]
# print(cnt)
# print(contours)
# cnt = contours[0]
for i, contour in enumerate(contours): #
cv.drawContours(frame[0:350, 380:700], contours, i, (255, 0, 0), 1) #
#
# area = cv.contourArea(contour)
#
# x, y, w, h = cv.boundingRect(contour)
#
# mm = cv.moments(contour)
# cx = mm['m10']/mm['m00']
# cy = mm['m01']/mm['m00']
# center, radius = cv.minEnclosingCircle(contour)
# center = (int(x), int(y))
# radius = int(radius)
# cv.circle(frame, center, radius, (0, 255, 255), 2)
# cv.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
# print(i)
# cv.imshow("measure_contures", frame)
x, y, w, h = cv.boundingRect(contour)
# center = (int(x), int(y))
cv.rectangle(frame[0:350, 380:700], (x, y), (x + w, y + h), (100, 100, 0), 1)
# approxcurve = cv.approxPolyDP(contour, 4, False)
# if approxcurve.shape[0] < 5:
# cv.drawContours(frame, contours, -1, (0, 255, 0), 3)
hull = cv.convexHull(contour, True, returnPoints=False) # x, y
defects = cv.convexityDefects(contour, hull) #
# print(hull, defects)
# cv.polylines(frame[0:350, 380:700], [hull], True, (0, 255, 0), 3)
"""
defect Nx4 ,
( )
( )
( )
"""
# cv.drawContours(frame[0:350, 380:700], hull, -1, (255, 0, 0), 5, 8) #
# dist = np.sqrt(np.sum(np.square(vect1 - vect2)))
ndefects = 0
if defects is not None: # !
for i in range(defects.shape[0]):
s, e, f, d = defects[i, 0]
# float(s)
# float(e)
# float(f)
# float(d)
start = tuple(contour[s][0]) #
end = tuple(contour[e][0]) #
far = tuple(contour[f][0]) #
a = _get_eucledian_distance(start, end)
b = _get_eucledian_distance(start, far)
c = _get_eucledian_distance(end, far)
angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))
cv.line(frame[0:350, 380:700], start, end, [255, 255, 0], 2)
cv.circle(frame[0:350, 380:700], far, 5, [0, 0, 255], -1)
if angle <= math.pi / 5: # <30 :
ndefects = ndefects + 1
print(" = %f" % ndefects)
# cv.polylines(frame[50:350, 380:700], [hull], True, (0, 255, 0), 2)
# retval = cv.pointPolygonTest(contour, center, True)
# cv.drawContours(frame, defects, -1, (0, 255, 0), 3)
# cv.imshow("defects", defects)
cv.imshow("video", frame)
c = cv.waitKey(50)
if c == 27:
break
def gesture_recognition_two():
img = cv.imread("E:/pictureprocessing/practice/picture/practice_one.png")
img = cv.flip(img, 1)
# dst = cv.GaussianBlur(frame, (3, 3), 0)
# gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
# ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# cv.imshow("binary_image", binary)
# hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # hsv
# lower_hsv = np.array([100, 43, 46])
# upper_hsv = np.array([124, 255, 255])
# mask = cv.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
dst = cv.GaussianBlur(binary, (1, 1), 0) #
# cv.imshow("dst_demo", dst)
contours, heriachy = cv.findContours(dst, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) #
for i, contour in enumerate(contours): #
cv.drawContours(img, contours, i, (0, 255, 0), 3) #
print(i)
cv.imshow("img_demo", img)
cv.namedWindow("video")
gesture_recognition()
# gesture_recognition_two()
cv.waitKey(0)
capture.release()
cv.destroyAllWindows()
プログラム運転の効果は以下の通りです. .