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()
プログラム運転の効果は以下の通りです.利用python+opencv实现手势识别(含源码,亲测)_第1张图片 利用python+opencv实现手势识别(含源码,亲测)_第2张图片.