Skip to content

python dm ocr

qiannian edited this page Jun 13, 2026 · 1 revision

Python 大漠字库 OCR 示例

本示例基于项目中的 examples/bind.py,演示使用 Python SWIG 模块 pyop 绑定 MuMu 模拟器窗口,并加载大漠文本点阵字库进行 OcrExFindStr 识别。

准备文件

示例假设脚本目录下已经放好这些文件:

demo.py
pyop.py
_pyop.pyd
op_x64.dll
dm_soft.txt

其中 dm_soft.txt 是大漠文本点阵字库,格式为:

点阵HEX$文本$左.右.数量$高度

例如:

FFFFFFFFFF$字$0.0.10$11

Code

from pathlib import Path

import pyop


def find_mumu_handles(op):
    # 查找 MuMu 主窗口
    parent_hwnd = op.FindWindow("", "MuMu安卓设备")
    if parent_hwnd == 0:
        raise RuntimeError("没有找到 MuMu安卓设备 窗口")

    # 枚举 MuMu 子窗口,分别找显示窗口和输入窗口
    display_hwnd = 0
    input_hwnd = 0
    hwnds = op.EnumWindow(parent_hwnd, "", "", 0)

    for hwnd_text in hwnds.split(","):
        if not hwnd_text:
            continue

        hwnd = int(hwnd_text)
        title = op.GetWindowTitle(hwnd)
        print("child hwnd:", hwnd, "title:", title)

        # nemudisplay 用于截图显示
        if title == "nemudisplay":
            display_hwnd = hwnd

        # MuMuNxDevice 用于后台鼠标键盘输入
        if title == "MuMuNxDevice":
            input_hwnd = hwnd

    if display_hwnd == 0 or input_hwnd == 0:
        raise RuntimeError("没有找到 MuMu 的显示窗口或输入窗口")

    return display_hwnd, input_hwnd


def bind_mumu(op, display_hwnd, input_hwnd):
    # 双句柄绑定:显示和输入分开传入
    ret = op.BindWindowEx(display_hwnd, input_hwnd, "dx2", "dx", "dx", 0)
    if ret != 1:
        raise RuntimeError("绑定 MuMu 窗口失败")


def load_dm_dict(op, dict_path):
    # 加载大漠文本点阵字库
    ret = op.SetDict(0, str(dict_path))
    if ret != 1:
        raise RuntimeError(f"加载字库失败: {dict_path}")

    # 使用第 0 号字库
    op.UseDict(0)


def recognize_and_click(op, width, height):
    # 大漠找字常用颜色格式:颜色-偏色,多组颜色用 | 分隔
    color = "ffffff-303030|c7c9ca-303030"
    sim = 0.9

    # 返回区域内识别到的文字和坐标信息
    ocr_result = op.OcrEx(0, 0, width, height, color, sim)
    print("OcrEx:", ocr_result)

    # 查找指定文字;pyop 返回 x, y, ret
    x, y, ret = op.FindStr(0, 0, width, height, "诛仙", color, sim)
    print("FindStr:", {"ret": ret, "x": x, "y": y})

    if ret == 1:
        # 找到文字后移动并点击
        op.MoveTo(x, y)
        op.LeftClick()


def main():
    root = Path(__file__).resolve().parent
    dict_path = root / "dm_soft.txt"

    op = pyop.libop()
    print("op version:", op.Ver())

    display_hwnd, input_hwnd = find_mumu_handles(op)

    try:
        bind_mumu(op, display_hwnd, input_hwnd)

        # 获取绑定显示窗口的客户区大小
        width, height = op.GetClientSize(display_hwnd)
        print("client size:", width, height)

        # 截图用于确认绑定是否正常
        if op.Capture(0, 0, width, height, "mumu.png") != 1:
            raise RuntimeError("截图失败")

        load_dm_dict(op, dict_path)
        recognize_and_click(op, width, height)

    finally:
        # 使用完成后解除绑定
        op.UnBindWindow()


if __name__ == "__main__":
    main()

说明

  • 这个示例使用的是 pyop.libop(),需要 pyop.py_pyop.pyd 和对应位数的 op_x64.dll/op_x86.dll
  • BindWindowEx(display_hwnd, input_hwnd, ...) 适合 MuMu 这类显示窗口和输入窗口分离的场景。
  • SetDict 可以直接加载大漠文本点阵字库;字库加载成功后,OcrEx/FindStr/FindStrEx 会走本地点阵字库识别。
  • FindStrpyop 中返回顺序为 x, y, retret == 1 表示找到目标文字。
  • 如果窗口标题和当前 MuMu 版本不一致,请先打印子窗口标题,再调整 nemudisplayMuMuNxDevice 的匹配条件。

Clone this wiki locally