前言
本文是對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 認字 → 畫框寫字 → 用協議打包 → 串口發出 → 屏幕顯示
逐字、逐參數、逐括號都拆完了,直接復制即可跑。