资讯动态

基于YOLOv5与强化学习的AI斗地主:从视觉识别到决策实战

发布时间:2026/9/3 7:25:35 来源:尧图企业网站定制
简介本资源是一个基于YOLOv5实现的AI斗地主识别与辅助决策系统面向人工智能、自动化、电子信息等专业的在校学生、教师及初级开发者解决扑克牌图像实时检测、牌面识别与游戏逻辑联动等典型CV规则引擎融合问题。压缩包共40个文件含10个核心Python脚本如infer.py、my_datasets.py、4个XML标注配置、4个C/H文件支撑移动端部署适配、2个PT模型权重含best.pt、以及Gradle构建脚本、README文档和演示截图等整体14.42MB结构清晰模块划分明确便于理解目标检测落地全流程。已有89人学习下载资源源自高分课程设计项目答辩获95分并经导师认可附带完整技术文档与可运行代码涵盖数据预处理、YOLOv5训练微调、牌面识别后处理及简易斗地主规则判定逻辑适合毕设、课设或CV工程实践进阶参考。1. 项目概述当YOLOv5“看”懂了你的牌最近在整理硬盘里的老项目翻到了一个挺有意思的玩意儿——一个用YOLOv5实现的AI斗地主。这可不是简单的规则引擎而是一个能“看见”屏幕、自动识别手牌和公共牌然后做出出牌决策的“外挂级”项目。当初做它纯粹是出于技术好奇计算机视觉能不能在非标准化的游戏UI上稳定工作强化学习在斗地主这种不完全信息博弈里能玩到什么水平今天就把这个项目的里里外外拆解一遍从环境搭建、模型训练到策略设计把踩过的坑和最终跑通的方案都摊开来聊聊。无论你是想学习YOLOv5的实际应用还是对游戏AI感兴趣这个项目都能提供一个从理论到落地的完整视角。这个项目本质上是一个自动化游戏代理。它的工作流程可以概括为通过屏幕截图获取游戏画面利用训练好的YOLOv5模型检测并识别出所有的扑克牌包括自己的手牌、地主牌、已出的牌将这些视觉信息转化为结构化的牌型数据最后基于这些数据运行决策算法模拟鼠标点击完成出牌。整个过程完全离线不依赖游戏官方的任何接口因此其核心挑战就在于视觉识别的鲁棒性和决策算法的有效性。下面我们就从最关键的视觉检测部分开始。2. 核心思路与方案选型为什么是YOLOv5面对“从游戏画面中识别扑克牌”这个问题有好几条技术路径可选。最简单粗暴的是模板匹配但斗地主游戏UI风格多样牌的位置、大小、背景都可能变化模板匹配的泛化能力太差。另一种思路是使用OCR识别牌面上的数字和字母但J、Q、K、A、2这些字符在艺术字体下识别率堪忧且无法区分花色。经过权衡我选择了基于深度学习的目标检测方案它能同时定位牌的位置并识别其类别如“红桃A”、“黑桃5”。在目标检测模型选型上YOLOv5在当时现在依然是一个平衡了速度、精度和易用性的绝佳选择。相较于更早的YOLOv3/v4v5的PyTorch实现更加友好训练脚本封装完善对于快速原型开发非常合适。它的轻量化版本如YOLOv5s完全能满足实时性要求每秒数十帧在消费级GPU甚至CPU上都能流畅运行。此外其活跃的社区和丰富的预训练模型也为迁移学习提供了便利。注意项目选型时需考虑可持续性。YOLOv5虽然经典但后续有v6、v7、v8等版本。本项目选用v5主要是因其在2021-2022年时生态最成熟资料最多。若今天启动类似项目可以评估更新的版本但v5的学习路径和原理依然具有很高的参考价值。整个系统的架构可以划分为三个核心模块视觉感知模块基于YOLOv5的扑克牌检测与识别。信息处理模块将检测到的牌面框坐标和类别转换为游戏逻辑所需的牌型数据结构如手牌列表、上家出牌牌型。决策执行模块基于当前牌局状态调用决策算法规则引擎或强化学习模型计算出最优出牌并控制鼠标执行操作。这个架构清晰地将视觉、逻辑、控制解耦方便每个模块独立调试和优化。3. 数据集制作与模型训练教AI认识每一张牌任何监督学习模型的上限都取决于数据集的质量。对于扑克牌检测我们需要收集大量包含扑克牌的游戏截图并精确标注每一张牌的位置和类别。3.1 数据收集与标注我采用了“游戏模拟器自动截图”的方式批量获取数据。在Windows上运行主流的斗地主游戏客户端如腾讯欢乐斗地主使用Python的pyautogui库控制游戏并定时截图。为了增加数据的多样性需要覆盖不同场景手牌区牌密集排列可能有部分重叠或遮挡。出牌区牌分散在桌面上角度、大小可能不一。地主牌区三张牌扣放或明牌。不同游戏主题和牌面样式这是泛化性的关键。标注工具选用LabelImg它支持YOLO格式中心点x, y宽度w高度h均归一化。类别标签就是54张扑克牌52张常规牌大小王。这里有个细节是否区分花色对于斗地主规则花色只在顺子中可能起作用且通常不严格区分但为了信息的完备性我选择了区分类别名如heart_ace,spade_5,black_joker等。实操心得标注时框Bounding Box要紧贴牌面边缘但不必过于精确。对于重叠的牌标注可见部分即可。数据集至少需要3000张以上有效标注图片才能保证模型在复杂背景下的识别稳定性。我最终整理了约5000张图片按8:1:1划分训练集、验证集和测试集。3.2 YOLOv5模型训练与调优训练环境基于PyTorch 1.7和CUDA 11.0。直接克隆YOLOv5官方仓库其清晰的目录结构让上手非常容易。git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt数据配置在data/目录下创建poker.yaml文件定义数据集路径和类别。# poker.yaml path: ../datasets/poker train: images/train val: images/val nc: 54 # 类别数 names: [heart_ace, heart_2, ..., black_joker, red_joker]模型选择从轻量化的yolov5s.pt预训练模型开始迁移学习。预训练模型在COCO等大型数据集上学到的通用特征边缘、纹理能加速收敛。python train.py --img 640 --batch 16 --epochs 100 --data data/poker.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt--img 640: 输入图像尺寸。更大的尺寸可能提升小目标检测精度但会增加计算量。--batch 16: 批大小根据GPU显存调整。--epochs 100: 训练轮数可通过早停Early Stopping策略优化。关键调参学习率lr使用--lr0和--lrf参数。一般从0.01开始配合余弦退火调度器。数据增强YOLOv5默认开启了Mosaic、MixUp等强增强。对于扑克牌这种形状规则、可能旋转的目标可以适当调整--degrees旋转角度和--shear剪切变换的强度。锚框AnchorYOLOv5会针对你的数据集自动计算最佳锚框尺寸这是一个非常实用的特性。训练过程中使用tensorboard --logdir runs监控损失曲线和评估指标如mAP0.5。当验证集上的mAP趋于稳定且过拟合迹象不明显时即可停止训练。3.3 模型导出与性能测试训练完成后得到的最佳模型保存在runs/train/exp/weights/best.pt。为了部署通常将其转换为ONNX或TorchScript格式以提升推理速度或兼容不同环境。python export.py --weights runs/train/exp/weights/best.pt --include onnx在测试集上评估模型性能重点关注整体mAP应达到95%以上才能保证后续流程的可靠性。特定类别召回率检查“大小王”、“2”、“A”等关键牌是否容易被漏检。推理速度在目标部署设备如你的开发机上用detect.py脚本测试实时帧率FPS。YOLOv5s在GTX 1660上处理640x640图像可达100 FPS完全满足实时要求。4. 游戏状态解析与牌型判断模型输出了扑克牌的类别和位置但这只是原始数据。我们需要将其转化为游戏能理解的逻辑状态。这部分代码的健壮性直接决定了AI的“视力”是否可靠。4.1 从像素坐标到逻辑位置游戏画面是固定的因此我们可以通过硬编码的屏幕区域坐标来区分不同区域的牌手牌区域通常位于屏幕底部。出牌区域位于屏幕中央。地主牌区域位于屏幕顶部。在代码中我们根据检测框的中心点坐标(x_center, y_center)来判断一张牌属于哪个区域。例如def classify_card_region(box, img_height): x_center, y_center box[0], box[1] if y_center img_height * 0.7: return hand elif img_height * 0.3 y_center img_height * 0.7: return played else: return unknown4.2 牌面信息聚合与数据结构化对于同一区域的牌需要进一步处理。例如手牌区的多张牌是水平排列的我们需要根据它们的水平坐标进行排序得到一个有序的手牌列表。# 假设hand_boxes是手牌区域的所有检测框 hand_boxes_sorted sorted(hand_boxes, keylambda b: b[0]) # 按x中心坐标排序 hand_cards [box[5] for box in hand_boxes_sorted] # 获取类别索引接下来将类别索引如heart_ace转换为内部表示。我定义了一个Card类包含点数rank和花色suit属性并方便地比较大小。class Card: suits {heart: H, diamond: D, club: C, spade: S} ranks {3: 3, 4: 4, ..., king: 13, ace: 14, 2: 15, black_joker: 16, red_joker: 17} def __init__(self, yolo_class_name): # 解析yolo_class_name如‘heart_ace’ parts yolo_class_name.split(_) if len(parts) 2: self.suit self.suits.get(parts[0], ) self.rank self.ranks.get(parts[1], 0) # ... 处理大小王这样我们就将视觉信息转化为了一个List[Card]对象代表了当前玩家的手牌。4.3 牌型判断引擎这是斗地主AI的逻辑核心之一。给定一组牌需要判断它是否符合游戏规则以及是什么牌型单张、对子、顺子、炸弹等。def check_card_type(cards): cards sorted(cards, keylambda c: c.rank) count len(cards) if count 1: return single, cards[0].rank elif count 2: if cards[0].rank cards[1].rank: return pair, cards[0].rank elif {cards[0].rank, cards[1].rank} {16, 17}: return rocket, 999 # 王炸最大 elif count 3: # 检查三张相同 ... elif count 4: # 可能是炸弹四张相同或三带一 ... # ... 更复杂的牌型顺子、连对、飞机等 return None, 0 # 无效牌型编写一个健壮的牌型判断函数需要仔细处理各种边界情况例如A-2-3-4-5算不算顺子在斗地主中通常不算以及连对中是否允许2点出现等。5. AI出牌决策策略从规则到强化学习有了精准的游戏状态感知接下来就是大脑——决策系统。我尝试了两种策略由简入繁。5.1 基于规则的策略初级版这是最直观的方法模拟人类玩家的基本思路。可以设计一系列优先级规则跟牌规则如果上家出牌在自己的手牌中寻找相同牌型且点数更大的牌组合。如果没有则不出Pass。出牌规则当自己获得出牌权时新回合或上家Pass后按照一定策略选择牌型打出。例如优先出较长的顺子或连对以快速减少手牌数量。保留大牌2、王、A和炸弹作为控制权。手牌很少时优先出能一次走完的牌型。炸弹使用策略炸弹是稀缺资源。规则可以设定仅在以下情况使用炸弹(a) 能直接获胜(b) 阻止对手可能的一次出完牌(c) 自己手牌很差需要抢夺出牌权。用代码实现就是一个巨大的if-elif-else状态机。虽然逻辑直白但要想玩得好规则会变得极其复杂和臃肿难以处理所有局面尤其是需要长远规划记牌、算牌时。5.2 基于强化学习的策略进阶版为了让AI学会更优的、甚至超越人类经验的策略我引入了强化学习RL。我们将斗地主一局游戏建模为一个部分可观测马尔可夫决策过程状态State当前玩家的手牌、已出的所有牌、剩余牌堆推断、当前回合信息等。由于是部分可观测我们只能推断其他玩家的手牌分布。动作Action选择一组牌打出或者不出Pass。奖励Reward最终赢得比赛获得1奖励输掉获得-1奖励。也可以设计中间奖励如每打出一手牌给予微小负奖励鼓励尽快出完或成功压制对手给予正奖励。我采用了深度Q网络DQN作为算法框架。状态需要被编码成固定长度的向量例如用一个54维的向量表示每种牌在自己手中的数量再用其他向量表示公共信息。动作空间是离散的但非常大所有合法的出牌组合Pass。直接处理如此大的动作空间不现实因此需要设计一个动作生成器先根据当前手牌和上家牌型生成所有合法的跟牌或出牌动作候选集然后由DQN网络评估每个候选动作的Q值选择最高的执行。网络结构相对简单输入层接收状态向量经过几个全连接层输出层对应每个候选动作的Q值。import torch.nn as nn class DQN(nn.Module): def __init__(self, state_dim, action_dim): super(DQN, self).__init__() self.fc1 nn.Linear(state_dim, 128) self.fc2 nn.Linear(128, 128) self.fc3 nn.Linear(128, action_dim) def forward(self, x): x torch.relu(self.fc1(x)) x torch.relu(self.fc2(x)) return self.fc3(x)训练过程需要大量的自我对弈Self-play。让三个AI玩家可以共享同一个网络也可以使用不同策略的网络不断进行游戏收集状态、动作、奖励、下一状态的序列(s, a, r, s)存储到经验回放缓冲区然后随机采样进行网络更新。踩坑实录RL训练非常耗时且不稳定。初期最大的问题是奖励稀疏只有终局才有导致学习缓慢。解决方案是加入人工设计的中间奖励例如成功出完一手牌奖励0.01被对手压制奖励-0.005。同时使用目标网络Target Network和双DQNDouble DQN技巧来稳定训练。即使这样训练出一个勉强能玩的AI也需要数十万局游戏对计算资源要求很高。6. 系统集成与自动化控制将视觉模块、状态解析模块和决策模块串联起来就构成了完整的自动化流程。同时我们需要一个控制模块来执行AI的决策。6.1 主循环流程系统的主循环通常以固定的频率如每秒10次运行流程如下截图使用pyautogui.screenshot()或更快的mss库捕获游戏窗口区域。推理将截图送入YOLOv5模型得到检测结果。状态更新解析检测结果更新当前玩家的手牌、桌面出牌等信息。决策触发判断是否轮到本方操作。可以通过检测游戏UI上的特定标志如“出牌”按钮高亮或根据回合逻辑推断。决策与执行如果轮到本方决策模块根据当前状态计算出牌动作。然后控制模块将牌面组合映射到屏幕坐标模拟鼠标点击出牌。6.2 模拟鼠标操作pyautogui库可以方便地控制鼠标移动和点击。关键是将“出哪几张牌”这个逻辑动作映射到屏幕上具体的坐标。手牌点击我们已经知道每张手牌在屏幕上的位置来自YOLO检测框。对于要出的多张牌需要按游戏规则顺序点击例如斗地主中需要先选中牌再点击“出牌”按钮。这里需要模拟点击和短暂的延迟。import pyautogui import time def click_cards(card_boxes): for box in card_boxes: x, y box_center_to_screen(box) # 将归一化坐标转换为屏幕坐标 pyautogui.moveTo(x, y, duration0.1) # 移动鼠标 pyautogui.click() time.sleep(0.05) # 短暂延迟防止操作过快被游戏忽略 # 点击“出牌”按钮 pyautogui.moveTo(play_button_x, play_button_y, duration0.1) pyautogui.click()稳定性优化直接模拟鼠标操作可能因为游戏响应延迟或动画效果而失败。需要加入重试机制和状态确认。例如点击“出牌”按钮后等待一段时间并再次截图确认牌是否真的被打出。6.3 工程化与调试一个完整的项目还需要考虑很多工程细节配置文件将游戏窗口位置、按钮坐标、模型路径、决策参数等写入配置文件如config.yaml便于适配不同分辨率和游戏版本。日志系统详细的日志对于调试至关重要。记录每一帧的检测结果、决策依据、执行的操作当AI行为异常时可以回溯查找问题。优雅退出设置全局热键如F12来暂停或终止AI程序防止失控。性能监控实时显示FPS、决策耗时等信息帮助优化瓶颈。7. 常见问题、优化与扩展方向在实际开发和运行中会遇到各种各样的问题。这里记录一些典型问题及其解决方案。7.1 视觉检测常见问题问题现象可能原因解决方案漏检某些牌尤其是边缘牌1. 训练数据中边缘样本不足。2. 数据增强过度导致模型对位置敏感度下降。1. 补充边缘位置的截图进行标注和训练。2. 调整数据增强参数减少随机裁剪和旋转的幅度。将游戏UI其他元素误检为牌背景干扰训练数据未覆盖足够多的UI样式。1. 在数据集中加入更多包含复杂UI的负样本不包含牌但包含其他UI的图片并在标注时明确标记为背景。2. 增加模型输入尺寸让模型能看到更多上下文信息以区分。检测速度慢无法实时运行1. 模型过大如使用了YOLOv5x。2. 在CPU上运行。1. 换用更小的模型YOLOv5n或YOLOv5s。2. 确保使用GPU进行推理。使用torch.cuda.is_available()检查。3. 将模型转换为TensorRT或OpenVINO等优化格式。同一张牌被重复检测多次NMS非极大值抑制阈值设置不当。调整推理时的--iou-thres交并比阈值和--conf-thres置信度阈值参数。对于扑克牌这种目标可以适当提高iou-thres如0.6来合并重叠框。7.2 决策与执行问题AI总是Pass或乱出牌规则策略检查牌型判断函数是否正确特别是复杂牌型飞机带翅膀、四带二的判断逻辑。确保跟牌规则中“牌型相同且点数更大”的逻辑覆盖所有情况。AI决策超时决策算法特别是RL策略中的动作生成可能组合爆炸。需要优化动作生成器提前剪枝明显不合理的出牌选择例如手牌很少时还考虑出长顺子。鼠标点击无效或点错位置游戏可能有动画延迟或窗口位置发生了变化。增加操作后的等待时间并实现一个“状态校验”循环执行操作后等待几帧再次检测画面确认操作是否生效如未生效则重试或报警。无法适应不同游戏客户端这是此类项目最大的挑战。解决方案是抽象一层“游戏适配器”。为每个需要支持的客户端编写一个适配器模块负责处理该客户端特有的UI布局、颜色、按钮位置等。主程序通过配置选择加载哪个适配器。7.3 项目优化与扩展模型轻量化与加速尝试使用YOLOv5的量化Quantization和剪枝Pruning技术进一步减小模型体积、提升推理速度使其能在树莓派等嵌入式设备上运行。引入记忆与推理当前的AI只关注当前时刻的牌面。高级玩家会“记牌”和“算牌”。可以在状态表示中融入历史出牌信息并尝试用神经网络或概率模型来推断剩余牌的分布让AI具备初步的推理能力。多智能体协作与对抗在三人斗地主中当地主和当农民的策略截然不同。可以训练两个不同的策略网络或者设计一个网络能根据自身角色地主/农民和盟友信息调整策略。更进一步可以研究农民之间的协作信号虽然游戏内无法直接通信但可以通过出牌传递隐含信息。从监督学习到自监督学习收集大量人类高手对局数据用行为克隆Behavior Cloning或逆强化学习Inverse RL来初始化AI策略可能比纯RL从头训练更快、更稳定。图形化界面与交互为项目开发一个简单的控制面板可以实时显示AI“看到”的牌、它的决策置信度、当前状态估计等方便调试和演示。这个项目从技术验证的角度是成功的它验证了YOLOv5在复杂UI游戏环境中进行特定目标检测的可行性并串联起了计算机视觉、游戏逻辑和自动控制。虽然距离战胜人类顶尖高手还有很长的路但作为一个学习和探索的载体它充满了挑战和乐趣。所有源码和详细的文档注释都已整理在项目仓库中希望能给有兴趣的朋友提供一个扎实的起点。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价