此前,我們依次講解了軟硬件介紹及計數實例、相機的基本使用、基于形狀匹配的視覺定位、BLOB有無檢測、測量尺寸、機器視覺方案中使用到的標定功能、ZDevelop軟件實現識別條形碼和二維碼,測量點/直線/圓以及劃痕檢測功能。
本期課程我們和大家一起使用ZDevelop軟件實現機器視覺中使用到的OCR功能。
一、 OCR 檢測原理
什么是OCR?
OCR全稱是Optical Character Recognition,即光學字符識別。在機器視覺中OCR是指使用圖像處理方法將獲取到的圖像上的黑白字符進行分割訓練后,識別并輸出對應的字符。
OCR的檢測原理?
在機器視覺中進行OCR檢測時,首先根據字符(前景)和背景的對比度以及字符的寬度和高度等參數將字符進行分割后提取字符圖像,然后對提取的字符逐一進行訓練學習,將所有可能出現的字符進行訓練學習后存儲到訓練庫中,在執行識別檢測時,將當前提取到的字符和訓練庫中的字符進行對比,輸出相似度滿足條件的字符結果。
二 、OCR 應用場景
1.驗證字符準確性
可以驗證待測產品上印刷字符的準確性。
2.獲取產品字符信息
可以獲取待測產品上的字符信息上傳數據庫或錄入系統。
3.信息對比
可以將待測產品識別出的字符和條碼輸出的信息進行對比,判斷字符印刷和條碼信息是否一致。
三、 軟件實現
(一)流程圖
(二)實例演示
1.打開ZDevelop軟件:新建項目→新建HMI文件→新建main.bas文件,用于編寫界面響應函數→新建global_variable.bas文件用于存放全局變量并開啟HMI自動運行任務→新建InitParam.bas文件用于初始化測量參數→新建camera.bas文件用于實現相機采集功能→新建draw.bas文件用于更新繪制圖形刷新界面→文件添加到項目。
2.設計HMI界面。
3.在global_variable.bas文件中定義全局變量,定義完成后運行Hmi.hmi文件。
'''''全局變量大部分使用數組結構'''''
''注:basic編程中很多函數會以TABLE(系統的數據結構)做為參數
''在這里table均是做為中間變量
''table 21-22,鼠標按鍵,控件坐標系
''table 31-35,旋轉矩ROI參數,cx、cy、width、height、angle,控件坐標系
''table 41-45,旋轉矩形控件坐標轉換后對應的圖像坐標,圖像坐標系
'主任務狀態
'0 - 未初始化
'1 - 停止
'2 - 運行中
'3 - 正在停止
GLOBAL DIM main_task_state
main_task_state = 1
'采集開關
'0 - 停止采集
'1 - 請求采集
GLOBAL DIM grab_switch
grab_switch = 0
'相機個數
GLOBAL cam_num
cam_num = 0
'相機種類,"zmotion;mvision;basler;mindvision;huaray"
GLOBAL DIM CAMERA_TYPE(16)
CAMERA_TYPE = "mvision"
' 定義主任務id - 10
GLOBAL DIM main_task_id
main_task_id = 10
'定義連續采集任務id - 9
GLOBAL DIM grab_task_id
grab_task_id = 9
'定義全局圖像變量
GLOBAL ZVOBJECT grabImg '采集圖像
'定義常用顏色變量
GLOBAL C_RED, C_GREEN, C_BLUE, C_YELLOW
C_RED = RGB(255, 0, 0)
C_GREEN = RGB( 0,255, 0)
C_BLUE = RGB( 0, 0,255)
C_YELLOW= RGB(255,255, 0)
'訓練的字符庫、輸出的字符結果
GLOBAL DIM nameSample(32),result(32)
'旋轉矩形ROI參數:cx、cy、width、height、angle
GLOBAL DIM d_roi_rect2(5)
'檢測參數:閾值模式、閾值參數、最小字符面積、最大字符面積、最小字符寬度、最大字符寬度、最小字符高度、最大字符高度、字符極性、形態學類型、結構元寬、結構元高、字符最小間距
GLOBAL DIM d_detect_param(13)
'***********定義讀取本地文件功能相關變量**************
''注意,該功能只在使用仿真器時有效
'定義是否使用本地圖片標志
GLOBAL DIM d_use_imgfile
d_use_imgfile=1
'定義本地圖片索引
GLOBAL DIM d_index
d_index=0
'定義讀取圖片的路徑
GLOBAL DIM File_Name(100)
'***********結束定義讀取本地文件功能相關變量**********
'運行HMI文件
RUN "Hmi1.hmi",1
4.在InitParam.bas文件中初始化測量參數。
end
GLOBAL SUB init_detect_param()'初始化測量參數
'初始化roi參數
d_roi_rect2(0) = 160.0 'roi中心x
d_roi_rect2(1) = 120.0 'roi中心y
d_roi_rect2(2) = 80.0 'roi寬
d_roi_rect2(3) = 60.0 'roi高
d_roi_rect2(4) = 0.0 'roi角度
TABLE(31) = d_roi_rect2(0) '將roi變量賦值給起始地址為31的table數組
TABLE(32) = d_roi_rect2(1)
TABLE(33) = d_roi_rect2(2)
TABLE(34) = d_roi_rect2(3)
TABLE(35) = d_roi_rect2(4)
'初始化檢測參數:閾值模式、閾值參數、最小字符面積、最大字符面積、最小字符寬度、最大字符寬度、最小字符高度、最大字符高度、字符極性、形態學類型、結構元寬、結構元高、字符最小間距
d_detect_param(0) = 0 '手動閾值
d_detect_param(1) = 187 '低閾值
d_detect_param(2) = 500 '最小字符面積
d_detect_param(3) = 80000 '最大字符面積
d_detect_param(4) = 10 '最小字符寬度
d_detect_param(5) = 500 '最大字符寬度
d_detect_param(6) = 10 '最小字符高度
d_detect_param(7) = 500 '最大字符高度
d_detect_param(8) = 1 '白底黑字
d_detect_param(9) = 1 '開運算
d_detect_param(10) = 1 '結構元寬,正奇數
d_detect_param(11) = 10 '結構元高,正奇數
d_detect_param(12) = 1 '字符最小間距
nameSample="" '初始化訓練字符樣本為空字符串
result=" " '初始化字符結果變量為空字符串
END SUB
5.關聯HMI界面值顯示控件變量。
具體變量關聯操作可參考視頻中相關內容或獲取程序代碼進行參考。
6.在main.bas文件中添加HMI界面初始化函數并在Hmi系統設置中關聯初始化函數。
'HMI界面初始化函數
GLOBAL SUB hmi_init()
grab_switch = 0 '初始化采集開關為停止采集
main_task_state = 1 '初始化主任務狀態為停止狀態
'初始化時依據圖像分辨率設置區域的裁剪尺寸,此處圖像分辨率為1280x960
ZV_RESETCLIPSIZE(1280, 960)
'設置鎖存通道0的大小,以適應圖片元件控件大小
ZV_LATCHSETSIZE(0, HMI_CONTROLSIZEX(10, 1), HMI_CONTROLSIZEY(10, 1))
ZV_SETSYSINT("LineWidth",5) '設置繪制畫筆寬度為5個像素
init_detect_param() '初始化測量參數
ZV_LATCHCLEAR(0) '清空鎖存通道0
END SUB
7.在camera.bas文件中添加HMI界面中采集相關按鈕響應的函數并關聯動作函數。
end
'主界面按下掃描相機按鈕時響應的函數
GLOBAL SUB cam_scan_all()
if(d_use_imgfile=1)then
?"請先按下使用本地圖片按鈕關閉該功能"
return
endif
ZV_SETSYSINT("LogLevel", 7) '設置控制器信息
ZV_SETSYSSTR("DataDir","")
CAM_SCAN(CAMERA_TYPE) '掃描相機,CAMERA_TYPE="mvision"
cam_num = CAM_COUNT() '獲取掃描到的相機數量
if (0 = cam_num) then '如果相機數量=0,打印提示信息
? "未找到相機"
return '退出子函數,不往下執行
endif
?"cam_num = " cam_num '如果掃描到相機,打印相機數量
CAM_SEL(0) '選擇掃描到的第一個相機進行操作
CAM_SETEXPOSURE(5000) '設置相機曝光時間為5000us
CAM_SETMODE(0) '設置軟件觸發模式
CAM_START(0) '開啟相機
END SUB
'主界面按下單次采集按鈕執行的函數
GLOBAL SUB btn_grab()
'如果d_use_imgfile=1時使用讀取本地圖片功能,使用控制器時請將此部分代碼注釋掉
if (d_use_imgfile=1) then
if(d_index=3) then
d_index=0
endif
File_Name="\10"+TOSTR(d_index,1,0)+".bmp" '.../flash/10/目錄下的圖片所在的路徑名稱
ZV_IMGREAD(grabImg,File_Name,1)
ZV_LATCH(grabImg, 0)
d_index=d_index+1
return
endif
''讀取本地圖片功能結束
'如果相機數量為0,提示先掃描相機,并退出子函數不往下執行
if cam_num = 0 then
?"請先掃描相機!"
return
endif
CAM_SETPARAM("TriggerSoftware", 0) '發送觸發指令
CAM_GET(grabImg, 0) '獲取一幀圖像存放到grabImg變量中
ZV_LATCH(grabImg, 0) '將圖像顯示到鎖存通道0中
END SUB
'主界面按下連續采集按鈕響應的函數
GLOBAL SUB btn_cgrab()
if grab_switch =1 then '如果已經處于連續執行狀態,打印提示信息并退出函數
?"正在連續運行中,請勿重復操作!"
return
endif
if( d_use_imgfile =0) then '如果使用相機采集功能
if cam_num = 0 then '判斷如果相機數量=0,打印提示信息并退出函數
?"請先掃描相機!"
return
endif
endif
grab_switch = 1 '采集任務開關置1
if (1 = grab_switch) then
if (0 = PROC_STATUS(grab_task_id)) then
RUNTASK grab_task_id, grab_task '開啟連續采集任務
endif
endif
END SUB
'采集任務實現函數
grab_task:
while(1)
if (0 = grab_switch) then '如果采集任務開關=0即停止采集按鈕按下時
exit while '退出循環
endif
'grab_switch=1時重復執行以下操作
btn_grab()'單次采集按鈕響應的函數
wend
END
'主界面按下停止采集按鈕響應的函數
GLOBAL SUB btn_stopCgrab()
if grab_switch =0 then '如果已經處于停止采集狀態,打印提示信息并退出函數
?"未開啟連續采集!"
return
endif
grab_switch = 0 '將采集任務開關置0
END SUB
8.在draw.bas文件中添加檢測ROI更新繪制函數,并在自定義元件屬性窗口中關聯刷新函數和繪制函數。
end
'和繪制(即選擇ROI)有關的界面的刷新繪制函數放在這個bas文件里
DIM is_redraw '繪圖標志,0表示未進行繪制,1表示正在進行繪制
is_redraw = 0
DIM hit_pos '定義調整操作標志
'根據鼠標操作更新ROI位置區域函數
GLOBAL SUB update_roi()
if mouse_scan(21) = 1 then '掃描鼠標按下操作
'只有按下時可以改變擊中位置,獲取鼠標點擊位置對應的擊中區域編號
hit_pos = ZV_HMIADJRECT2(table(21), table(22), 31, -1)
is_redraw = 1 '繪圖標志置1
endif
if mouse_scan(21) = -1 then '掃描鼠標松開操作
'根據區域編號調整roi區域位置
ZV_HMIADJRECT2(table(21), table(22), 31, hit_pos)
is_redraw = 1 '繪圖標志置1
endif
if (MOUSE_state(21)) then '鼠標按下時
'根據區域編號調整roi區域位置
ZV_HMIADJRECT2(table(21), table(22), 31, hit_pos)
is_redraw = 1 '繪圖標志置1
endif
if (1 = is_redraw) then '如果繪制標志=1
is_redraw = 0 '繪圖標志置0
'控件roi坐標轉圖像roi坐標,控件坐標存放在起始地址為111的數組,圖像坐標存放在起始地址為50的數組
ZV_POSTOIMG(0, 1, 31, 41)
d_roi_rect2(0) = TABLE(41)'將圖像坐標的數據賦值給ROI變量
d_roi_rect2(1) = TABLE(42)
d_roi_rect2(2) = ZV_LENTOIMG(0, TABLE(33))
d_roi_rect2(3) = ZV_LENTOIMG(0, TABLE(34))
d_roi_rect2(4) = TABLE(35)
SET_REDRAW '重新繪制全部區域
endif
END SUB
'ROI區域更新后實時繪制ROI區域
GLOBAL SUB draw_roi()
SET_COLOR(C_BLUE) '設置畫筆顏色為藍色
ZV_HMIRECT2(31, 300) '將旋轉矩形roi分解為HMI支持的繪圖圖元并添加控制參數,便于HMI繪圖顯示
DRAWLINE(TABLE(300), TABLE(301), TABLE(302), TABLE(303)) '繪制外矩形
DRAWLINE(TABLE(302), TABLE(303), TABLE(304), TABLE(305))
DRAWLINE(TABLE(304), TABLE(305), TABLE(306), TABLE(307))
DRAWLINE(TABLE(306), TABLE(307), TABLE(300), TABLE(301))
DRAWLINE(TABLE(308), TABLE(309), TABLE(310), TABLE(311)) '繪制方向箭頭
DRAWLINE(TABLE(312), TABLE(313), TABLE(310), TABLE(311))
DRAWLINE(TABLE(314), TABLE(315), TABLE(310), TABLE(311))
END SUB
9.在main.bas文件中添加HMI界面按下【提取訓練】按鈕時響應的函數并關聯動作函數名。
'HMI界面按下提取字符按鈕時響應的函數
GLOBAL SUB btn_segment()
'定義檢測需要用到的變量:分割參數、樣本圖片庫、訓練樣本庫、OCR分類器、結果圖片
GLOBAL ZVOBJECT param,sample,trainSample,ocr,colorImg
'根據界面輸入參數生成分割參數
ZV_OCRSEGSETPARAM_(param,d_detect_param(0),d_detect_param(1),d_detect_param(2),d_detect_param(3),d_detect_param(4),d_detect_param(5),d_detect_param(6),d_detect_param(7),d_detect_param(8),d_detect_param(9),d_detect_param(10),d_detect_param(11),d_detect_param(12))
'根據分割參數和檢測區域進行字符分割,分割的字符樣本圖片存放到sample變量中
ZV_OCRSEGCHAR_(grabImg,param,sample,d_roi_rect2(0),d_roi_rect2(1),d_roi_rect2(2),d_roi_rect2(3),d_roi_rect2(4))
'獲取樣本數量,存放到table(100)中
ZV_OCRSAMPLECNT_(sample,100)
'灰度圖轉換到RGB圖,作為結果圖像
ZV_GRAYTORGB(grabImg, colorImg)
if(TABLE(100)>0) then '如果識別到的字符數量大于0
for i=0 to TABLE(100)-1'根據識別到的字符次數進行循環
ZV_OCRSAMPLERECT2_(sample,i,150)'獲取每個樣本字符的最小外接矩陣,用于顯示分割結果
'將樣本的最小外接矩陣繪制到界面中
ZV_RECT2(colorImg,table(150),table(151),table(152),table(153),table(154),C_GREEN)
next
elseif (TABLE(100)=0) then '如果未分割提取到字符
?"未成功分割提取出字符!" '打印提示并退出執行
return
endif
ZV_LATCH(colorImg,0)'在鎖存通道0中顯示結果圖像
if (STRCOMP(nameSample, "")=0)then '如果輸入的訓練字符樣本是空的
?"請先輸入訓練字符樣本再重新分割訓練!" '打印提示
return '返回子函數,不往下執行
endif
'清空OCR分類器
ZV_CLEAR(ocr)
if(ZV_ISEMPTY(trainSample)=0) then '如果訓練樣本庫不為空
ZV_OCRSAMPLECLR_(trainSample)'在訓練字符之前先清空樣本庫
endif
'根據輸入的訓練庫字符生成訓練樣本庫
ZV_OCRSAMPLEAPP_(sample,trainSample,nameSample)
'使用訓練樣本庫訓練分類器,0.8為優化參數(懲罰系數),表示分類器的預測能力, 越小預測能力越強但越容易出錯,范圍[0,1],建議 0.8;
'0.15為徑向基核參數,表示非線性映射能力,值越大非線 性映射能力就越強,范圍[0,1],建議 0.15
ZV_OCRTRAINSVM_(trainSample,ocr,0.8,0.15)
if(ZV_ISEMPTY(ocr)=0) then '如果分類器訓練成功
?"字符分割訓練已完成!" '打印成功提示
else
?"訓練字符和分割提取的字符不匹配!"
endif
END SUB
10.在main.bas文件中添加HMI界面按下【識別】按鈕時響應的函數并關聯動作函數名。
'HMI界面按下識別按鈕時響應的函數
GLOBAL SUB btn_test()
result=" " '清空字符結果變量
'根據界面輸入參數生成分割參數
ZV_OCRSEGSETPARAM_(param,d_detect_param(0),d_detect_param(1),d_detect_param(2),d_detect_param(3),d_detect_param(4),d_detect_param(5),d_detect_param(6),d_detect_param(7),d_detect_param(8),d_detect_param(9),d_detect_param(10),d_detect_param(11),d_detect_param(12))
'根據分割參數和檢測區域進行字符分割,分割的字符樣本存放到sample變量中
ZV_OCRSEGCHAR_(grabImg,param,sample,d_roi_rect2(0),d_roi_rect2(1),d_roi_rect2(2),d_roi_rect2(3),d_roi_rect2(4))
'獲取分割到的字符數量,存放到table(100)中
ZV_OCRSAMPLECNT_(sample,100)
if(TABLE(100)=0) then '如果未分割提取到字符
?"未成功分割提取出字符!" '打印提示并退出執行
return
endif
'使用訓練樣本和分類器識別字符并輸出字符結果到起始地址為50的變量中
ZV_OCRCLASSIFYSVM_(ocr,sample,32,50)
'獲取識別到的字符數量,存放到table(100)中
ZV_OCRSAMPLECNT_(sample,100)
'灰度圖轉換到RGB圖,作為結果圖像
ZV_GRAYTORGB(grabImg, colorImg)
if(TABLE(100)>0) then '如果識別到的字符數量大于0
for i=0 to TABLE(100)-1'將字符結果循環賦值給結果變量顯示到界面中
result(i)=TABLE(50+i)
ZV_OCRSAMPLERECT2_(sample,i,150)'獲取每個樣本字符的最小外接矩陣,用于顯示分割結果
'將樣本的最小外接矩陣繪制到界面中
ZV_RECT2(colorImg,table(150),table(151),table(152),table(153),table(154),C_GREEN)
next
endif
ZV_LATCH(colorImg,0)'在鎖存通道0中顯示結果圖像
END SUB
11.在main.bas文件中添加【運行】按鈕響應的函數并關聯動作函數。
'HMI界面按下運行按鈕時響應的函數
GLOBAL SUB btn_run()
if(2 = main_task_state) then '如果主任務處于運行中狀態
?"已經開啟連續運行任務,請勿重復操作!" '打印提示
return
endif
if (1 = main_task_state) then '如果主任務處于停止狀態
if (0 = PROC_STATUS(main_task_id)) then'如果程序中任務未開啟
main_task_state = 2 '將主任務狀態設置為運行中狀態
RUNTASK main_task_id, main_task'開啟主任務
endif
endif
END SUB
'主任務執行的函數
main_task:
while(1)
'如果主任務狀態處于正在停止狀態即停止按鈕按下時
if (3 = main_task_state) then
main_task_state = 1'將主任務狀態設置為停止狀態
exit while '退出循環
endif
'否則循環執行采集和識別函數
btn_grab()
btn_test()
wend
END
12.在main.bas文件中添加【停止】按鈕響應的函數并關聯動作函數。
'HMI界面按下停止按鈕時響應的函數
GLOBAL SUB btn_stop()
if (2 = main_task_state) then '如果主任務狀態處于2即任務運行中時
main_task_state = 3 '將主任務狀態置為3,退出循環
endif
END SUB
(三)仿真演示效果
本次,正運動技術VPLC系列機器視覺運動控制一體機快速入門(十)——OCR功能,就分享到這里。
更多精彩內容請關注“正運動小助手”公眾號,需要相關開發環境與例程代碼,請咨詢正運動技術銷售工程師:400-089-8936。
本文由正運動技術原創,歡迎大家轉載,共同學習,一起提高中國智能制造水平。文章版權歸正運動技術所有,如有轉載請注明文章來源。
-
機器視覺
+關注
關注
162文章
4372瀏覽量
120319 -
字符識別
+關注
關注
0文章
17瀏覽量
8653 -
OCR
+關注
關注
0文章
144瀏覽量
16361 -
正運動技術
+關注
關注
0文章
101瀏覽量
404
發布評論請先 登錄
相關推薦
評論