Python调用微信OCR识别文字和坐标

news/发布时间2024/5/4 19:14:40

原理

在看雪看到一篇文章:逆向调用QQ截图NT与WeChatOCR-软件逆向。里面说了怎么调用微信和QQ本地的OCR模型,还有很详细的分析过程。

我稍微看了下文章,多的也看不懂。大概流程是使用mmmojo.dll这个dll来与WeChatOCR.exe做通信的,也是用它来启动和关闭WeChatOCR.exe进程的。所以关键只需要知道这个dll里的导出函数怎么使用,就能自己实现调用OCR。并且可以脱离微信,不需要启动微信就能调用。既然这样,那完全可以使用Python加载mmmojo.dll启动WeChatOCR.exe并和它通信进行OCR识别。

代码怎么实现的就不多说的,感兴趣的可以看github的源码。我就说下有意思的一个技巧和一个踩坑的地方

回调指针技巧

OCR识别成功完成后会调用你给定的回调函数,并将结果作为参数传给回调函数。而其中一个回调函数的原型是static void OCRRemoteOnConnect(bool is_connected, void* user_data);。第一个参数是当前连接状态,比较有意思的是第二个参数


第二个参数是你给定的一个指针,它可以通过SetMMMojoEnvironmentCallbacks这个导出函数来设置,然后你就可以在回调函数里访问到这个指针。这个有什么用呢?就以上面github里的C++代码为例,代码里是将它设置为类的this指针,然后在建立连接后调用OCRRemoteOnConnect回调函数时,通过这个this指针改变类变量m_connect_con_var,然后你才能调用DoOCRTask,如果m_connect_con_var变量没有被设置,说明没有连接成功,就一直等待。


搜了一下,在Python里也可以实现这样一个操作,把这个值设置成Python类对象,然后就可以在回调函数访问这个类对象。原理大概像这篇文章:python - Back-casting a ctypes.py_object in a callback - Stack Overflow。先使用ctypes.py_object将对象转化为一个PyObject指针传给c层,然后在回调函数里再通过ctypes.cast(context, py_object).value得到这个对象,在这个项目里的代码如下:

# 将self转为c指针设置成user_data
SetMMMojoEnvironmentCallbacks(m_mmmojo_env_ptr, 0, py_object(self))
# 在回调函数里使用它
def OCRRemoteOnConnect(is_connected:c_bool, user_data:py_object):print(f"OCRRemoteOnConnect 回调函数被调用, 参数, is_connected: {is_connected}")if user_data:manager_obj:OcrManager = cast(user_data, py_object).valuemanager_obj.SetConnectState(True)

踩坑

调用dll时的参数不能直接用c_wchar_p,需要先赋值给一个变量,不然会被垃圾回收机制给回收了。而且错误很难定位,不会报错,程序直接终止

# 错误代码
SetMMMojoEnvironmentInitParams(m_mmmojo_env_ptr, 2, c_wchar_p(m_exe_path))
# 正确代码
c_m_exe_path = c_wchar_p(m_exe_path)
SetMMMojoEnvironmentInitParams(m_mmmojo_env_ptr, 2, c_m_exe_path)

另外还要注意的它的生命周期,和使用的时间。有些使用比较久的,你还得定义成全局变量或者赋值给self.

如何使用

安装

我已经发布到了pypi上,可以使用pip安装:pip install wechat-ocr

如果使用的是国内源,可能还没有更新,可以使用pip install wechat-ocr -i https://pypi.org/simple来使用官方源安装

使用

