2024-9-10 17:27:28 [显示全部楼层]
22685浏览
查看: 22685|回复: 0

[项目] 用Mediapipe来通过手势实现灯光调光

[复制链接]
本帖最后由 gada888 于 2024-9-23 17:29 编辑

通过手势实现灯光调光
前言:完成这样一个项目的意义在于什么呢,在于你会发现整个项目的核心居然是两个数学计算公式。所以有人说‘’AI的尽头是数学‘’不无道理。当下在AI代码助手的帮助下,学习代码这个工作的意义其实在弱化了。我们更多的关注点应该在创意和数学上。

mediapipe是机器视觉的一个套件。在opencv的框架下,可以利用mediapipe的高互动性来做一些有趣的项目。今天我们用个简化的mediapipe库文件。cvzone来完成一个手势控制灯光的项目。

用Mediapipe来通过手势实现灯光调光图1
为了让大家对这个项目的核心内容有个快速的了解。这里发布一个教学视频。视频里有对核心代码部分的解释。因为时间关系,也因为代码注释很完整,视频讲解就不对mediapipe和opencv部分进行解释,因此它不是初学者项目。需要学习者有python,opencv和机器视觉知识的基础储备。


下面是视频链接:


下面是源代码:并且提供了代码注释。

  1. from cvzone.HandTrackingModule import HandDetector
  2. import cv2
  3. #Arduino Declare
  4. import time
  5. from pinpong.board import Board,Pin
  6. Board("uno","COM3").begin()
  7. pwm0 = Pin(Pin.D7, Pin.PWM)
  8. # Initialize the webcam to capture video
  9. # The '2' indicates the third camera connected to your computer; '0' would usually refer to the built-in camera
  10. cap = cv2.VideoCapture(0)
  11. length = 0
  12. # Initialize the HandDetector class with the given parameters
  13. detector = HandDetector(staticMode=False, maxHands=2, modelComplexity=1, detectionCon=0.5, minTrackCon=0.5)
  14. # Continuously get frames from the webcam
  15. while True:
  16.     # Capture each frame from the webcam
  17.     # 'success' will be True if the frame is successfully captured, 'img' will contain the frame
  18.     success, img = cap.read()
  19.     # Find hands in the current frame
  20.     # The 'draw' parameter draws landmarks and hand outlines on the image if set to True
  21.     # The 'flipType' parameter flips the image, making it easier for some detections
  22.     hands, img = detector.findHands(img, draw=True, flipType=True)
  23.     # Check if any hands are detected
  24.     if hands:
  25.         # Information for the first hand detected
  26.         hand1 = hands[0]  # Get the first hand detected
  27.         lmList1 = hand1["lmList"]  # List of 21 landmarks for the first hand
  28.         bbox1 = hand1["bbox"]  # Bounding box around the first hand (x,y,w,h coordinates)
  29.         center1 = hand1['center']  # Center coordinates of the first hand
  30.         handType1 = hand1["type"]  # Type of the first hand ("Left" or "Right")
  31.         # Count the number of fingers up for the first hand
  32.         fingers1 = detector.fingersUp(hand1)
  33.         print(f'H1 = {fingers1.count(1)}', end=" ")  # Print the count of fingers that are up
  34.         # Calculate distance between specific landmarks on the first hand and draw it on the image
  35.         length, info, img = detector.findDistance(lmList1[4][0:2], lmList1[8][0:2], img, color=(255, 0, 255),
  36.                                                   scale=10)
  37.         # Check if a second hand is detected
  38.         if len(hands) == 2:
  39.             # Information for the second hand
  40.             hand2 = hands[1]
  41.             lmList2 = hand2["lmList"]
  42.             bbox2 = hand2["bbox"]
  43.             center2 = hand2['center']
  44.             handType2 = hand2["type"]
  45.             # Count the number of fingers up for the second hand
  46.             fingers2 = detector.fingersUp(hand2)
  47.             print(f'H2 = {fingers2.count(1)}', end=" ")
  48.             # Calculate distance between the index fingers of both hands and draw it on the image
  49.             length, info, img = detector.findDistance(lmList1[4][0:2], lmList2[8][0:2], img, color=(255, 0, 0),
  50.                                                       scale=10)
  51.         length = int((length // 10) * 10 - 30)
  52.         if length < 0: length = 0
  53.         if length > 100: length = 100
  54.         print(length)
  55.         pwm0.write_analog(length)
  56.     #lengthConverted = int(np.interp(length, [0, 200], [398, 150]))
  57.     print(" ")  # New line for better readability of the printed output
  58.     # Display the image in a window
  59.     cv2.imshow("Image", img)
  60.     # Keep the window open and update it for each frame; wait for 1 millisecond between frames
  61.     cv2.waitKey(1)
复制代码


这个项目主要用食指和拇指的缩放来进行灯的明暗控制。软件控制硬件是用的DFRobot的pinpong库。感谢pinpong库,让我们能够完成软硬件互动项目。程序通过摄像头来对双手进行辨识。它会提取并且绘制手型框。它能识别左右手,用H1和H2表示。它可以识别手指。最关键是识别缩放。因为缩放是变量值。需要计算和公式才能达到我们的目的。

关于软件部分,我是参考了cvzone的官方手势识别案例,换句话说,人家把框架搭好了。我可以按照自己的意图去实现更个性化的目的。在这个案例里,我调用了pinpong库的pwm0函数功能。那问题来了。我怎么知道它的功能是怎么使用的呢?我是在下列地址找到了pinpong原始档案。https://pypi.org/project/pinpong/#files
找到pwm文件。
------------------------------
根据下面两条语句:
from pinpong.board import Board,Pin #导入PWM类实现模拟输出
pwm0.write_analog(i) #设置模拟输出值

----------------------
从而知道了取值范围是0-100和模拟输出的值范围0-255,0-255也就是0-5V之间的电压。通过AD转换,就是0-1023.这个不断变化的值给到Arduino的PWM引脚,这个引脚通过了mosfet进行了放大。给到了12V的灯泡。于是呈现了我视频里要呈现的0-12V电压变压的效果。==========
  • 下面是官方提供的pinpong pwm源文件
  1. # -*- coding: utf-8 -*-
  2. #实验效果:使用按钮控制LED模块亮度
  3. #接线:使用windows或linux电脑连接一块arduino主控板,主控板D6接一个LED灯模块
  4. import time
  5. from pinpong.board import Board,Pin #导入PWM类实现模拟输出
  6. Board("uno").begin()  #初始化,选择板型和端口号,不输入端口号则进行自动识别
  7. #Board("uno","COM36").begin()  #windows下指定端口初始化
  8. #Board("uno","/dev/ttyACM0").begin()   #linux下指定端口初始化
  9. #Board("uno","/dev/cu.usbmodem14101").begin()   #mac下指定端口初始化
  10. pwm0 = Pin(Pin.D6, Pin.PWM)
  11. while True:
  12.   for i in range(100): #从0到255循环
  13.     pwm0.write_analog(i)  #设置模拟输出值
  14.     print(i)
  15.     time.sleep(0.05)
复制代码


  • 下面讲一讲场效应模块mosfet的连线方式。先看照片
用Mediapipe来通过手势实现灯光调光图2


  • 下面是连线图。
  • 从5V到12V,三极管已经无法应对,需要能应付大功率的场效应管登场了。灯泡选的是12V的灯泡。arduino uno无法直接点亮,它需要通过场效应管放大5V电压到12V才能实现。
用Mediapipe来通过手势实现灯光调光图5

  • 下面是场效应管模块原理图
用Mediapipe来通过手势实现灯光调光图3用Mediapipe来通过手势实现灯光调光图4











您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail