文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

2023-06-29 10:58

关注

今天小编给大家分享一下怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

介绍

规则:食指指尖控制蛇头,指尖每接触到黄色方块,计数加一,蛇身变长,方块随机切换位置。如果指尖停止移动,或者移动过程中蛇头撞到蛇身,那么游戏结束。点击键盘上的R键重新开始游戏。

游戏进行时:

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

游戏结束界面:

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

1. 安装工具包

pip install opencv_python==4.2.0.34  # 安装opencvpip install mediapipe  # 安装mediapipe# pip install mediapipe --user  #有user报错的话试试这个pip install cvzone  # 安装cvzone # 导入工具包import cv2import cvzoneimport numpy as npfrom cvzone.HandTrackingModule import HandDetector  # 导入手部检测模块import mathimport random

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

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

2. 检测手部关键点

(1)cvzone.HandTrackingModule.HandDetector()是手部关键点检测方法

参数:

mode: 默认为 False,将输入图像视为视频流。它将尝试在第一个输入图像中检测手,并在成功检测后进一步定位手的坐标。在随后的图像中,一旦检测到所有 maxHands 手并定位了相应的手的坐标,它就会跟踪这些坐标,而不会调用另一个检测,直到它失去对任何一只手的跟踪。这减少了延迟,非常适合处理视频帧。如果设置为 True,则在每个输入图像上运行手部检测,用于处理一批静态的、可能不相关的图像。

maxHands: 最多检测几只手,默认为 2

detectionCon: 手部检测模型的最小置信值(0-1之间),超过阈值则检测成功。默认为 0.5

minTrackingCon: 坐标跟踪模型的最小置信值 (0-1之间),用于将手部坐标视为成功跟踪,不成功则在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 mode 为 True,则忽略这个参数,手部检测将在每个图像上运行。默认为 0.5

它的参数和返回值类似于官方函数 mediapipe.solutions.hands.Hands()

MULTI_HAND_LANDMARKS: 被检测/跟踪的手的集合,其中每只手被表示为21个手部地标的列表,每个地标由x, y, z组成。x和y分别由图像的宽度和高度归一化为[0,1]。Z表示地标深度。

MULTI_HANDEDNESS: 被检测/追踪的手是左手还是右手的集合。每只手由label(标签)和score(分数)组成。 label 是 'Left' 或 'Right' 值的字符串。 score 是预测左右手的估计概率。

(2)cvzone.HandTrackingModule.HandDetector.findHands()找到手部关键点并绘图

参数:

img: 需要检测关键点的帧图像,格式为BGR

draw: 是否需要在原图像上绘制关键点及识别框

flipType: 图像是否需要翻转,当视频图像和我们自己不是镜像关系时,设为True就可以了

返回值:

hands: 检测到的手部信息,由0或1或2个字典组成的列表。如果检测到两只手就是由两个字典组成的列表。字典中包含:21个关键点坐标(x,y,z),检测框左上坐标及其宽高,检测框中心点坐标,检测出是哪一只手。

img: 返回绘制了关键点及连线后的图像

代码如下:

import cv2import cvzoneimport numpy as npfrom cvzone.HandTrackingModule import HandDetector  # 导入手部检测模块 #(1)获取摄像头cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头# 设置显示窗口的sizecap.set(3, 1280)  # 窗口宽1280cap.set(4, 720)   # 窗口高720 #(2)模型配置detector = HandDetector(maxHands=1,  # 最多检测1只手                        detectionCon=0.8)  # 最小检测置信度0.8 #(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)  # 由于上一行翻转过图像了,这里就不用翻转了     # 查看关键点信息    print(hands)     #(4)关键点处理    if hands:  # 如果检测到手了,那就处理关键点         # 获得食指指尖坐标(x,y)        hand = hands[0]  # 获取一只手的全部信息        lmList = hand['lmList']  # 获得这只手的21个关键点的坐标(x,y,z)        pointIndex = lmList[8][0:2]  # 只获取食指指尖关键点的(x,y)坐标         # 以食指指尖为圆心画圈(圆心坐标是元组类型),半径为15,青色填充        cv2.circle(img, tuple(pointIndex), 15, (255,0,0), cv2.FILLED)     #(5)显示图像    cv2.imshow('img', img)  # 输入图像显示窗口的名称及图像     # 每帧滞留1毫秒后消失,并且按下ESC键退出    if cv2.waitKey(1) & 0xFF == 27:        break # 释放视频资源cap.release()cv2.destroyAllWindows()

效果图如下:

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

打印手部关键点信息如下:

