手势识别rtos小车(1)----手部识别

1.安装mediapipe库和cv2库

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple



pip install Mediapipe==0.8.9.1 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 

这里我主要还是弄明白了这个pycharm编辑器和项目之间的关系,我在这里浪费了一下午的时间去配置环境

1.pycharm里面的环境存在于anaconda里面,你的每个项目都可以创建对应的解释器,但是其实这个解释器就是你安装的python的版本

手势识别rtos小车(1)----手部识别_第1张图片

所以每次使用的解释器都来自这里【anaconda环境下】

2.当出现无法安装一些库的时候,可以选择去windows终端去建立,当然以及在pycharm里面不可以创建的python版本也可以在终端创建。

3.当一些库无法找到的时候,可以去对应的官网下载对应python版本的库,然后在windows终端pip直接安装,但是前提记得把whl文件放入到对应的解释器的Scripts里面再去安装。当无法找到你的whl文件的时候,可以尝试把文件的完整地址带上。

 代码如下及理解:

while True:
    count = 0
    success, img = cap.read()#BGR存储格式
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#转为RGB存储
    results = hands.process(imgRGB)#处理返回的手的标志点以及处理
    if results.multi_hand_landmarks:#返回none或手的标志点坐标
        for handLms in results.multi_hand_landmarks:
            for id, lm in enumerate(handLms.landmark):
                #id是索引,总共21个,lm指的是每个点对应的x,y的坐标,在0-1之间,因为是相对于窗口来计算的
                h, w, c = img.shape
                    #h 表示图像的高度(height),即图像在垂直方向上的像素数;
                    #w 表示图像的宽度(width),即图像在水平方向上的像素数;
                    #c 表示图像的通道数(channels),即图像的颜色通道数量,
                    #如灰度图像的通道数为1,彩色图像的通道数为3。
                cx, cy = int(lm.x*w), int(lm.y*h)
                    #转换为实际的像素坐标
                
                xs[id] = cx
                ys[id] = cy
                #写入到每个id的数组里面
                cv2.circle(img, (cx, cy), 5, (0, 255, 105), cv2.FILLED)
                #将每个点以坐标为圆心,放大,以及更改颜色
                cv2.putText(img, str(int(id)), (cx, cy), cv2.FONT_HERSHEY_PLAIN, 2,
                (200, 20, 50), 3)
                #周围显示的数字的颜色,以及大小
                K_count()
            mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
    #计算当前图像的帧率
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
                (255, 0, 255), 1)

    cv2.imshow("Image", img)
    k = cv2.waitKey(1)
    if k == 27:
        cap.release()
        cv2.destroyAllWindows()
        exit()

 核心代码分析:

def K_count():
    k=5             #因为0-4s是大拇指的id
    i=0          
    while(k<20): 
        #计算其他四个手指每个的中心坐标
        aveX1 = (xs[k] + xs[k+1] + xs[k+2] + xs[k+3]) / 4   
        aveY1 = (ys[k] + ys[k+1] + ys[k+2] + ys[k+3]) / 4  
        #使用最小二乘法求得每个手指的斜率,判断了坟墓为0的情况
        t = (xs[k] * xs[k] + xs[k+1] * xs[k+1] + xs[k+2] * xs[k+2] + xs[k+3] * xs[k+3] - 4 * aveX1 * aveX1)
        if(abs (t - 0) < 0.000001):
            t += 0.000001
        if aveX1 != 0 and aveY1 != 0:
            k1 = (xs[k] * ys[k] + xs[k+1] * ys[k+1] + xs[k+2] * ys[k+2] + xs[k+3] * ys[k+3] - 4 * aveX1 * aveY1) /t
        else:
            k1 = 0
        ks[i] = k1
        i += 1
        k += 4
    #计算每个手指相对于中心平均值的偏离程度
    avek = sum(ks)/4
    ks0 = abs(ks[0] - avek)
    ks1 = abs(ks[1] - avek)
    ks2 = abs(ks[2] - avek)
    ks3 = abs(ks[3] - avek)
    print(ks[1])
    #根据id4和id8的距离来决定要不要停止
    dis = point_distance(xs[4], ys[4], xs[8], ys[8])
    if (ks0+ks1+ks2+ks3) < 3.5 and dis > 100 and abs(ks[1]) > 3:
        print("前进")
    elif (ks0+ks1+ks2+ks3) < 3.5 and dis > 100 and -1 < ks[1] < 0:
        print("左转")
    elif (ks0 + ks1 + ks2 + ks3) < 3.5 and dis > 100 and 0 < ks[1] < 1:
        print("右转")
    elif dis < 100:
        print("停止")

