云天 发表于 2022-4-11 15:49:09

LattePanda+Mind+摄像头玩AI贪吃蛇

本帖最后由 云天 于 2022-4-11 15:49 编辑


【项目说明】
今天和大家分享一下如何使用LattePanda+Mind+ mediapipe+opencv 自制贪吃蛇小游戏。规则:食指指尖控制蛇头,指尖每接触到黄色方块,计数加一,蛇身变长,方块随机切换位置。如果指尖停止移动,或者移动过程中蛇头撞到蛇身,那么游戏结束。点击键盘上的R键重新开始游戏。
【项目准备】1、CVzone简介
OpenCV是一个开源计算机视觉库,可提供播放不同图像和视频流的权限,还有助于端到端项目,如对象检测、人脸检测、对象跟踪等。
MediaPipe是一个主要用于构建音频、视频或任何时间序列数据的框架。在 MediaPipe 框架的帮助下,我们可以为不同的媒体处理功能构建管道。
CVzone是一个计算机视觉包,可以让我们轻松运行像人脸检测、手部跟踪、姿势估计等,以及图像处理和其他 AI 功能。它的核心是使用 OpenCV 和 MediaPipe 库。
2、安装所需的模块。


-- pip install OpenCV-python

-- pip install cvzone

-- pip install mediapipe
在Mind+中使用“库管理”——“PIP”模式安装以上这三个库






3、首先,让我们检查一下LattePanda安装的网络摄像头是否工作正常。

import cv2

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)