[{'lmList': [[1152, 675, 0], [1085, 693, -37], [1030, 698, -68], [1003, 698, -97], [1003, 679, -122], [1001, 511, -48], [1041, 546, -81], [1093, 608, -102], [1134, 652, -110], [1075, 484, -46], [1119, 534, -84], [1171, 605, -101], [1217, 659, -103], [1141, 481, -45], [1177, 529, -83], [1219, 590, -84], [1253, 642, -73], [1195, 494, -47], [1221, 521, -73], [1245, 566, -65], [1267, 602, -49]], 'bbox': (1001, 481, 266, 217),'center': (1134, 589), 'type': 'Right'}]

3. 蛇身移动

构造一个处理蛇身移动的类,要求在没吃食物时,蛇身保持固定的长度跟随食指指尖移动。

举个例子,如果当前的蛇身节点列表 self.points 包含 [a, b, c, d] 这四个节点,a节点代表蛇尾,d节点代表蛇头。在下一帧,食指指尖移动到 e 点,将 e 节点追加到蛇身节点列表中,那么现在的列表包含 [a, b, c, d, e] 节点,其中 e 节点为新的蛇头。

此时判断当前蛇身总长度 self.currentLength(列表中所有节点之间的长度之和)是否大于蛇身固定长度 self.allowedLength,保证在移动过程中蛇身长度不变。

如果当前蛇身总长度 self.currentLength 大于固定长度 self.allowedLength,那么在节点列表中从尾到头依次删除节点,列表 [a, b, c, d, e] 中 a 表示蛇尾节点,先删除,判断列表 [b, c, d, e] 的节点之间的总长度是否满足要求。若仍大于固定长度,那么就再删除 b 节点,再判断。

如果当前蛇身总长度 self.currentLength 小于固定长度 self.allowedLength,那么就不做任何处理。

在上述代码中补充:

import cv2import cvzoneimport numpy as npfrom cvzone.HandTrackingModule import HandDetector  # 导入手部检测模块import math # 构造一个贪吃蛇移动的类class SnakeGameClass:     #(一)初始化    def __init__(self):         self.points = []  # 蛇的身体的节点坐标        self.lengths = []  # 蛇身各个节点之间的坐标        self.currentLength = 0  # 当前蛇身长度        self.allowedLength = 150  # 没吃东西时,蛇的总长度        self.previousHead = (0,0)  # 前一个蛇头节点的坐标     #(二)更新增加蛇身长度    def update(self, imgMain, currentHead): # 输入图像,当前蛇头的坐标         px, py = self.previousHead  # 获得前一个蛇头的x和y坐标        cx, cy = currentHead  # 当前蛇头节点的x和y坐标                # 添加当前蛇头的坐标到蛇身节点坐标列表中        self.points.append([cx,cy])         # 计算两个节点之间的距离        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         #(四)绘制蛇        # 当节点列表中有值了,才能绘制        if self.points:             # 遍历蛇身节点坐标            for i, point in enumerate(self.points):                  # 绘制前后两个节点之间的连线                if i != 0:                    cv2.line(imgMain, tuple(self.points[i-1]), tuple(self.points[i]), (0,255,0), 20)             # 在蛇头的位置画个圆            cv2.circle(imgMain, tuple(self.points[-1]), 20, (255,0,0), cv2.FILLED)         # 返回更新后的图像        return imgMain  #(1)获取摄像头cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头# 设置显示窗口的sizecap.set(3, 1280)  # 窗口宽1280cap.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)  # 由于上一行翻转过图像了,这里就不用翻转了     # 查看关键点信息    print(hands)     #(4)关键点处理    if hands:  # 如果检测到手了,那就处理关键点         # 获得食指指尖坐标(x,y)        hand = hands[0]  # 获取一只手的全部信息        lmList = hand['lmList']  # 获得这只手的21个关键点的坐标(x,y,z)        pointIndex = lmList[8][0:2]  # 只获取食指指尖关键点的(x,y)坐标         # 更新贪吃蛇的节点,给出蛇头节点坐标。返回更新后的图像        img = game.update(img, pointIndex)     #(5)显示图像    cv2.imshow('img', img)  # 输入图像显示窗口的名称及图像     # 每帧滞留1毫秒后消失,并且按下ESC键退出    if cv2.waitKey(1) & 0xFF == 27:        break # 释放视频资源cap.release()cv2.destroyAllWindows()

效果图如下,蛇身保持默认固定长度随着指尖而移动。

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

4. 蛇进食增加身体长度

先看下面代码 SnakeGameClass 类中的第(五)步。给食物(即绘制的矩形)随机给出一个中心点坐标,自定义的类方法 randomFoodLocation(),执行该方法则食物的中心点坐标的x在[100,1000]中随机取一个数,y在[100,600]中随机取一个数。

