回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

【科学探究】串口数据记录器——分析数据判断手势 简单

头像 云天 2022.05.08 1312 2

利用Mediapipe获取手势数据,通过串口数据记录器存储数据,使用EXCEL分析数据,再利用程序分析手势。

【测试数据传输】

利用显示屏显示接收的数据

①在Mind+的扩展库、功能模块,添加“软串口”。

project-image

②拖曳积木编写程序

project-image

代码第四行设置主控板11号引脚为Rx,6号引脚为Tx。

数据传输测试(Python)

代码
import serial
import time
ser = serial.Serial('COM4', 9600, timeout=0)
Timestamp = str(int(time.time()))
if __name__ == '__main__':
     #while True:
     for index in range(10):
                   Timestamp = str(int(time.time()))
                   time.sleep(2)
                   data=Timestamp+"s"
                   
                   ser.write(data.encode("utf-8"))#向端口些数据
                   #print(data.encode("utf-8"))
     ser.close()#关闭端口
project-image

手部的节点,每只手有21个。

project-image

【存储数据】

代码
import cv2
import numpy as np
import mediapipe as mp
import serial
import time
ser = serial.Serial('COM4', 9600, timeout=0)
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic

joint_list = [[6,9, 10],[4,3, 2],[8, 7, 6], [12, 11, 10], [16, 15, 14], [20, 19, 18]]  # 手指关节序列