while True:
success, img = cap.read()
cv2.imshow("Image", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
    break
4、调用Mediapipe,识别手部关键点

21个手部关键点信息如下,本节我们主要研究食指指尖'8'的坐标(x,y)信息。


import cvzone
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector

cap = cv2.VideoCapture(0)   # 0代表自己电脑的摄像头
cap.set(3, 1280)      # 宽
cap.set(4, 720)         # 高

detector = HandDetector(detectionCon=0.8, maxHands=1)

# 处理每一帧图像
while True:
    success, img = cap.read()
    # 翻转图像,使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, 1)      # 将手水平翻转
    hands, img = detector.findHands(img, flipType=False)    # 左手是左手,右手是右手,映射正确
    cv2.imshow("Image", img)
    cv2.waitKey(1)
5、观察手的信息

import cvzone
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector

cap = cv2.VideoCapture(0)   # 0代表自己电脑的摄像头
cap.set(3, 1280)      # 宽
cap.set(4, 720)         # 高

detector = HandDetector(detectionCon=0.8, maxHands=1)

# 处理每一帧图像
while True:
    success, img = cap.read()
    # 翻转图像,使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, 1)      # 将手水平翻转
    hands, img = detector.findHands(img, flipType=False)    # 左手是左手,右手是右手,映射正确

    print(hands)

    cv2.imshow("Image", img)
    cv2.waitKey(1)
输出信息

[{‘lmList’: [, , , , , , , , , , , , , , , , , , , , ], ‘bbox’: (838, 403, 250, 252), ‘center’: (963, 529), ‘type’: ‘Left’}]



【硬件组装】






【程序测试】
运行Mind+

测试识别手部关键点


【完整程序】

import cv2
import cvzone
from matplotlib.cbook import pts_to_midstep
import numpy as np
from cvzone.HandTrackingModule import HandDetector # 导入手部检测模块
import math
import random
   
# 构造一个贪吃蛇移动的类
class SnakeGameClass:
   
   #(一)初始化
   def __init__(self):
   
         self.score = 0 # 积分器
         self.points = [] # 蛇的身体的节点坐标
         self.lengths = [] # 蛇身各个节点之间的坐标
         self.currentLength = 0 # 当前蛇身长度
         self.allowedLength = 150 # 没吃东西时,蛇的总长度
         self.previousHead = (0,0) # 前一个蛇头节点的坐标
   
         self.foodPoint = (0,0) # 食物的起始位置
         self.randomFoodLocation() # 随机改变食物的位置
   
         self.gameover = False # 蛇头撞到蛇身,变成True,游戏结束
   
   #(二)食物随机出现的位置
   def randomFoodLocation(self):
         # x在100至1000之间,y在100至600之间,随机取一个整数
         self.foodPoint = random.randint(100, 1000), random.randint(100, 600)
   
   #(三)更新增加蛇身长度
   def update(self, imgMain, currentHead): # 输入图像,当前蛇头的坐标
   
         # 游戏结束,显示文本
         if self.gameover:
             cvzone.putTextRect(imgMain, 'GameOver', , 5, 3, colorR=(0,255,255), colorT=(0,0,255))
             cvzone.putTextRect(imgMain, f'Score:{self.score}', , 5, 3, colorR=(255,255,0))
             cvzone.putTextRect(imgMain, f"Press Key 'R' to Restart", , 4, 3, colorR=(0,255,0), colorT=(255,0,0))
   
         else:
             px, py = self.previousHead # 获得前一个蛇头的x和y坐标
             cx, cy = currentHead # 当前蛇头节点的x和y坐标
            
             # 添加当前蛇头的坐标到蛇身节点坐标列表中
             self.points.append()
   
             # 计算两个节点之间的距离
             distance = math.hypot(cx-px, cy-py) # 计算平方和开根
             # 将节点之间的距离添加到蛇身节点距离列表中
             self.lengths.append(distance)
             # 增加当前蛇身长度
             self.currentLength += distance
   
             # 更新蛇头坐标
             self.previousHead = (cx,cy)
   
             #(四)减少蛇尾长度,即移动过程中蛇头到蛇尾的长度不大于150
             if self.currentLength > self.allowedLength:
   
               # 遍历所有的节点线段长度。新更新的蛇头索引在列表后面,蛇尾的索引在列表前面
               for i, length in enumerate(self.lengths):
   
                     # 从蛇尾到蛇头依次减线段长度,得到的长度是否满足要求
                     self.currentLength -= length
   
                     # 从列表中删除蛇尾端的线段长度,以及蛇尾节点
                     self.lengths.pop(i)
                     self.points.pop(i)
   
                     # 如果当前蛇身长度小于规定长度,满足要求,退出循环
                     if self.currentLength < self.allowedLength:
                      break
            
             #(五)绘制得分板
             cvzone.putTextRect(imgMain, f'Score:{self.score}', , 4, 3, colorR=(255,255,0))
   
             #(六)检查蛇是否吃了食物
             rx, ry = self.foodPoint # 得到食物的中心点坐标位置
            
             # 绘制矩形作为蛇的食物
             cv2.rectangle(imgMain, (rx-20, ry-20), (rx+20, ry+20), (255,255,0), cv2.FILLED)
             cv2.rectangle(imgMain, (rx-20, ry-20), (rx+20, ry+20), (0,255,255), 5)
             cv2.rectangle(imgMain, (rx-5, ry-5), (rx+5, ry+5), (0,0,255), cv2.FILLED)
   
             # 检查指尖(即蛇头cx,cy)是否在矩形内部
             if rx-20 < cx < rx+20 and ry-20< cy < ry+20:
   
               # 随机更换食物的位置
               self.randomFoodLocation()
   
               # 增加蛇身的限制长度,每吃1个食物就能变长50
               self.allowedLength += 50
   
               # 吃食物的计数加一
               self.score += 1
   
               print('eat!', f'score:{self.score}')
   
             #(七)绘制蛇
             # 当节点列表中有值了,才能绘制
             if self.points:
   
               # 遍历蛇身节点坐标
               for i, point in enumerate(self.points):
                     # 绘制前后两个节点之间的连线
                     if i != 0:
                      cv2.line(imgMain, tuple(self.points), tuple(self.points), (0,255,0), 20)
                      cv2.line(imgMain, tuple(self.points), tuple(self.points), (0,0,255), 15)
   
               # 在蛇头的位置画个圆
               cv2.circle(imgMain, tuple(self.points[-1]), 20, (255,255,0), cv2.FILLED)
               cv2.circle(imgMain, tuple(self.points[-1]), 18, (255,0,0), 3)
               cv2.circle(imgMain, tuple(self.points[-1]), 5, (0,0,0), cv2.FILLED)
   
             #(八)检查蛇头碰撞到自身
             for point in self.points[:-2]: # 不算蛇头到自身的距离
   
               # 计算蛇头和每个节点之间的距离
               dist = math.hypot(cx-point, cy-point)
   
               # 如果距离小于1.8,那么就证明碰撞了
               if dist < 1.8:
   
                     # 游戏结束
                     self.gameover = True
   
         # 返回更新后的图像
         return imgMain
   
   
#(1)获取摄像头
cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头
# 设置显示窗口的size
cap.set(3, 1280) # 窗口宽1280
cap.set(4, 720) # 窗口高720
   
#(2)模型配置
detector = HandDetector(maxHands=1, # 最多检测1只手
                     detectionCon=0.8) # 最小检测置信度0.8
   
# 接收创建贪吃蛇的类
game = SnakeGameClass()
   
#(3)图像处理
while True:
   
   # 每次读取一帧相机图像,返回是否读取成功success,读取的帧图像img
   success, img = cap.read()
   
   # 图像翻转,使图像和自己呈镜像关系
   img = cv2.flip(img, 1) # 0代表上下翻转,1代表左右翻转
   
   # 检测手部关键点。返回手部信息hands,绘制关键点后的图像img
   hands, img = detector.findHands(img, flipType=False) # 由于上一行翻转过图像了,这里就不用翻转了
   
   #(4)关键点处理
   if hands: # 如果检测到手了,那就处理关键点
   
         # 获得食指指尖坐标(x,y)
         hand = hands # 获取一只手的全部信息
         lmList = hand['lmList'] # 获得这只手的21个关键点的坐标(x,y,z)
         pointIndex = lmList # 只获取食指指尖关键点的(x,y)坐标
   
         # 更新贪吃蛇的节点,给出蛇头节点坐标。返回更新后的图像
         img = game.update(img, pointIndex)
   
   #(5)显示图像
   cv2.imshow('img', img) # 输入图像显示窗口的名称及图像
   
   # 重新开始游戏
   k = cv2.waitKey(1) # 每帧滞留1毫秒后消失
   if k == ord('r'): # 键盘'r'键代表重新开始游戏
         game.gameover = False
         game.score = 0 # 积分器
         game.points = [] # 蛇的身体的节点坐标
         game.lengths = [] # 蛇身各个节点之间的坐标
         game.currentLength = 0 # 当前蛇身长度
         game.allowedLength = 150 # 没吃东西时,蛇的总长度
         game.previousHead = (0,0) # 前一个蛇头节点的坐标
         game.randomFoodLocation() # 随机改变食物的位置
   
   if k & 0xFF == 27: # 键盘ESC键退出程序
         break
   
# 释放视频资源
cap.release()
cv2.destroyAllWindows()




【演示视频】
https://www.bilibili.com/video/BV17A4y1978g?share_source=copy_web

云天 发表于 2022-4-11 15:49:10

https://www.realvnc.com/en/connect/download/vnc/

hnyzcj 发表于 2022-4-11 15:53:49

{:5_121:}

发表于 2022-4-13 10:54:40

有点儿没懂。那台电脑是你用拿铁熊猫做的吗?

rzegkly 发表于 2022-4-17 12:14:19

漂亮,喜欢

云天 发表于 2022-4-18 16:49:21

诩 发表于 2022-4-13 10:54
有点儿没懂。那台电脑是你用拿铁熊猫做的吗?

就是用拿铁熊猫做的

小企鹅 发表于 2022-4-23 17:13:17

厉害厉害

派大星ym 发表于 2022-8-2 08:53:12

{:6_209:}。。。

三春牛-创客 发表于 2023-7-27 22:27:13

厉害厉害

三春牛-创客 发表于 2023-7-27 22:28:19

好赞啊!!!

三春牛-创客 发表于 2023-7-27 22:31:05

贪吃蛇亲身体验,第一次见呢,不错!
页: [1]
查看完整版本: LattePanda+Mind+摄像头玩AI贪吃蛇