树莓派opencv手势识别点亮led灯或响蜂鸣器 (附完整代码)
前言
材料:树莓派 摄像头 SG90舵机两个 PCA9685拓展板 led小灯 蜂鸣器模块
一、树莓派引脚介绍
树莓派引脚对照表
可以看到一共有三种定义方式 分别是Wiring Pi编码,BCM编码和BOARD物理引脚编码。
1.1引脚设置
在最开始终端输入
sudo raspi-config
进入设置 后找到
Interfacing Options
进入 找到
Remote GPIO
开启GPIO
二、代码书写
2.1引入库
在最开始导入库
import RPi.GPIO as GPIO #1导入引脚库 GPIO.setmode(GPIO.BOARD) # 2定义引脚方式 此处为BOARD编码 GPIO.setup(channel, GPIO.OUT) # 3建立通道 该函数需要两个参数 第一个为引脚编号 第二个为模式定义 #此处为输出 GPIO.output(7, True)#4 驱动通道 GPIO.cleanup()#5清除 释放资源
2.2示例代码点亮led 响蜂鸣器
#导入gpio模块 调用引脚 import RPi.GPIO as GPIO #初始化引脚模式为BOARD 屏蔽警告 GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) #引脚定义 蜂鸣器接的35引脚 led接的37引脚 beep=35 led=37 GPIO.setup(beep,GPIO.OUT)#设置gpio模式为输出 GPIO.setup(led,GPIO.OUT) GPIO.output(led,GPIO.HIGH)#开灯 GPIO.output(led,GPIO.LOW)#关灯 GPIO.output(beep,GPIO.HIGH)#蜂鸣器响 GPIO.output(beep,GPIO.LOW)#蜂鸣器关
三完整代码 图片
#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ * @par Copyright (C): 2010-2020, hunan CLB Tech * @file 50_Hand_gestures.py * @version V2.0 * @details * @par History @author: zhulin """ import cv2 import numpy as np import math import time import sys import Adafruit_PCA9685#导入PCA9685模块 #设置编码为utf-8 import importlib importlib.reload(sys) #sys.setdefaultencoding('utf8') #导入gpio模块 调用引脚 import RPi.GPIO as GPIO #初始化引脚模式为BOARD 屏蔽警告 GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) #引脚定义 蜂鸣器接的35引脚 led接的37引脚 beep=35 led=37 GPIO.setup(beep,GPIO.OUT)#设置gpio模式为输出 GPIO.setup(led,GPIO.OUT) #初始化PCA9685和舵机 servo_pwm = Adafruit_PCA9685.PCA9685() # 实例话舵机云台 # 设置舵机初始值,可以根据自己的要求调试 servo_pwm.set_pwm_freq(60) # 设置频率为60HZ servo_pwm.set_pwm(5,0,325) # 底座舵机 servo_pwm.set_pwm(4,0,325) # 倾斜舵机 time.sleep(1) #初始化摄像头并设置阙值 cap = cv2.VideoCapture(0) cap.set(3,120) cap.set(4,160) while(1): try: #an error comes if it does not find anything in window as it cannot find contour of max area #therefore this try error statement ret, frame = cap.read() frame=cv2.flip(frame,1) kernel = np.ones((3,3),np.uint8) #define region of interest roi=frame[0:300, 0:300] cv2.rectangle(frame,(0,0),(300,300),(0,255,0),0) hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # define range of skin color in HSV lower_skin = np.array([0,20,70], dtype=np.uint8) upper_skin = np.array([20,255,255], dtype=np.uint8) #extract skin colur imagw mask = cv2.inRange(hsv, lower_skin, upper_skin) #extrapolate the hand to fill dark spots within mask = cv2.dilate(mask,kernel,iterations = 4) #blur the image mask = cv2.GaussianBlur(mask,(5,5),100) #find contours _,contours,hierarchy= cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #find contour of max area(hand) cnt = max(contours, key = lambda x: cv2.contourArea(x)) #approx the contour a little epsilon = 0.0005*cv2.arcLength(cnt,True) approx= cv2.approxPolyDP(cnt,epsilon,True) #make convex hull around hand hull = cv2.convexHull(cnt) #define area of hull and area of hand areahull = cv2.contourArea(hull) areacnt = cv2.contourArea(cnt) #find the percentage of area not covered by hand in convex hull arearatio=((areahull-areacnt)/areacnt)*100 #find the defects in convex hull with respect to hand hull = cv2.convexHull(approx, returnPoints=False) defects = cv2.convexityDefects(approx, hull) # l = no. of defects l=0 #code for finding no. of defects due to fingers for i in range(defects.shape[0]): s,e,f,d = defects[i,0] start = tuple(approx[s][0]) end = tuple(approx[e][0]) far = tuple(approx[f][0]) pt= (100,180) # find length of all sides of triangle a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2) b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2) c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2) s = (a+b+c)/2 ar = math.sqrt(s*(s-a)*(s-b)*(s-c)) #distance between point and convex hull d=(2*ar)/a # apply cosine rule here angle = math.acos((b**2 + c**2 - a**2)/(2*b*c)) * 57 # ignore angles > 90 and ignore points very close to convex hull(they generally come due to noise) if angle <= 90 and d>30: l += 1 cv2.circle(roi, far, 3, [255,0,0], -1) #draw lines around hand cv2.line(roi,start, end, [0,255,0], 2) l+=1 #print corresponding gestures which are in their ranges font = cv2.FONT_HERSHEY_SIMPLEX if l==1: if areacnt<2000: cv2.putText(frame,'Put hand in the box',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) else: if arearatio<12: cv2.putText(frame,'0',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) elif arearatio<17.5: cv2.putText(frame,'Best of luck',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) else: cv2.putText(frame,'1',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) GPIO.output(led,GPIO.HIGH)#开灯 elif l==2: cv2.putText(frame,'2',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) GPIO.output(led,GPIO.LOW)#关灯 elif l==3: if arearatio<27: cv2.putText(frame,'3',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) GPIO.output(beep,GPIO.HIGH)#蜂鸣器响 else: pass#屏蔽ok手势 #cv2.putText(frame,'ok',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) elif l==4: cv2.putText(frame,'4',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) GPIO.output(beep,GPIO.LOW)#蜂鸣器关 elif l==5: cv2.putText(frame,'5',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) GPIO.output(led,GPIO.HIGH)#开灯 time.sleep(0.5) GPIO.output(beep,GPIO.HIGH)#蜂鸣器响 time.sleep(0.5) GPIO.output(beep,GPIO.LOW)#蜂鸣器关 time.sleep(0.5) GPIO.output(led,GPIO.LOW)#关灯 time.sleep(0.5) elif l==6: cv2.putText(frame,'reposition',(0,50), font, 2, (0,0,255), 3, cv2.LINE_AA) else : cv2.putText(frame,'reposition',(10,50), font, 2, (0,0,255), 3, cv2.LINE_AA) #show the windows cv2.imshow('mask',mask) cv2.imshow('frame',frame) except: pass k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows() cap.release()
实现功能 :
识别手势1 伸一个指头 点亮LED 灯
识别手势2 伸两个指头 关闭LED 灯
识别手势3 伸三个指头 响蜂鸣器
识别手势4 伸四个指头 蜂鸣器关
识别手势5 伸5个指头 声光警报
成品展示:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
python缩进和二维列表的解包
这两天博主遇见了一道题目 如下: 现在给你N个数(0<N<1000),现在要求你写出一个程序,找出这N个数中的所有素数,并求和。 输入 第一行给出整数M(0<M<10)代表多少组测试数据 每组测试数据第一行给你N,代表该组测试数据的数量。 接下来的N个数为要测试的数据,每个数小于1000 输出 每组测试数据结果占一行,输出给出的测试数据的所有素数和 输入 3 5 1 2 3 4 5 8 11 12 13 14 15 16 17 18 10 21 22 23 24 25 26 27 28 29 30 输出 10 41 52 博主在写的过程中是这么想的 既然要素数求和 那就要先求素数 用一些代码求素数(1不是素数) 然后进行第二步 规范输入输出 这里的多组输入我选择用map直接给列表a传参 这个方法我是从学长那学到的 。传参,筛选出素数后求和 把最后结果当成一个列表存进大列表中 。这里博主想用一个二维列表 ,这样就可以存储上多组数据并一起输出, 最后用解包的办法把二维列表里的一维列表遍历出来 。 (我对于解包了解不是太全面 欢迎大神补充 ) 这是我第一次的代码 fr...
- 下一篇
树莓派4B通过16路PWM输出的PCA9685模块控制舵机(机械臂)附完整代码
树莓派4B通过16路PWM输出的PCA9685模块控制舵机(机械臂)附完整代码 文章目录 树莓派4B通过16路PWM输出的PCA9685模块控制舵机(机械臂)附完整代码 一、 Servo Driver HAT拓展板介绍 二、2开启I2C 三、安装相关驱动 四、通过代码驱动舵机(机械臂) 4.1舵机的初始位置校准 4.2完整代码 内容参考微雪课堂 一、 Servo Driver HAT拓展板介绍 Servo Driver HAT是基于树莓派而设计的PWM/舵机扩展板,通过PCA9685芯片扩展16路舵机控制或者PWM输出,每个通道12位分辨率。通过I2C接口控制,无需占用额外的引脚。板载5V稳压芯片,可接电池供电,最大输出3A电流。适用于控制机械手臂,以及各种舵机机器人。 输入电压VIN:6V~12V 舵机电压:5V 逻辑电压:3.3V 板子可以从树莓派上取电不需要额外供电。 也可以通过右边绿色端子VIN接电池供电,输入电压范围6V~12V。经过板载的5V稳压芯片输出5V电源给舵机和树莓派供电,最大输出电流3A。 A0~A4可以设置PCA9685芯片的I2C设备地址,可以同时接多个Ser...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 2048小游戏-低调大师作品
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果