用Python+OpenCV给斗地主做个‘外挂’:手把手教你写个桌面记牌器(附源码)
PythonOpenCV实战打造智能斗地主记牌工具记得去年宿舍通宵打牌时室友总抱怨记不住出过的牌。作为计算机系学生我琢磨着能否用课堂学的OpenCV做个记牌工具。三周后当这个能自动识别桌面上扑克牌的小程序成功运行时那种将理论知识转化为实际应用的成就感至今难忘。下面就把这个结合图像处理与界面开发的完整项目经验分享给大家。1. 开发环境与工具链搭建工欲善其事必先利其器。这个项目需要多个Python库的协同工作建议使用Anaconda创建独立环境conda create -n poker_ai python3.8 conda activate poker_ai pip install opencv-python numpy pyqt5 pillow pywin32核心工具链构成工具版本用途OpenCV4.5图像采集与处理核心库PyQt55.15构建用户界面NumPy1.20数值计算支持Pillow8.0图像格式转换pywin32300Windows系统API调用提示避免混用pip和conda安装可能导致依赖冲突。建议全部使用pip在虚拟环境中安装。常见环境问题解决方案出现DLL加载错误安装VC 2015-2019运行库摄像头无法调用检查权限并更新驱动程序PyQt5样式异常安装Qt官方运行时库2. 屏幕图像采集与预处理精准获取游戏窗口是第一步。我们采用Windows API获取指定窗口的像素数据import win32gui import win32ui from ctypes import windll def capture_window(hwnd): left, top, right, bottom win32gui.GetWindowRect(hwnd) w right - left h bottom - top hwndDC win32gui.GetWindowDC(hwnd) mfcDC win32ui.CreateDCFromHandle(hwndDC) saveDC mfcDC.CreateCompatibleDC() saveBitMap win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) saveDC.SelectObject(saveBitMap) windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 2) bmpinfo saveBitMap.GetInfo() bmpstr saveBitMap.GetBitmapBits(True) img np.frombuffer(bmpstr, dtypeuint8).reshape((h, w, 4)) # 释放资源 win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(hwnd, hwndDC) return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)关键预处理步骤色彩空间转换BGR→HSV便于颜色阈值处理高斯模糊3×3内核消除噪声边缘检测Canny算法提取牌面轮廓形态学操作闭运算填充内部空隙def preprocess_image(img): hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) blur cv2.GaussianBlur(hsv, (3,3), 0) edges cv2.Canny(blur, 50, 150) kernel cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) closed cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel) return closed3. 扑克牌识别核心技术3.1 牌面区域定位通过轮廓分析找到所有可能的扑克牌区域def find_card_contours(processed_img): contours, _ cv2.findContours( processed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) cards [] for cnt in contours: peri cv2.arcLength(cnt, True) approx cv2.approxPolyDP(cnt, 0.02*peri, True) if len(approx) 4 and cv2.contourArea(cnt) 1000: x,y,w,h cv2.boundingRect(approx) aspect_ratio w / float(h) if 0.6 aspect_ratio 0.8: cards.append((x,y,w,h)) return sorted(cards, keylambda c: c[0]) # 按x坐标排序3.2 牌面字符识别采用模板匹配与OCR结合的方式花色识别模板匹配def detect_suit(card_img): suits [hearts, diamonds, clubs, spades] best_match None max_val 0 for suit in suits: template cv2.imread(ftemplates/{suit}.png, 0) res cv2.matchTemplate(card_gray, template, cv2.TM_CCOEFF_NORMED) _, val, _, _ cv2.minMaxLoc(res) if val max_val: max_val val best_match suit return best_match if max_val 0.7 else None数字/字母识别OCR预处理流程提取ROI区域二值化处理字符分割使用预训练CNN模型识别4. PyQt5界面设计与功能集成创建带记忆功能的用户界面from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget) class PokerTracker(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(斗地主智能记牌器) self.setGeometry(100, 100, 400, 600) self.central_widget QWidget() self.layout QVBoxLayout() self.status_label QLabel(等待游戏开始...) self.start_btn QPushButton(开始监控) self.start_btn.clicked.connect(self.start_tracking) self.layout.addWidget(self.status_label) self.layout.addWidget(self.start_btn) self.central_widget.setLayout(self.layout) self.setCentralWidget(self.central_widget) self.played_cards set() self.current_hand [] def start_tracking(self): self.status_label.setText(监控中...) # 启动定时截图线程界面功能亮点实时牌面显示可视化已出牌和剩余牌概率计算根据已出牌计算各玩家持牌概率历史记录保存多局比赛数据热键支持AltS快速截图5. 实战中的坑与解决方案5.1 特效干扰问题当玩家出顺子或炸弹时游戏会显示特效动画导致截图失真。解决方案检测动画帧通过颜色直方图突变延迟100ms后重新截图添加异常重试机制5.2 多分辨率适配不同显示器分辨率导致牌面位置变化。我们采用动态检测窗口尺寸比例计算关键坐标自适应模板缩放def adapt_resolution(window_size): base_w, base_h 1920, 1080 # 基准分辨率 curr_w, curr_h window_size scale_x curr_w / base_w scale_y curr_h / base_h return { card_width: int(80 * scale_x), card_height: int(120 * scale_y), margin_x: int(30 * scale_x), margin_y: int(50 * scale_y) }5.3 性能优化技巧使用ROI减少处理区域缓存模板匹配结果多线程处理UI线程与图像处理线程分离定时器替代循环检测这个项目让我深刻体会到课堂上的图像处理算法真正应用到实际问题时需要考虑的边界条件远超想象。比如最初没想到游戏特效会影响识别直到实战测试才发现这个问题。现在回看这些踩坑经历反而成了最宝贵的收获。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2458591.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!