cap = cv2.VideoCapture(0)
Timestamp = time.time()
with mp_holistic.Holistic(
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5) as holistic:
    while cap.isOpened():
        data=""
        success, image = cap.read()
        if not success:
            print("Ignoring empty camera frame.")
            break
        image.flags.writeable = False
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        results = holistic.process(image)
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

        # 渲染
        #mp_drawing.draw_landmarks(image,results.face_landmarks)
        #mp_drawing.draw_landmarks(image,results.pose_landmarks)

        mp_drawing.draw_landmarks(image, results.left_hand_landmarks)
        mp_drawing.draw_landmarks(image, results.right_hand_landmarks)
        # 监测到右手,执行
        if results.right_hand_landmarks:
            RHL = results.right_hand_landmarks
            # 计算角度
            for joint in joint_list:
                a = np.array([RHL.landmark[joint[0]].x, RHL.landmark[joint[0]].y])
                b = np.array([RHL.landmark[joint[1]].x, RHL.landmark[joint[1]].y])
                c = np.array([RHL.landmark[joint[2]].x, RHL.landmark[joint[2]].y])
                # 计算弧度
                radians_fingers = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
                angle = np.abs(radians_fingers * 180.0 / np.pi)  # 弧度转角度

                if angle > 180.0:
                    angle = 360 - angle
                if data!="":
                 data=data + "," + str(angle)
                else:
                 data=str(angle)
                cv2.putText(image, str(round(angle, 2)), tuple(np.multiply(b, [640, 480]).astype(int)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
                
        if results.left_hand_landmarks:
            RHL = results.left_hand_landmarks
            # 计算角度
            for joint in joint_list:
                a = np.array([RHL.landmark[joint[0]].x, RHL.landmark[joint[0]].y])
                b = np.array([RHL.landmark[joint[1]].x, RHL.landmark[joint[1]].y])
                c = np.array([RHL.landmark[joint[2]].x, RHL.landmark[joint[2]].y])
                # 计算弧度
                radians_fingers = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
                angle = np.abs(radians_fingers * 180.0 / np.pi)  # 弧度转角度

                if angle > 180.0:
                    angle = 360 - angle

                cv2.putText(image, str(round(angle, 2)), tuple(np.multiply(b, [640, 480]).astype(int)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
                if joint[0]==6:
                    if angle>50 and time.time()-Timestamp>2:
                        Timestamp=time.time()
                        data=data+"s"
                        ser.write(data.encode("utf-8"))#向端口些数据
                        data=""

        # cv2.imshow('MediaPipe Holistic', cv2.flip(image, 1))
        cv2.imshow('Mediapipe Holistic', image)  # 取消镜面翻转
        if cv2.waitKey(5) == ord('q'):
            break
cap.release()

【硬件连接】

project-image

【发送数据】

右手食指与中食打开角度超过50度,开始向主板发送数据。

project-image

【处理数据】

串口数据记录器用数据线连接电脑,拷贝数据文件。

project-image
project-image

将数据文件TXT修改为CSV,用EXCE程序打开。并利用公式计算最大值(MAX)和最小值(MIN)。

project-image

通过以上方法,可记录各种手势的数据,通过EXCEL进行分析,再利用Python程序对手势进行相应判断。

project-image

【手势判断】

利用所得数据编写程序

代码
                if joint[0]==4:
                    if angle>162 and angle<180:
                      palm=palm+1
                if joint[0]==8:
                    if angle>175 and angle<179:
                      palm=palm+1
                if joint[0]==12:
                    if angle>178 and angle<180:
                      palm=palm+1 
                if joint[0]==16:
                    if angle>177 and angle<180:
                      palm=palm+1
                if joint[0]==20:
                    if angle>175 and angle<179:
                      palm=palm+1
                
                if joint[0]==4:
                    if angle>112 and angle<133:
                      fist=fist+1
                if joint[0]==8:
                    if angle>126 and angle<180:
                      fist=fist+1
                if joint[0]==12:
                    if angle>118 and angle<179:
                     fist=fist+1
                if joint[0]==16:
                    if angle>118 and angle<180:
                      fist=fist+1
                if joint[0]==20:
                    if angle>130 and angle<176:
                      fist=fist+1
            if palm==5:
                cv2.putText(image, "PALM", (100,100),cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 2, cv2.LINE_AA)
            if fist==5:
                cv2.putText(image, "FIST", (100,100),cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 2, cv2.LINE_AA)
    

【完整程序】

代码
import cv2
import numpy as np
import mediapipe as mp
import serial
import time
ser = serial.Serial('COM4', 9600, timeout=0)
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic

joint_list = [[6,9, 10],[4,3, 2],[8, 7, 6], [12, 11, 10], [16, 15, 14], [20, 19, 18]]  # 手指关节序列

cap = cv2.VideoCapture(0)
Timestamp = time.time()
palm=0
fist=0
with mp_holistic.Holistic(
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5) as holistic:
    while cap.isOpened():
        
        success, image = cap.read()
        if not success:
            print("Ignoring empty camera frame.")
            break
        image.flags.writeable = False
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        results = holistic.process(image)
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

        # 渲染
        #mp_drawing.draw_landmarks(image,results.face_landmarks)
        #mp_drawing.draw_landmarks(image,results.pose_landmarks)

        mp_drawing.draw_landmarks(image, results.left_hand_landmarks)
        mp_drawing.draw_landmarks(image, results.right_hand_landmarks)
        # 监测到右手,执行
        if results.right_hand_landmarks:
            RHL = results.right_hand_landmarks
            palm=0
            fist=0
            # 计算角度
            for joint in joint_list:
                a = np.array([RHL.landmark[joint[0]].x, RHL.landmark[joint[0]].y])
                b = np.array([RHL.landmark[joint[1]].x, RHL.landmark[joint[1]].y])
                c = np.array([RHL.landmark[joint[2]].x, RHL.landmark[joint[2]].y])
                # 计算弧度
                radians_fingers = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
                angle = np.abs(radians_fingers * 180.0 / np.pi)  # 弧度转角度

                if angle > 180.0:
                    angle = 360 - angle
             
                cv2.putText(image, str(round(angle, 2)), tuple(np.multiply(b, [640, 480]).astype(int)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
                if joint[0]==4:
                    if angle>162 and angle<180:
                      palm=palm+1
                if joint[0]==8:
                    if angle>175 and angle<179:
                      palm=palm+1
                if joint[0]==12:
                    if angle>178 and angle<180:
                      palm=palm+1 
                if joint[0]==16:
                    if angle>177 and angle<180:
                      palm=palm+1
                if joint[0]==20:
                    if angle>175 and angle<179:
                      palm=palm+1
                
                if joint[0]==4:
                    if angle>112 and angle<133:
                      fist=fist+1
                if joint[0]==8:
                    if angle>126 and angle<180:
                      fist=fist+1
                if joint[0]==12:
                    if angle>118 and angle<179:
                     fist=fist+1
                if joint[0]==16:
                    if angle>118 and angle<180:
                      fist=fist+1
                if joint[0]==20:
                    if angle>130 and angle<176:
                      fist=fist+1
            if palm==5:
                cv2.putText(image, "PALM", (100,100),cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 2, cv2.LINE_AA)
            if fist==5:
                cv2.putText(image, "FIST", (100,100),cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 2, cv2.LINE_AA)
       
        if results.left_hand_landmarks:
            RHL = results.left_hand_landmarks
            
            # 计算角度

            for joint in joint_list:
                a = np.array([RHL.landmark[joint[0]].x, RHL.landmark[joint[0]].y])
                b = np.array([RHL.landmark[joint[1]].x, RHL.landmark[joint[1]].y])
                c = np.array([RHL.landmark[joint[2]].x, RHL.landmark[joint[2]].y])
                # 计算弧度
                radians_fingers = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
                angle = np.abs(radians_fingers * 180.0 / np.pi)  # 弧度转角度

                if angle > 180.0:
                    angle = 360 - angle

                cv2.putText(image, str(round(angle, 2)), tuple(np.multiply(b, [640, 480]).astype(int)),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
                # cv2.imshow('MediaPipe Holistic', cv2.flip(image, 1))
        cv2.imshow('Mediapipe Holistic', image)  # 取消镜面翻转
        if cv2.waitKey(5) == ord('q'):
            break
cap.release()

评论

user-avatar
  • 三春牛-创客

    三春牛-创客2023.03.04

    赞赞赞

    0
    • 三春牛-创客

      三春牛-创客2023.03.04

      厉害厉害

      0