树莓派摄像头手势识别:实时显示手势类型

使用树莓派、摄像头模块和 Python 编程语言,可以实现实时手势识别,并在摄像头上显示识别出的手势类型。以下是详细的步骤和代码示例:

1. 安装摄像头模块

在树莓派上连接摄像头模块,然后在终端中输入以下命令进行安装:

sudo raspi-config

选择 Interfacing Options -> Camera -> Enable,然后重启树莓派。

2. 安装 OpenCV

使用以下命令在树莓派上安装 OpenCV:

sudo apt-get install python-opencv

3. 编写代码

首先,需要导入所需的库和模块:

import cv2
import numpy as np

然后,定义一些变量和参数:

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
kernel = np.ones((3, 3), np.uint8)

其中,cap 为摄像头对象,kernel 为用于腐蚀和膨胀的内核。

接下来,定义函数来识别手势:

def recognize_gesture(frame):
    # 转换为灰度图像
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 高斯模糊
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    # 二值化
    ret, thresh = cv2.threshold(blur, 70, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # 腐蚀和膨胀
    erosion = cv2.erode(thresh, kernel, iterations=1)
    dilation = cv2.dilate(erosion, kernel, iterations=1)
    # 查找轮廓
    contours, hierarchy = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 获取最大轮廓
    cnt = max(contours, key=lambda x: cv2.contourArea(x))
    # 判断手势类型
    if len(cnt) > 0:
        hull = cv2.convexHull(cnt, returnPoints=False)
        defects = cv2.convexityDefects(cnt, hull)
        if defects is not None:
            # 绘制轮廓和凸包
            cv2.drawContours(frame, [cnt], -1, (0, 255, 0), 2)
            cv2.drawContours(frame, [hull], -1, (0, 0, 255), 2)
            # 统计凸缺陷
            count_defects = 0
            for i in range(defects.shape[0]):
                s, e, f, d = defects[i, 0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                a = np.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
                b = np.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
                c = np.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
                angle = np.arccos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))
                if angle <= np.pi / 2:
                    count_defects += 1
                    cv2.circle(frame, far, 3, (0, 0, 255), -1)
            # 判断手势类型
            if count_defects == 0:
                cv2.putText(frame, 'Rock', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            elif count_defects == 1:
                cv2.putText(frame, 'Scissors', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            elif count_defects == 2:
                cv2.putText(frame, 'Paper', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            else:
                cv2.putText(frame, 'Unknown', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)

该函数接受一个帧对象作为输入参数,然后执行以下步骤:

  1. 将图像转换为灰度图像。
  2. 对图像进行高斯模糊。
  3. 对图像进行二值化。
  4. 对二值化图像进行腐蚀和膨胀。
  5. 查找图像中的轮廓。
  6. 获取最大的轮廓。
  7. 计算轮廓的凸缺陷。
  8. 绘制轮廓和凸包。
  9. 统计凸缺陷的数量并判断手势类型。
  10. 在图像上绘制手势类型。

最后,在一个无限循环中获取摄像头帧并调用 recognize_gesture 函数来识别手势:

while True:
    ret, frame = cap.read()
    recognize_gesture(frame)
    cv2.imshow('frame', frame)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

4. 运行程序

运行程序后,摄像头会打开并开始识别手势。在摄像头上对着它做出不同的手势,程序会在摄像头上显示出手势类型。

完整代码:

import cv2
import numpy as np

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
kernel = np.ones((3, 3), np.uint8)

def recognize_gesture(frame):
    # 转换为灰度图像
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 高斯模糊
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    # 二值化
    ret, thresh = cv2.threshold(blur, 70, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # 腐蚀和膨胀
    erosion = cv2.erode(thresh, kernel, iterations=1)
    dilation = cv2.dilate(erosion, kernel, iterations=1)
    # 查找轮廓
    contours, hierarchy = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 获取最大轮廓
    cnt = max(contours, key=lambda x: cv2.contourArea(x))
    # 判断手势类型
    if len(cnt) > 0:
        hull = cv2.convexHull(cnt, returnPoints=False)
        defects = cv2.convexityDefects(cnt, hull)
        if defects is not None:
            # 绘制轮廓和凸包
            cv2.drawContours(frame, [cnt], -1, (0, 255, 0), 2)
            cv2.drawContours(frame, [hull], -1, (0, 0, 255), 2)
            # 统计凸缺陷
            count_defects = 0
            for i in range(defects.shape[0]):
                s, e, f, d = defects[i, 0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                a = np.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
                b = np.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
                c = np.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
                angle = np.arccos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))
                if angle <= np.pi / 2:
                    count_defects += 1
                    cv2.circle(frame, far, 3, (0, 0, 255), -1)
            # 判断手势类型
            if count_defects == 0:
                cv2.putText(frame, 'Rock', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            elif count_defects == 1:
                cv2.putText(frame, 'Scissors', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            elif count_defects == 2:
                cv2.putText(frame, 'Paper', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)
            else:
                cv2.putText(frame, 'Unknown', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2)

while True:
    ret, frame = cap.read()
    recognize_gesture(frame)
    cv2.imshow('frame', frame)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

注意:

  • 代码中的 70 是二值化阈值,可以根据实际情况调整。
  • 手势识别算法可以进一步优化,例如使用更复杂的特征提取方法。
  • 代码中引号已修改为单引号。
树莓派摄像头手势识别:实时显示手势类型

原文地址: https://www.cveoy.top/t/topic/nSSF 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录