对于接下来该怎么的判断,可以根据自己的要求进行改变。根据斜率,每个点的距离,以及到摄像头的距离,都可以灵活判断。核心还是在于mediapipe库的调用。

整体代码:

# -*-coding:utf-8-*-

import cv2
import mediapipe as mp
import time
import math
cap = cv2.VideoCapture(0)
#该函数的参数
#static_image_mode,max_num_hands,min_detection_confidence,min_tracking_confidence
mpHands = mp.solutions.hands
hands = mpHands.Hands()
mpDraw = mp.solutions.drawing_utils
pTime = 0#开始时间初始化
cTime = 0#目前时间初始化
xs = []
ys = []
ks = []
#大小为21的数组初始化
for i in range(0,21):
    xs.append(0)
    ys.append(0)
for i in range(0,4):
    ks.append(0)
#计算两点间的距离
def point_distance(x1, y1, x2, y2 ):
    dis = abs(math.sqrt((x2 - x1)*(x2 - x1)+(y2 - y1)*(y2 - y1)))
    return dis
def K_count():
    k=5
    i=0
    while(k<20):
        aveX1 = (xs[k] + xs[k+1] + xs[k+2] + xs[k+3]) / 4
        aveY1 = (ys[k] + ys[k+1] + ys[k+2] + ys[k+3]) / 4
        t = (xs[k] * xs[k] + xs[k+1] * xs[k+1] + xs[k+2] * xs[k+2] + xs[k+3] * xs[k+3] - 4 * aveX1 * aveX1)
        if(abs (t - 0) < 0.000001):
            t += 0.000001
        if aveX1 != 0 and aveY1 != 0:
            k1 = (xs[k] * ys[k] + xs[k+1] * ys[k+1] + xs[k+2] * ys[k+2] + xs[k+3] * ys[k+3] - 4 * aveX1 * aveY1) /t
        else:
            k1 = 0
        ks[i] = k1
        i += 1
        k += 4
    avek = sum(ks)/4
    #print(avek)
    ks0 = abs(ks[0] - avek)
    ks1 = abs(ks[1] - avek)
    ks2 = abs(ks[2] - avek)
    ks3 = abs(ks[3] - avek)
    #ks0 = (ks[0] - avek)
    #ks1 = (ks[1] - avek)
    #ks2 = (ks[2] - avek)
    #ks3 = (ks[3] - avek)
    print(ks[1])
    dis = point_distance(xs[4], ys[4], xs[8], ys[8])
    if (ks0+ks1+ks2+ks3) < 3.5 and dis > 100 and abs(ks[1]) > 3:
        print("前进")
    elif (ks0+ks1+ks2+ks3) < 3.5 and dis > 100 and -1 < ks[1] < 0:
        print("左转")
    elif (ks0 + ks1 + ks2 + ks3) < 3.5 and dis > 100 and 0 < ks[1] < 1:
        print("右转")
    elif dis < 100:
        print("停止")
while True:
    count = 0
    success, img = cap.read()#BGR存储格式
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#转为RGB存储
    #处理返回的手的标志点以及处理
    results = hands.process(imgRGB)
    if results.multi_hand_landmarks:#返回none或手的标志点坐标
        for handLms in results.multi_hand_landmarks:
            #id是索引,lm是x,y坐标
            for id, lm in enumerate(handLms.landmark):
                h, w, c = img.shape
                cx, cy = int(lm.x*w), int(lm.y*h)
               # print(id, cx, cy)
                xs[id] = cx
                ys[id] = cy
                cv2.circle(img, (cx, cy), 5, (0, 255, 105), cv2.FILLED)
                cv2.putText(img, str(int(id)), (cx, cy), cv2.FONT_HERSHEY_PLAIN, 2,
                (200, 20, 50), 3)
                K_count()
            mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
                (255, 0, 255), 1)
    cv2.imshow("Image", img)
    k = cv2.waitKey(1)
    if k == 27:
        cap.release()
        cv2.destroyAllWindows()
        exit()





你可能感兴趣的:(手势识别小车,python,开发语言)