引言
手寫數(shù)字識別是一個很基礎(chǔ)的模式識別問題,從傳統(tǒng)特征提取加機器學(xué)習(xí)訓(xùn)練方法到深度神經(jīng)網(wǎng)絡(luò)訓(xùn)練的識別方法識別都會達(dá)到比較高的精度,同時手寫數(shù)字識別也是一個特別不穩(wěn)定,很難具備普適性的模型,需要針對性的數(shù)據(jù)集與訓(xùn)練,然后才得到比較好的識別精度。
OpenVINO 在2021.4 版本中已經(jīng)加入了手寫數(shù)字識別的預(yù)訓(xùn)練模型,開始支持手寫數(shù)字識別,下面讓我們一起探索與嘗試下它的使用方法與效果如何!
模型介紹
在OpenVINO 2021.4版本中支持的手寫數(shù)字識別模型為handwritten-score-recognition-0003
,支持《digit》 or 《digit》。《digit》 格式的數(shù)字識別與小數(shù)點識別。該模型的結(jié)構(gòu)有兩個部分組成,前面是一個典型的CNN骨干網(wǎng)絡(luò),采用的是VGG-16類似的架構(gòu),實現(xiàn)特征提取;后面是一個雙向的LSTM網(wǎng)絡(luò),實現(xiàn)序列預(yù)測;最終的預(yù)測結(jié)果基于CTC解析即可。其輸入與輸出格式如下:
輸入格式為:[NCHW]= [1x1x32x64]
輸出格式為:[WxBxL]=[16x1x13]
其中13表示“0123456789._#”,#表示空白、_表示非數(shù)字的字符
對輸出格式的解碼方式支持CTC貪心與Beam搜索,演示程序使用CTC貪心解碼,這種方式相對簡單,前面一篇文章中我們已經(jīng)詳細(xì)介紹過了,后面就直接套用即可!
模型使用與演示
使用該模型必須是基于常見文字檢測得到的ROI區(qū)域,然后轉(zhuǎn)化為灰度圖象,使用該模型完成預(yù)測,關(guān)于場景文字檢測,在前面一篇文章中我已經(jīng)詳細(xì)交代過了,這里就不再贅述。這里小可腦洞大開,針對常見的文本圖象,采用OpenCV二值圖象輪廓分析來完成數(shù)字ROI區(qū)域得截取,同樣取得了不錯得效果。基本的流程是這樣:
Step 1: 讀取圖象并二值化
代碼如下
Mat src = imread(“D:/images/zsxq/ocr.png”);
imshow(“input”, src);
Mat gray, binary;
cvtColor(src, gray, COLOR_BGR2GRAY);
adaptiveThreshold(gray, binary, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 25, 10);
其中adaptiveThreshold函數(shù)實現(xiàn)對灰度圖象自適應(yīng)二值化,參數(shù)blockSize=25表示高斯窗口大小,constants=10表示自適應(yīng)常量值。需要注意的是參數(shù)blockSize值必須為奇數(shù)。
Step 2: 使用輪廓分析過填充過濾小噪點
代碼如下
std::vector《vector《Point》》 contours;
std::vector《Vec4i》 hireachy;
findContours(binary, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
int image_height = src.rows;
int image_width = src.cols;
for (size_t t = 0; t 《 contours.size(); t++) {
double area = contourArea(contours[t]);
if (area 《 10) {
drawContours(binary, contours, t, Scalar(0), -1, 8);
}
}
上面的代碼findContours表示輪廓發(fā)現(xiàn),RETR_EXTERNAL表示采用發(fā)現(xiàn)最外層輪廓,CHAIN_APPROX_SIMPLE表示采用簡單的鏈?zhǔn)骄幋a收集輪廓上的像素點集。contourArea表示計算一個輪廓的面積,計算方式基于格林積分公式。drawContours表示繪制輪廓,其中thickness參數(shù)為-1表示填充,大于零表示繪制邊緣。這里通過對白色噪點填充為黑色,完成噪聲去除,
Step 3:膨脹預(yù)處理
對第二步輸出的圖象我們不能直接通過輪廓發(fā)現(xiàn)截取ROI,然后交給數(shù)字識別網(wǎng)絡(luò)去識別,原因是這樣會導(dǎo)致ROI區(qū)域的寬高比失衡,導(dǎo)致輸入的數(shù)字resize之后發(fā)現(xiàn)畸變,識別精度會降低,所以通過膨脹操作,把數(shù)字適度的加寬與加高,主要是加寬,這樣保持輸入ROI區(qū)域resize之后不變性,就很容易識別了。這部分預(yù)處理的代碼如下:
Mat se = getStructuringElement(MORPH_RECT, Size(45, 5));
Mat temp;
dilate(binary, temp, se);
其中dilate表示膨脹操作、然后對得到temp圖象。
Step 4:數(shù)字識別推理與解析
對圖-4進(jìn)行輪廓發(fā)現(xiàn),截取ROI,遍歷每個輪廓,調(diào)用識別推理即可輸出。其中加載模型與獲取推理請求,這里就不再贅述了,截取ROI與推理解析部分的代碼如下:
// 處理輸出結(jié)果
findContours(temp, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (size_t t = 0; t 《 contours.size(); t++) {
Rect box = boundingRect(contours[t]);
Mat roi = gray(box);
size_t image_size = h*w;
Mat blob_image;
resize(roi, blob_image, Size(w, h));
// NCHW
unsigned char* data = static_cast《unsigned char*》(input-》buffer());
for (size_t row = 0; row 《 h; row++) {
for (size_t col = 0; col 《 w; col++) {
data[row*w + col] = blob_image.at《uchar》(row, col);
}
}
// 執(zhí)行預(yù)測
infer_request.Infer();
auto output = infer_request.GetBlob(output_name);
const float* blob_out = static_cast《PrecisionTrait《Precision::FP32》::value_type*》(output-》buffer());
const SizeVector reco_dims = output-》getTensorDesc().getDims();
const int RW = reco_dims[0];
const int RB = reco_dims[1];
const int RL = reco_dims[2];
std::string ocr_txt = ctc_decode(blob_out, RW, RL);
std::cout 《《 ocr_txt 《《 std::endl;
cv::putText(src, ocr_txt, box.tl(), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255, 0, 0), 1);
cv::rectangle(src, box, Scalar(0, 0, 255), 2, 8, 0);
}
首先進(jìn)行輪廓發(fā)現(xiàn),然后根據(jù)每個輪廓截取ROI區(qū)域,設(shè)置輸入數(shù)據(jù),推理,解析輸出采用CTC方式。
擴(kuò)展探索
這里我沒有采用場景文字檢測來獲取ROI,而是采用傳統(tǒng)的二值圖象分析來完成,主要是避免跟前面的文字內(nèi)容重疊,同時啟發(fā)更多的思路。另外采用膨脹擴(kuò)展。
有時候并非是上上之選,還可以直接修改ROI大小來擴(kuò)展,這部分其實可以參考上一篇場景文字識別的代碼,輪廓發(fā)現(xiàn)獲取外接矩形,直接修改ROI大小的方式,同時根據(jù)橫縱比過濾非數(shù)字符號。改動部分就是去掉第三步膨脹,然后直接在第四步循環(huán)中添加下面的代碼;
Rect box = boundingRect(contours[t]);
float rate = box.width / box.height;
if (rate 》 1.5) {
continue;
}
box.x = box.x - 15;
box.width = box.width + 30;
box.y = box.y - 5;
box.height = box.height + 10;
編輯:jq
-
數(shù)字識別
+關(guān)注
關(guān)注
2文章
19瀏覽量
10140
原文標(biāo)題:OpenVINO? 手寫字符識別模型與使用
文章出處:【微信號:英特爾物聯(lián)網(wǎng),微信公眾號:英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論