下面代码定义的类中的第(七)步。判断食指指尖(即蛇头节点坐标)是否在矩形内部,如果在内部,那么蛇身移动过程中的固定长度 self.allowedLength 增加50个像素值。得分 self.score 加一。并在下一帧随机改变食物的位置。

在上述代码中补充:

import cv2import cvzoneimport numpy as npfrom cvzone.HandTrackingModule import HandDetector  # 导入手部检测模块import mathimport 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()  # 随机改变食物的位置     #(五)食物随机出现的位置    def randomFoodLocation(self):        # x在100至1000之间,y在100至600之间,随机取一个整数        self.foodPoint = random.randint(100, 1000),  random.randint(100, 600)     #(二)更新增加蛇身长度    def update(self, imgMain, currentHead): # 输入图像,当前蛇头的坐标         px, py = self.previousHead  # 获得前一个蛇头的x和y坐标        cx, cy = currentHead  # 当前蛇头节点的x和y坐标                # 添加当前蛇头的坐标到蛇身节点坐标列表中        self.points.append([cx,cy])         # 计算两个节点之间的距离        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                #(七)检查蛇是否吃了食物        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[i-1]), tuple(self.points[i]), (0,255,0), 20)                    cv2.line(imgMain, tuple(self.points[i-1]), tuple(self.points[i]), (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)         # 返回更新后的图像        return imgMain  #(1)获取摄像头cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头# 设置显示窗口的sizecap.set(3, 1280)  # 窗口宽1280cap.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[0]  # 获取一只手的全部信息        lmList = hand['lmList']  # 获得这只手的21个关键点的坐标(x,y,z)        pointIndex = lmList[8][0:2]  # 只获取食指指尖关键点的(x,y)坐标         # 更新贪吃蛇的节点,给出蛇头节点坐标。返回更新后的图像        img = game.update(img, pointIndex)     #(5)显示图像    cv2.imshow('img', img)  # 输入图像显示窗口的名称及图像     # 每帧滞留1毫秒后消失,并且按下ESC键退出    if cv2.waitKey(1) & 0xFF == 27:        break # 释放视频资源cap.release()cv2.destroyAllWindows()

效果图如下:

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

5. 自身碰撞及界面的处理

先看到自定义类 SnakeGameClass 中的第(八)步,蛇身节点列表 self.points 中包含从蛇头到蛇尾的所有节点。如 [a, b, c, d, e] 节点,a 节点代表蛇尾,e 节点代表蛇头。这里我就粗糙地判断一下是否碰撞,如果大家有更好的判断方法可以改动这第(八)步。计算蛇头 e 节点到所有节点之间的距离,如果小于某个值就代表碰撞了,游戏结束 self.gameover = True

再看到自定义类中的第(三)步。如果游戏结束 self.gameover = True,那就在下一帧中绘制结算界面,不再执行蛇身移动程序。

再看到主程序中的第(5)步。其中 k == ord('r'),按下键盘上的 r 键来重新游戏。将所有蛇身变量初始化,并将 self.gameover = False,退出结算界面,使得下一帧能执行蛇身移动操作。

在上述代码中补充:

import cv2import cvzonefrom matplotlib.cbook import pts_to_midstepimport numpy as npfrom cvzone.HandTrackingModule import HandDetector  # 导入手部检测模块import mathimport 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', [400,300], 5, 3, colorR=(0,255,255), colorT=(0,0,255))            cvzone.putTextRect(imgMain, f'Score:{self.score}', [450,400], 5, 3, colorR=(255,255,0))            cvzone.putTextRect(imgMain, f"Press Key 'R' to Restart", [230,500], 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([cx,cy])             # 计算两个节点之间的距离            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}', [50,80], 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[i-1]), tuple(self.points[i]), (0,255,0), 20)                        cv2.line(imgMain, tuple(self.points[i-1]), tuple(self.points[i]), (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[0], cy-point[1])                 # 如果距离小于1.8,那么就证明碰撞了                if dist < 1.8:                     # 游戏结束                    self.gameover = True         # 返回更新后的图像        return imgMain  #(1)获取摄像头cap = cv2.VideoCapture(0) # 0代表电脑自带的摄像头# 设置显示窗口的sizecap.set(3, 1280)  # 窗口宽1280cap.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[0]  # 获取一只手的全部信息        lmList = hand['lmList']  # 获得这只手的21个关键点的坐标(x,y,z)        pointIndex = lmList[8][0:2]  # 只获取食指指尖关键点的(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()

效果图如下,在移动过程中,蛇头每碰到一个食物,蛇身就会变长,如果 停止移动 或 蛇头节点距离蛇身节点过近 就会结束游戏。

怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏

以上就是“怎么用Python+OpenCV自制AI视觉版贪吃蛇游戏”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