meiyao 发表于 2026-1-20 11:11:40

汽车大赛+AI手识识别提交贴

本帖最后由 meiyao 于 2026-1-20 14:06 编辑

一、功能使用摄像头实现AI手识检测识别,使用树莓派摄像头捕捉实时视频流。对视频流进行处理,然后再进行对比,是否是正确的手势,使用背景减除算法去除背景干扰,利用OpenCV的手势识别算法检测和跟踪手势,根据手势识别结果进行相应的操作控制灯光,或者对应的执行设备,舵机等装置。进行物体识别,或者是进行场景灯光调节,当正在看书时,出现阅读模式,点亮阅读灯,如果正在玩手机时,点切换为游戏模式,高亮白光灯。
二、模式介绍1、手识:1,2,32、模式:无人模式,阅读模式,手机模式3、灯光模式:白光,蓝光,**光
设置开机自动启动 上电后等几十秒就可以手势操作了对准摄像头 手正对摄像头30厘米左右就行 这个识别范围比较大手势1读书模式 暖色灯 舵机动手势2手机模式 冷色灯 舵机不动其他手势 保持灯的亮度和颜色无手势无人模式 灯光会暗
三、主要器件树莓派5-- PI5(4核2.4GHz Cortex-A76)-- 支持4K视频解码、硬件PWM、原生USB3.0(高速摄像头数据传输)舵机--SG90(9g微型舵机)-- 扭矩2.5kg·cm(5V供电)、响应速度0.12s/60°、控制信号周期20ms(50Hz)灯--WS2812(5050 RGB LED)--单线通信(NeoPixel协议)、24位真彩色(1677万色)、支持级联(最大100颗)串口屏--TJC804X550_011(4.3寸)--分辨率480×272、TJC自定义协议、支持触摸交互、预留UART接口(波特率115200)摄像头--九目4K USB免驱动--分辨率3840×2160@30FPS、自动对焦、UVC协议兼容(Linux原生支持)
舵机物理引脚:GPIO 12树莓派40针引脚:引脚32(GPIO 12)功能:PWM信号输出,控制舵机角度电压:3.3V PWM信号串口屏树莓派默认串口引脚:TXD (发送)       GPIO14      引脚8RXD (接收)      GPIO15   引脚10GND    引脚6(或任何GND)

四、连接原理图graph LR    PI5[树莓派5] -->|GPIO18(PWM)| SG90[舵机]    PI5-->|GPIO12(PWM)| WS2812[灯带]    PI5-->|UART(TX/RX)| TJC[串口屏]    PI5-->|USB3.0| Camera五、软件框架图框架图
软件工作流程图
六、代码

初始化串口通信
ser = serial.Serial(
   port='/dev/serial0',# 树莓派默认串口设备
   baudrate=9600,      # 波特率
   timeout=1             # 读取超时时间(秒)
)

串口通信数据定义
格式说明:每条指令以0xFF 0xFF 0xFF结尾
book_data = bytes([
    0x70,0x61, 0x67, 0x65, 0x30, 0x2E, 0x70, 0x30, # "page0.p0"
    0x2E,0x70, 0x69, 0x63, 0x3D, 0x30,             # ".pic=0"
    0xFF,0xFF, 0xFF                                 # 结束标志
    ])# 对应"书本"命令,显示图片0

phone_data = bytes([
    0x70,0x61, 0x67, 0x65, 0x30, 0x2E, 0x70, 0x30, # "page0.p0"
    0x2E,0x70, 0x69, 0x63, 0x3D, 0x31,             # ".pic=1"
    0xFF,0xFF, 0xFF                                 # 结束标志
    ])# 对应"手机"命令,显示图片1

nobody_data = bytes([
    0x70,0x61, 0x67, 0x65, 0x30, 0x2E, 0x30, 0x30, # "page0.p0"
    0x2E,0x70, 0x69, 0x63, 0x3D, 0x32,             # ".pic=2"
    0xFF,0xFF, 0xFF                                 # 结束标志
    ])# 对应"无人"状态,显示图片2

DEBOUNCE_TIME = 1 # 防抖时间(秒),手势需稳定1秒才触发动作

#####################################
--- 舵机(Servo)控制模块 ---
#####################################

初始化舵机,连接到GPIO 12引脚
脉冲宽度范围:0.5ms-2.5ms,对应-90°到+90°
servo = Servo(12, min_pulse_width=0.5/1000,max_pulse_width=2.5/1000)

def servo_move():
   """
    控制舵机旋转动作
    舵机顺时针(CCW)旋转0.25秒后停止
   """
   servo.value = 1       # 设置为最大值,舵机以最快速度逆时针旋转
   print("CCW fast - 舵机逆时针旋转")
   sleep(0.25)         # 持续旋转0.25秒

   servo.value = 0       # 设置为0,舵机停止
   print("Stopped - 舵机停止")
   sleep(0.2)            # 短暂停顿

#####################################
--- LED控制模块(SPI版本)---
#####################################

LED配置参数
LED_COUNT = 4             # LED灯珠数量
LED_BRIGHTNESS = 0.7      # 正常亮度(范围0.0-1.0)
DIM_BRIGHTNESS = 0.05   # 休眠模式亮度

初始化SPI总线连接NeoPixel LED
spi_bus = board.SPI()
pixels = neopixel.NeoPixel_SPI(
   spi_bus,               # SPI总线
   LED_COUNT,             # LED数量
   brightness=LED_BRIGHTNESS,# 初始亮度
   pixel_order=neopixel.GRB,   # LED颜色顺序(Green-Red-Blue)
   auto_write=False       # 手动控制刷新
)

