1. 求教從圖片中識別文字的方法和演算法,謝謝!
你的文字是掃描儀掃描的列印文本,還是用戶手寫的?
對於前者要用OCR技術,google提供的免費開源ocr包很厲害的(好像叫tessertocr)!現在版本都3.0支持包括中文在內的很多語言。這是個c語言的包
如果是手寫線條,,可以使用微軟的tablet組件,他對中文的識別,和漢王不相上下,畢竟是花了10億美元的貨。這個c++ c#都能用,,
2. OCR技術淺析
姓名:吳兆陽 學號:14020199009
轉自機器人學習研究會
嵌牛導讀:OCR(Optical Character Recognition,光學字元識別)的概念早於1920年代便被提出,一直是模式識別領域中重要的研究方向。近年來,隨著移動設備的快速更新迭代,以及移動互聯網的快速發展,使得OCR有更為廣泛的應用場景,從以往的掃描文件的字元識別,到現在應用到自然場景中圖片文字的識別,如識別身份證、銀行卡、門牌、票據及各類網路圖片中的文字。
嵌牛鼻子:ORC技術
嵌牛提問:什麼是ORC,如何使用?
嵌牛正文:
以深度學習興起的時間為分割點,直至近五年之前,業界最為廣泛使用的仍然是傳統的OCR識別技術框架,而隨著深度學習的崛起,基於這一技術的OCR識別框架以另外一種新的思路迅速突破了原有的技術瓶頸(如文字定位、二值化和文字分割等),並已在工業界得到廣泛應用。
筆者針對業務中的身份證照片文字識別需求分別嘗試了傳統OCR識別框架及基於深度學習的OCR識別框架。下面就以身份證文字識別為例分別簡要介紹兩種識別框架。
傳統OCR技術框架
如上圖所示,傳統OCR技術框架主要分為五個步驟:
首先文本定位,接著進行傾斜文本矯正,之後分割出單字後,並對單字識別,最後基於統計模型(如隱馬爾科夫鏈,HMM)進行語義糾錯。可按處理方式劃分為三個階段:預處理階段、識別階段和後處理階段。其中關鍵在於預處理階段,預處理階段的質量直接決定了最終的識別效果,因此這里詳細介紹下預處理階段。
預處理階段中包含了三步:
定點陣圖片中的文字區域,而文字檢測主要基於連通域分析的方法,主要思想是利用文字顏色、亮度、邊緣信息進行聚類的方式來快速分離文字區域與非文字區域,較為流行的兩個演算法分別是:最大極值穩定區域(MSER)演算法及筆畫寬度變換(SWT)演算法,而在自然場景中因受到光照強度、圖片拍攝質量和類文字背景的干擾,使得檢測結果中包含非常多的非文字區域,而目前從候選區域區分出真正文字區域主要兩種方法,用規則判斷或輕量級的神經網路模型進行區分;
文本區域圖像矯正,主要基於旋轉變換和仿射變換;
行列分割提取出單字,這一步利用文字在行列間存在間隙的特徵,通過二值化並在投影後找出行列分割點,當在文字與背景的區分度較好時,效果很好,而拍攝的圖片中光照、攝像質量的影響,並且文字背景難以區分時,常造成錯誤分割的情況。
下面介紹基於傳統OCR框架處理身份證文字識別:
身份證識別技術流程與上述框架稍微有所差異。對該問題,已知先驗信息:a.證件長寬固定;b.字體及大小一致;c.文本相對於證件位置固定;d.存在固定文字。因此,處理該問題的思路為:先定位目標物體(證件),矯正後提取文字進行識別,最後進行語義糾錯,如下圖:
目標物體定位並矯正。基於現有的先驗信息,定位最後的方法為採用模板關鍵點特徵匹配的方法,並利用模板上特徵點及目標圖像特徵點坐標之間的關系進行透視變換,以定位目標物體,如下圖所示。接著,基於四角的坐標,進行旋轉、仿射、尺寸的變換,並提取出目標物體的俯視圖。
因文字位置相對固定,接著便分割出文字區域,二值化後,行列分割出單個字元。這里的技術難點在於二值化,二值化效果的好壞直接影響字元分割,並最終影響識別結果。受光照和拍攝質量的影響,全局二值化難以設置統一的閾值,而自適應二值化演算法易受到陰影及模糊邊界的干擾。所以在這邊嘗試過許多方法,測試下來未發現在任何情形下效果都滿足要求的方法。
分割出單字後接著用分類器進行識別,並在這步基於統計上的先驗信息定義了一個簡單的優化函數,可看做1-gram語言模型。先驗信息為:2400(總共660273)漢字的使用頻率之和為99%以上。定義的優化函數為:
式中,Pi為該字出現的概率,confi為置信度值。
下圖給出了示例:
因上述的優化過程中假定各狀態相互獨立並與上一狀態沒有聯系,故不可避免存在語義上的錯誤。而如何基於現有的輸出序列,對序列進行語義上的修正,那麼最直觀的想法就是用隱馬爾可夫模型(Hidden Markov Model,HMM)解決這個問題,其基於觀察序列,求出最優隱序列。其可以抽象為如下圖的過程。在給定O序列情況下,通過維特比演算法,找出最優序列S:
傳統OCR冗長的處理流程以及大量人工規則的存在,使得每步的錯誤不斷累積,而使得最終識別結果難以滿足實際需求。接下來討論基於深度學習的OCR。
基於深度學習的OCR識別框架
目前,從技術流程上來說,主要分為兩步,首先是檢測出圖像中的文本行,接著進行序列識別。 可見,基於深度學習的OCR識別框架相比於傳統OCR識別框架,減少了三個步驟,降低了因誤差累積對最終識別結果的影響。
文本行檢測,其又可分為水平行文字檢測演算法與傾斜文字行檢測演算法。這里主要介紹下Tian提出演算法CTPN,其演算法框架如下圖。主要思路是將文本行識別看做一個序列識別問題,不同於一般的目標檢測問題,引入RNN來利用上下文的信息。
具體流程為:
用VGG16的5個卷積層得到特徵圖(feature map,W*H*C);
在Conv5的feature map的每個位置上取3*3*C的窗口的特徵,這些特徵將用於預測該位置k個anchor(anchor的定義和Faster RCNN類似)對應的類別信息,位置信息;
將每一行的所有窗口對應的3*3*C的特徵(W*3*3*C)輸入到RNN(BLSTM)中,得到W*256的輸出;
將RNN的W*256輸入到512維的fc層;
fc層特徵輸入到三個分類或者回歸層中。第二個2k scores 表示的是k個anchor的類別信息(是字元或不是字元)。第一個2k vertical coordinate和第三個k side-refinement是用來回歸k個anchor的位置信息。2k vertical coordinate表示的是bounding box的高度和中心的y軸坐標(可以決定上下邊界),k個side-refinement表示的bounding box的水平平移量。這邊注意,只用了3個參數表示回歸的bounding box,因為這里默認了每個anchor的width是16,且不再變化(VGG16的conv5的stride是16)。回歸出來的box如Fig.1中那些紅色的細長矩形,它們的寬度是一定的;
用簡單的文本線構造演算法,把分類得到的文字的proposal(圖Fig.1(b)中的細長的矩形)合並成文本線。
上圖為給出基於CTPN的例子,框線部分是演算法識別出的文字行,可見在圖片光照不均、人工合成及文字背景對比不明顯的情形下均有很好的效果。 相比於傳統文字定位方法,具有更好的魯棒性及明顯的優勢。
文字行識別。近兩年比較受關注的主要有兩種,一種是CNN+RNN+CTC的方法,另外一種是用attention model+CNN+RNN的方法。這里主要介紹下CNN+RNN+CTC,演算法框架由圖給出。分為三層,CNN層、RNN層及解碼(transcription)層。在CNN層,用於提取圖像特徵,利用Map-to-Sequence表示成特徵向量;在RNN層,用雙向LSTM識別特徵向量,得到每列特徵的概率分布;在解碼層,利用CTC和前向後向演算法求解最優的label序列。因此,該方法能夠識別不定長的文字行。
兩個例子:
Out:遼寧省長海縣廣鹿鄉沙尖
Out:河南省鄧州市九龍鄉姚營
3. 使用原始的c語言把bmp格式的圖片識別成文字
這個是最初級的OCR了
很麻煩的
可以到網上找找開源的ocr代碼參考一下。
4. 怎麼在c語言中調用騰訊雲的ocr文字識別api來識別文字
服務簡介:手寫體 OCR 識別,根據用戶上傳的圖像,返回識別出的欄位信息。
計費說明:本介面按實際使用量計費,具體定價請查看 計費說明。
URL說明:支持 http 和 https 兩種協議:
http://recognition.image.myqcloud.com/ocr/handwriting
https://recognition.image.myqcloud.com/ocr/handwriting
然後就是向它POST相應格式的數據就行了(用socket連接,發送HTTP request)。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
請求方式
請求頭 header
參數名 必選 值 描述
host 是 recognition.image.myqcloud.com 騰訊雲文字識別伺服器域名
content-length 否 包體總長度 每個請求的包體大小限制為6MB,不支持.gif類型的動圖
content-type 是 application/json 或 multipart/form-data 根據不同介面選擇:
1. 使用圖片 url,選擇 application/json;
2. 使用圖片 image,選擇 multipart/form-data。
authorization 是 鑒權簽名 多次有效簽名,用於鑒權,生成方式見 鑒權簽名方法
注意:
如選擇 multipart/form-data,請使用 http 框架/庫推薦的方式設置請求的 content-type,不推薦直接調用 setheader 等方法設置,否則可能導致 boundary 缺失引起請求失敗。
請求參數
參數名稱 必選 類型 說明
appid 是 string 接入項目的唯一標識,可在 賬號信息 或 雲 API 密鑰 中查看
image 否 binary 圖片文件,支持多個
url 否 String image 和 url 只提供一個即可;如果都提供,只使用 url
返回內容 欄位 類型 說明
code Int 返回狀態值
message String 返回錯誤消息
data.items array(item) 識別出的所有欄位信息
item 說明:
欄位 類型 說明
itemstring string 欄位字元串
itemcoord object 欄位在圖像中的像素坐標,包括左上角坐標 x,y,以及寬、高 width,height
words array(word) 欄位識別出來的每個字的信息
words 說明:
欄位 類型 說明
character string 識別出的單字字元
confidence float 識別出的單字字元對應的置信度,取值范圍[0,100]
5. 利用CRNN來識別圖片中的文字(二)tensorflow中ctc有關函數詳解
定歲滲義一個稀疏tensor。
將一個稀疏tensor轉換成稠密tensor。
計算ctc_loss。
主要參數1:labels: int32 SparseTensor 是數據的真實標簽,一般是先用桐橘sparse_placeholder(),然後在session中feed訓練數據batch_y。batch_y為 SparseTensor 利用sparse_tuple_from(y)函數計算得到。
sparse_tuple_from(y)函數的輸入是在train_y中隨機選擇大小為 batch_size 的數據,輸出是一個(indices, values, shape)形式的三元組。
主要參數2:inputs:是三維 float Tensor .logits是網路向前傳播inference計算的結果。形狀為[max_time_step, batch_size, num_classes]這里的num_classes是中文字典的局雀團大小,及992個漢字加1個空白,所以num_classes=993。輸入圖像經過卷積之後的大小為[batch_size, 11, 1, 512],max_time_step=512,是通道數,可以看作是512個圖片特徵序列。
主要參數3:sequence_length:一維 int32 向量【注意是向量,不是 Tensor !!!】長度為batch_size(批處理大小),值為max_len(ctc的最大輸出長度,這個長度是自己定義的!合理即可!)的可以按照下面的方式定義。
佔位符。在session中feed訓練數據。
6. 使用原始的c語言把bmp格式的圖片識別成文字
這個得有特徵提取的演算法了,鄙人不會
7. 利用CRNN來識別圖片中的文字(一)數據預處理
數據集中含有10072個圖片文件和10072個圖片所對應的包含圖片中中文字內容的文本宴攔渣文。
1.得到圖片數據集中所有的中文字元,構成字元字典,字典大小為所包含不同中文字元的類別數;(dict_size=992,加上一個「空白」,在CTC中一共含有992+1=993個類別)
2.構建訓練數據 train_x,train_y; train_x中每一個元素為一張圖片(cv2.imread()讀取的灰度圖),train_y 中每一個元素為圖片對應的文字在字元字典中的序號;
返回path路徑下的符合條件的所有文件,然後用for循環對每一個文件進行操作。
用於打開一個文件。創建衡嫌一個 file 對象,相關的方法才可以調用它進行讀寫。
readline()函數讀取整行,包括 "\n" 字元。
返回一個無序不重復元素集(這里用於刪除重復的中文字元)。
用於將元組晌悄轉換為列表。
8. CRNN演算法詳解
文字識別是對序列的預測方法,所以採用了對序列預測的RNN網路。通過CNN將圖片的特徵提取出來後採用RNN對序列進行預測,最後通過一個CTC的翻譯層得到最終結果。
所以CRNN演算法主要採用的是CNN+RNN+CTC三層網路結構,從下到上,依次為:
(1)卷積層,使用CNN,從輸入圖像中提取特徵序列;
(2)循環層,使用RNN,預測從卷積層獲取的特徵序列的標簽(真實值)分布;
(3)轉錄層,使用CTC,把從循環層獲取的標簽分布通過去重整合等操作轉換成最終的識別結果。
卷積層共包含7層卷積神經網路,基礎結構採用的是VGC的結構,其中輸入是把灰度圖縮放到尺寸為W*32,即固定高。在第三個和第四個池化層的時候,為了追求真實的高寬比例,採用的核尺寸為1*2(並非2*2)。為了加速收斂並引入了BN層。 把CNN提取到的特徵圖按列切分,每一列的512維特徵,輸入到兩層各256單元的雙向LSTM進行分類。在訓練過程中,通過CTC損失函數的指導,實現字元位置與類標的近似軟對齊。
如圖:
現在需要從CNN模型產生的特徵圖中提取特徵向量序列,每一個特徵向量(紅色框)在特徵圖上按列從左到右生成,每一列包含512維汪握特徵,這意味著第i個特徵向量是所有的特徵圖第i列像素的連接,這些特徵向量就構成一個序列。
由於卷積層,最大池化層和激活函數在局部區域上執行,因此它們是平移不變的。因此特徵圖的每列(即一個特徵向量)對應於原始圖像的一個矩形區域(成為感受野),並且這些矩形區域與特徵圖上從左到右的相應列具有相同的順序。特徵序列中的每個向量關聯一個感受野。
提取的特徵序列中的向量是從特徵圖上從左到右按照順序生成的,每個特徵向量表示了圖像上一定寬度上的特徵,論文中使用的這個寬度是1,就是單個像素。
如果一張包含10個字元的圖片大小為100×32,經過上述的CNN網路得到的特徵尺度為25×1(這里忽略通道數),這樣得到一個序列,每一列特徵對應原圖的一個矩形區域(如下圖所示),這樣就很方便作為RNN的輸入進行下一步的計算了,而且每個特徵與輸入有一個一對一的對應關系。
從上圖可以看出,對VGG的調整如下:
1.為了能將CNN提取的特徵作為輸入,輸入到RNN網路中,文章將第三和第困高慶四個maxpooling的核尺度從2×2改為了1×2
2.為了加速網路的訓練,在第五和第六個卷積層後面加上了BN層。
為什麼將第三和第四個maxpooling的核尺度從2×2改為1×2是為了方便的將CNN的提取特徵作為RNN的輸入.首先要注意的是這個網路的輸入為W×32,也就是說該網路對輸入圖片的寬沒有特殊的要求,但是高都必須resize到32。
假設現在輸入有個圖像,為了將特徵輸入到Recurrent Layers,做如下處理:
關於CNN原理詳解,具體可以參考: https://www.jianshu.com/writer#/notebooks/46006121/notes/71156459
因為 RNN 有梯度消失的問題,不能獲取更多上下文信息,所以 CRNN 中使用的是 LSTM,LSTM 的特殊設計允許它捕獲長距離依賴。
RNN網路是對於CNN輸出的特徵序列x=x1,⋯⋯,xt,每一個輸入xt,都有一個輸出yt, 為了防止訓練時梯度的消失,文章採用了LSTM神經單元作為RNN的單元。文章認為對於序列的預測,序列的前向信息和後向信息都有助於序列的預測,所以文章採用了雙向念衫RNN網路。LSTM神經元的結構和雙向RNN結構如下圖所示。
示例:
通過上面一步,我們得到了40個特徵向量,每個特徵向量長度為512,在 LSTM 中一個時間步就傳入一個特徵向量進行分類,這里一共有40個時間步。
我們知道一個特徵向量就相當於原圖中的一個小矩形區域,RNN 的目標就是預測這個矩形區域為哪個字元,即根據輸入的特徵向量,進行預測,得到所有字元的softmax概率分布,這是一個長度為字元類別數的向量,作為CTC層的輸入。
因為每個時間步都會有一個輸入特徵向量 ,輸出一個所有字元的概率分布 ,所以輸出為 40 個長度為字元類別數的向量構成的後驗概率矩陣,然後將這個後驗概率矩陣傳入轉錄層。
測試時,翻譯分為兩種,一種是帶字典的,一種是沒有字典的。
帶字典的就是在測試的時候,測試集是有字典的,測試的輸出結果計算出所有字典的概率,取最大的即為最終的預測字元串
不帶字典的,是指測試集沒有給出測試集包含哪些字元串,預測時就選取輸出概率最大的作為最終的預測字元串。
端到端OCR識別的難點在於怎麼處理不定長序列對齊的問題!(因為是不定長序列,按照以前的方法我們很難去計算loss,如果是定長的話容易造成信息的丟失,而且局限性太大!)
轉錄是將 RNN 對每個特徵向量所做的預測轉換成標簽序列的過程。數學上,轉錄是根據每幀預測找到具有最高概率組合的標簽序列。
具體可以參考: https://www.jianshu.com/writer#/notebooks/46006121/notes/71156474
9. C語言中如何識別字元與數字
凡是數字皆為字元。任何數字首先是字元,然後才能是數字。所以這個問題應該是如何在字元中識別數字。
直接將每個字元挨個提取出來,將他賦給一個整型,得到它的ASCII碼值。然後根據ASCII碼的范圍來判斷它到底是數字字元還是非數字字元。由下表可以得知,數字范圍在48~57的都是數字字元。
#include<stdio.h>
#include<ctype.h>
voidmain()
{
chara[10];
inti,j,flag=0;/*flag標記小數點個數,如果超過一個,那麼就不是數字*/
printf("inputanumber:
");
scanf("%s",a);
for(i=0;a[i]!=0;i++)
{
if(i==0&&(a[i]=='+'||a[i]=='-'))
{
i++;
continue;
}/*如果第一個字元為+或-,不判斷為非數字,可能是符號標志,繼續向下判斷*/
if(a[i]=='.')
{
flag++;
缺謹爛if(flag>1)/*如果小數點個數超過一個,則表示不是數字*/
{
break;
}
elseif(flag==1)/*如果小數點個數為1個,則可能為小數,繼續判斷*/
{
continue;
}
}
j=isdigit(a[i]);
if(j==0)
{
break;
}
}
if(j!=0)
printf("%syes",a);
else
printf("%sno",a);
getch();
}
10. c語言 關於漢字怎樣識別
每個漢字都用2個位元組表示,這兩個位元組必須都大於0xa0,所以漢野友字的兩個位元組必須是無符燃友號型(unsigned)。
常式:
unsigned char ch[2];
//把漢頌段槐字賦值給ch[2]
.....代碼略
if ((ch[0]>0xa0) && (ch[1]>0xa0))
{
// 漢字處理
}
else
{
// 字元處理
}