import os
import json
import time
from wechat_ocr.ocr_manager import OcrManager, OCR_MAX_TASK_IDwechat_ocr_dir = "C:\\Users\\Administrator\\AppData\\Roaming\\Tencent\\WeChat\\XPlugin\\Plugins\\WeChatOCR\\7057\\extracted\\WeChatOCR.exe"
wechat_dir = "D:\\GreenSoftware\\WeChat\\3.9.6.32"def ocr_result_callback(img_path:str, results:dict):result_file = os.path.basename(img_path) + ".json"print(f"识别成功,img_path: {img_path}, result_file: {result_file}")with open(result_file, 'w', encoding='utf-8') as f:f.write(json.dumps(results, ensure_ascii=False, indent=2))def main():ocr_manager = OcrManager(wechat_dir)# 设置WeChatOcr目录ocr_manager.SetExePath(wechat_ocr_dir)# 设置微信所在路径ocr_manager.SetUsrLibDir(wechat_dir)# 设置ocr识别结果的回调函数ocr_manager.SetOcrResultCallback(ocr_result_callback)# 启动ocr服务ocr_manager.StartWeChatOCR()# 开始识别图片ocr_manager.DoOCRTask(r"T:\Code\WeChat\OCR\Python\img\1.png")ocr_manager.DoOCRTask(r"T:\Code\WeChat\OCR\Python\img\2.png")ocr_manager.DoOCRTask(r"T:\Code\WeChat\OCR\Python\img\3.png")time.sleep(1)while ocr_manager.m_task_id.qsize() != OCR_MAX_TASK_ID:pass# 识别输出结果ocr_manager.KillWeChatOCR()if __name__ == "__main__":main()

运行结果:

源码仓库

https://github.com/kanadeblisst00/wechat_ocr

aardio版本

aardio作者也实现了一个aardio版本:https://mp.weixin.qq.com/s/kYGGyjKW-GJxlqGkmQfuBg

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/82327537.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

泰国股票盘搭建【TG:@Gangguhk】

功能最强大的股票配资系统 我们的股票配资系统是由拥有10年项目开发经验的资深技术人员,针对股票配资市场情况及股票投资者需要而精心研发,可同时运行于手机端、电脑端的多屏杠杆融资风控管理系统。功能包括自设配资额度、多级代理、交易管理、客户管理、警戒平仓、系统监控、…

openGauss AI4DB-数据库自治运维

AI4DB: 数据库自治运维 如上文所述,AI4DB主要用于对数据库进行自治运维和管理,从而帮助数据库运维人员减少运维工作量。在实现上,DBMind的AI4DB框架具有监控和服务化的性质,同时也提供即时AI工具包,提供开箱即用的AI运维功能(如索引推荐)。AI4DB的监控平台以开源的Prome…

服务端测试开发必备技能:Mock测试

什么是mock测试 Mock 测试就是在测试活动中,对于某些不容易构造或者不容易获取的数据/场景,用一个Mock对象来创建以便测试的测试方法。 Mock测试常见场景无法控制第三方系统接口的返回,返回的数据不满足要求 依赖的接口还未开发完成,就需要对被测系统进行测试Mock测试的缺点…

03、OSPF与BFD联动

OSPF与BFD联动定义 双向转发检测BFD(Bidirectional Forwarding Detection)是一种用于检测转发引擎之间通信故障的检测机制。 BFD对两个系统间的、同一路径上的同一种数据协议的连通性进行检测,这条路径可以是物理链路或逻辑链路,包括隧道。 OSPF与BFD联动就是将BFD和OSPF协…

获取layui表格(table)当前页的页码值和当前页的数据条数

获取layui表格(table)当前页的页码值和当前页的数据条数 在浏览器查看源码,获取当前页面的数据条数如下核心代码 $(".layui-laypage-limits").find("option:selected").val() //分页数目 $(".layui-laypage-skip").find("input").va…

PandasTA 源码解析(七)

.\pandas-ta\pandas_ta\momentum\stc.py # -*- coding: utf-8 -*- 从 pandas 库中导入 DataFrame 和 Series 类 从 pandas_ta.overlap 模块中导入 ema 函数 从 pandas_ta.utils 模块中导入 get_offset、non_zero_range 和 verify_series 函数# 定义函数:Schaff Trend Cycle (S…