【电赛学习笔记】MaxiCAM 的OCR图片文字识别
前言
本文是对MaixPy官方文档 MaixCAM MaixPy 实现 OCR 图片文字识别 - MaixPy 的项目实践整理与拓展,侵权即删。
功能介绍
OCR是MaixCAM中功能强大的数字文字识别模块,可以做到轻松的识别各种数字与文字。
OCR官方例程解析
工程源码
from maix import camera, display, image, nn, appmodel = "/root/models/pp_ocr.mud"
ocr = nn.PP_OCR(model)cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format())
disp = display.Display()image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size = 20)
image.set_default_font("ppocr")while not app.need_exit():img = cam.read()objs = ocr.detect(img)for obj in objs:points = obj.box.to_list()img.draw_keypoints(points, image.COLOR_RED, 4, -1, 1)img.draw_string(obj.box.x4, obj.box.y4, obj.char_str(), image.COLOR_RED)disp.show(img)
拆解
把整段代码拆成“零基础小白语言”,一行一行嚼碎了解释。
读完你就能知道:“这段程序到底在干嘛?每个括号里的东西是什么意思?”
🔑 先记住 3 个角色
角色 | 作用 | 比喻 |
---|---|---|
摄像头 | 拍照 | 眼睛 |
PP_OCR | 认字 | 大脑里的“识字老师” |
屏幕 | 把结果给你看 | 画板 |
🧩 逐行讲解
1️⃣ 把“识字老师”请进门
from maix import camera, display, image, nn, app
-
告诉 Python:我要用 摄像头、屏幕、画图、识字老师、退出按钮 这 5 个工具包。
model = "/root/models/pp_ocr.mud"
-
识字老师的“教材”放在板子里的
/root/models/pp_ocr.mud
。 -
.mud
就是 MaixPy 的模型文件(提前烧好的)。
ocr = nn.PP_OCR(model)
-
ocr
就是这位老师的名字。 -
nn.PP_OCR(...)
:用刚才那本教材,创建出识字老师。
2️⃣ 打开眼睛(摄像头)
cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format())
-
ocr.input_width()
:老师告诉我们“照片必须宽 320 像素”(举例)。 -
ocr.input_height()
:照片必须高 320 像素。 -
ocr.input_format()
:照片必须是 RGB888 格式。 -
摄像头就按这三条要求拍照。
3️⃣ 准备画板(屏幕)
disp = display.Display()
-
把板载 LCD 初始化成“画板”,后面用
disp.show(...)
把图刷上去。
4️⃣ 换一支能写中文的笔
image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size=20)
image.set_default_font("ppocr")
先把字体文件加载进来并取名
"ppocr"
,再告诉系统“以后写字默认就用它”。
这样后面draw_string
写中文时就不会缺字或乱码。
-
load_font
:把ppocr_keys_v1.ttf
这张“字体卡片”装进内存,取名叫"ppocr"
。 -
set_default_font
:后面写字都默认用这张卡片,字号 20。 -
把它想象成 “给电脑安装并设置默认输入法” 的三步:
① 把字体文件装进内存
image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size = 20)
参数 白话解释 类比 "ppocr"
给这套字体起个“小名”,后面写字时直接叫这个小名 把「搜狗拼音」安装后,系统里出现一个叫“搜狗”的输入法 "/maixapp/share/font/ppocr_keys_v1.ttf"
字体文件真正存放的位置 输入法安装包在硬盘上的路径 size = 20
默认字号 20 像素 安装时把默认字体大小调成 20 号 执行完这行,内存里就多了一套叫
"ppocr"
的字体,字号默认 20。
② 把这套字体设为“默认”
image.set_default_font("ppocr")
-
以后所有
draw_string(...)
如果不另外指定,就用刚才那套"ppocr"
字体。 -
就像 Windows 里把“搜狗”设为默认输入法,以后打字不用每次手动切换。
5️⃣ 无限循环:拍照 → 认字 → 画画 → 显示
while not app.need_exit():
-
一直循环,直到你按 Home 键或 IDE 停止。
-
app.need_exit()
就像“有人按了暂停键吗?”
5.1 拍照
img = cam.read()
-
摄像头立即拍一张图,存到变量
img
里。
5.2 交给老师认字
objs = ocr.detect(img)
-
ocr.detect(img)
:老师看图,返回 一堆“字对象” 列表objs
。 -
每个对象里包含:
-
字的内容(
obj.char_str()
) -
字的方框 4 个顶点 (
obj.box
)
-
5.3 把每个字框出来并写字
for obj in objs:
-
对每一个识别到的字,做下面两件事。
points = obj.box.to_list()
-
把字的 4 个角坐标变成列表,例如
[x1,y1,x2,y2,x3,y3,x4,y4]
。
img.draw_keypoints(points, image.COLOR_RED, 4, -1, 1)
-
在 4 个角上画红色小圆点(“红点钉”)。
参数:-
points
:要画的点 -
image.COLOR_RED
:颜色红 -
4
:点大小 4 像素 -
-1
:实心填充 -
1
:线宽 1(此处实心所以忽略)
-
img.draw_string(obj.box.x4, obj.box.y4, obj.char_str(), image.COLOR_RED)
-
在方框右下角
(x4, y4)
写文字本身。
参数:-
obj.box.x4, obj.box.y4
:文字左上角坐标 -
obj.char_str()
:识别到的文字(如“你”、“好”) -
image.COLOR_RED
:红色
-
5.4 把画好的图给屏幕
disp.show(img)
-
把整幅图立即刷到 LCD,你就能看到红框红字。
🎯 一句话总结
摄像头不停拍照 → PP_OCR 认字 → 程序把每个字用红框标出来并写上字本身 → 屏幕实时显示。
OCR应用拓展
本部分将实现,通过OCR识别文字然后通过串口协议通讯发送到MSPM0G3507单片机。
串口通讯部分内容可查看【电赛学习笔记】MaxiCAM 项目实践——与单片机的串口通信-CSDN博客
from maix import camera, display, image, nn, app, uart, time
import struct
from serial_protocol import SerialProtocol # 同目录下的协议类# ---------- 初始化 OCR ----------
model = "/root/models/pp_ocr.mud"
ocr = nn.PP_OCR(model)# ---------- 初始化摄像头 ----------
cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format())
disp = display.Display()# ---------- 加载中文字体 ----------
image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size=20)
image.set_default_font("ppocr")# ---------- 初始化串口 ----------
device = "/dev/ttyS0" # UART1:IO15(TX) IO16(RX)
serial = uart.UART(device, 115200)
proto = SerialProtocol() # 协议打包/解包工具while not app.need_exit():img = cam.read()objs = ocr.detect(img)# 本地可视化(可选)for obj in objs:points = obj.box.to_list()img.draw_keypoints(points, image.COLOR_RED, 4, -1, 1)img.draw_string(obj.box.x4, obj.box.y4, obj.char_str(), image.COLOR_RED)# 串口发送:改为索引遍历MAX_SEND = 3for idx in range(min(MAX_SEND, len(objs))):obj = objs[idx]text_utf8 = obj.char_str().encode('utf-8')payload = struct.pack('<H', idx) + text_utf8packet = proto.encode(payload)serial.write(packet)print(packet.hex(' '))disp.show(img)time.sleep_ms(50)
下面把 整段代码 拆成 “一句话一行” 的幼儿园级别讲解,每个括号、每个参数都说明白。你可以直接对着代码看注释。
0️⃣ 工具箱:把要用的“工具”搬进来
from maix import camera, display, image, nn, app, uart, time
-
告诉 Python:我要用 摄像头、屏幕、画图、神经网络、退出按钮、串口、延时 这些工具。
import struct
-
用来把数字/文字 打包成字节,方便串口发送。
from serial_protocol import SerialProtocol
-
把我们自己写的“串口协议”小工具请进来,负责加帧头、校验、帧尾。
1️⃣ 初始化“识字老师”
model = "/root/models/pp_ocr.mud"
-
OCR 老师的“教材”文件路径(提前烧在板子里)。
ocr = nn.PP_OCR(model)
-
用这本教材 创建 OCR 识别器对象,名字叫
ocr
。
2️⃣ 打开“眼睛”和“画板”
cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format())
-
摄像头拍照尺寸与老师要求一致:
ocr.input_width()
→ 宽(如 320)
ocr.input_height()
→ 高(如 224)
ocr.input_format()
→ 像素格式(RGB/BGR)
disp = display.Display()
-
初始化屏幕,准备把图刷上去。
3️⃣ 换一支“能写中文的笔”
image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size=20)
-
把字体文件
ppocr_keys_v1.ttf
装进内存,给它起小名叫"ppocr"
,字号 20。
image.set_default_font("ppocr")
-
以后写字默认都用
"ppocr"
这套字体。
4️⃣ 打开“嘴巴”(串口)
device = "/dev/ttyS0"
-
告诉系统:我要用 UART1(板子上 IO15=TX,IO16=RX)。
serial = uart.UART(device, 115200)
-
把串口波特率设成 115200,8N1,准备说话。
proto = SerialProtocol()
-
实例化“协议打包器”,负责给每句话加 帧头 AA、校验和、帧尾 55。
5️⃣ 主循环:一直干到死循环
while not app.need_exit():
-
如果没人按“停止”键,就一直循环。
5.1 拍照
img = cam.read()
-
摄像头立刻拍一张图,存进变量
img
。
5.2 让“识字老师”看图
objs = ocr.detect(img)
-
把图交给
ocr
识别,返回一个 OCR_Objects 列表,里面每条是一个字/一行文字。
5.3 本地画画(可选,但看得见)
for obj in objs:
-
对识别到的 每个文字块 做下面两件事。
points = obj.box.to_list()
-
把 四边形框 的四个顶点变成
[x1,y1,x2,y2,x3,y3,x4,y4]
。
img.draw_keypoints(points, image.COLOR_RED, 4, -1, 1)
-
在四个角画 红色实心小圆点(大小 4 像素)。
img.draw_string(obj.box.x4, obj.box.y4, obj.char_str(), image.COLOR_RED)
-
在右下角 写文字本身,颜色红色。
5.4 串口发送:最多发 3 条
MAX_SEND = 3
-
每帧最多发 3 条文字,防止串口拥堵。
for idx in range(min(MAX_SEND, len(objs))):
-
实际条数取 “3 与识别数量” 的较小值,避免越界。
obj = objs[idx]
-
拿第
idx
条文字对象。
text_utf8 = obj.char_str().encode('utf-8')
-
把文字转成 UTF-8 字节流(1 个汉字 3 字节左右)。
payload = struct.pack('<H', idx) + text_utf8
-
小端 16 位序号(2 字节)+ 文字字节流 → 组成 payload。
packet = proto.encode(payload)
-
用协议类给 payload 加帧头、长度、校验、帧尾。
serial.write(packet)
-
把完整的 协议帧 通过 UART1 发出去。
print(packet.hex(' ')) # 调试用
-
在控制台打印十六进制,肉眼检查帧格式。
5.5 把画好的图刷到屏幕
disp.show(img)
-
把带红框红字的图像显示到 LCD。
time.sleep_ms(50)
-
每帧后休息 50 毫秒,让 CPU 喘口气;可删。
🎯 一句话总结
摄像头拍照 → OCR 认字 → 画框写字 → 用协议打包 → 串口发出 → 屏幕显示
逐字、逐参数、逐括号都拆完了,直接复制即可跑。