def set_color(r, g, b):
   """
    设置所有LED灯的颜色
    参数:
      r: 红色分量 (0-255)
      g: 绿色分量 (0-255)
      b: 蓝色分量 (0-255)
   """
    for i inrange(LED_COUNT):
       pixels = (r, g, b)
   pixels.show()# 更新LED显示

def set_brightness(value):
   """
    设置LED亮度
    参数:
       value: 亮度值(0.0-1.0)
   """
   pixels.brightness = value
   pixels.show()

#####################################
--- Mediapipe手势识别配置 ---
#####################################

初始化Mediapipe手部识别
mp_hands = mp.solutions.hands

手指关键点索引定义
FINGER_TIPS =    # 大拇指、食指、中指、无名指、小指尖端
FINGER_DIPS =    # 对应手指的中间关节

def is_finger_up(hand, tip, dip):
   """
    判断手指是否伸直
    原理: 指尖的y坐标小于中间关节的y坐标时,手指向上
    注意: Mediapipe坐标系原点在左上角,y轴向下
   """
    returnhand.landmark.y < hand.landmark.y

#####################################
--- 主程序循环 ---
#####################################

初始化摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)   # 设置分辨率320x240
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)# 降低分辨率提高处理速度

手势状态变量
last_gesture = None             # 最新检测到的手势
last_executed_gesture = None    # 上一次执行过动作的手势
gesture_start_time = time.time()# 手势开始时间

current_color = (255, 255, 255)# 当前LED颜色,初始为白色

初始化Mediapipe手部识别模型
with mp_hands.Hands(
   max_num_hands=1,            # 最多识别1只手
   min_detection_confidence=0.5,# 检测置信度阈值
   min_tracking_confidence=0.5    # 跟踪置信度阈值
) as hands:

    # 主循环
    whileTrue:
      # 读取摄像头帧
      ok,frame = cap.read()
      ifnot ok:
         continue# 读取失败则跳过

      # 将BGR转换为RGB(Mediapipe需要RGB格式)
      rgb =cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

      # 手势识别处理
       result = hands.process(rgb)

       gesture = None      # 当前检测到的手势
       hand_present = False# 是否有手部被检测到

      #-------------------------
      # 1. 手势检测逻辑
      #-------------------------
      ifresult.multi_hand_landmarks:# 检测到手部
         hand_present = True
         hand = result.multi_hand_landmarks # 只处理第一只手

            #计算除大拇指外的手指伸直数量
         fingers_up = 0
         for tip, dip in zip(FINGER_TIPS, FINGER_DIPS):
               if is_finger_up(hand, tip, dip):
                   fingers_up += 1

            #手势映射:
            #1根手指伸直-> 手势1
            #2根手指伸直-> 手势2
         if fingers_up == 1:
               gesture = 1
         elif fingers_up == 2:
               gesture = 2
            #其他手指数量视为无效手势

      #-------------------------
      # 2. 无手状态处理(休眠模式)
      #-------------------------
      ifnot hand_present:
         set_brightness(DIM_BRIGHTNESS)# 降低亮度进入休眠
         last_gesture = None
         last_executed_gesture = None
         ser.write(nobody_data)# 发送无人状态到串口设备
         continue# 跳过**处理

      #-------------------------
      # 3. 手部刚出现处理(唤醒模式)
      #-------------------------
      iflast_gesture is None:# 手部刚出现
         set_brightness(LED_BRIGHTNESS)# 恢复亮度

            #根据手势设置不同颜色
         if gesture == 1:
               current_color = (255, 150, 80)# 橙色
               set_color(*current_color)
         elif gesture == 2:
               current_color = (100, 150, 255)#蓝色
               set_color(*current_color)
         else:
               # 无效手势保持原颜色
               set_color(*current_color)

            #更新手势状态和时间
         last_gesture = gesture
         gesture_start_time = time.time()
         continue

      #-------------------------
      # 4. 手势变化检测
      #-------------------------
      ifgesture != last_gesture:# 手势发生变化
         last_gesture = gesture
         gesture_start_time = time.time() # 重置计时器
         print(f"检测到手势变化 →{gesture}")
         continue

      #-------------------------
      # 5. 手势稳定触发(防抖处理)
      #-------------------------
      iftime.time() - gesture_start_time >= DEBOUNCE_TIME:
            #如果与上次执行的手势相同,不重复执行
         if gesture == last_executed_gesture:
               continue

            #记录本次执行的手势
         last_executed_gesture = gesture

            #根据手势执行对应动作
         if gesture == 1:
               print("执行:手势1动作(书本)")
               ser.write(book_data)# 发送书本命令
               current_color = (255, 150, 80)# 橙色
               set_color(*current_color)
               # 在新线程中控制舵机,避免阻塞主循环
               t = threading.Thread(target=servo_move, daemon=True)
               t.start()

         elif gesture == 2:
               print("执行:手势2动作(手机)")
               ser.write(phone_data)# 发送手机命令
               current_color = (100, 150, 255)#蓝色
               set_color(*current_color)
         else:
               continue# 无效手势不执行
释放摄像头资源
cap.release()
释放舵机资源
servo.angle = None

七、实物连接图



八、视频PI5手识识别_哔哩哔哩_bilibili

eefocus_3914144 发表于 5 天前

牛呀,太强了!
页: [1]
查看完整版本: 汽车大赛+AI手识识别提交贴