本文的作者在教育行業搞OCR識别工作,教育領域的OCR比較複雜,除了文字外,還有圖片、表格、公式等等。即便同樣是公式,在數學裡要斜體,在化學裡要正體,這都是行業規範。
本文的讀者是誰呢?讀者是……最終誰會讀,我不知道。但是,我定位以下人群為本文的讀者,換句話說,我就是寫給他們看的。
1.1 公司領導:節省成本,沉澱技術很多企業領導,看到OCR屬于人工智能範疇,很恐懼。哎呀,我們公司的員工,連正常的業務邏輯都寫不好,交付個系統一堆Bug。
現在需要使用OCR功能了,怎麼辦?買一個吧。不買難道自己做嗎?那樣,我還要建一個人工智能團隊。
這個情況,還真得具體分析。
我了解到有一家公司,他們的OCR識别需求非常簡單:僅僅識别0到9,共10個數字。而且,數據來源單一,保證透明背景純色線條字迹。這種待識别的樣本,非常規範。
其實,随便找一本圖像識别的書,翻開第一章,幾乎都是在講如何識别這類數字,這個例題已經20多年了。這在程序員中,被稱為是Hello World級别的程序,是入門的第一課,沒有難度。
甚至谷歌公司覺得這太簡單了,以至于人工智能受到了侮辱。于是,他們率先把入門的例子,由10個數字,改成了識别“輪船”、“汽車”、“青蛙”、“小鳥”等10類物體。
但是,這家公司依然以30萬一年的價格,購買了一個識别數字的OCR服務。
這就像是買了輛大巴車,當電動車來用,一個人開着它走街串巷,維護成本高,利用率也低。
因此,我感覺,領導不需要了解技術細節,但是需要大體了解它的成熟度和行業狀态。
本文會講述做OCR的流程,以及每一步需要的資源支持,以便領導們可以盤點資源,量入為出。
1.2 産品經理:了解過程,融會貫通産品經理經常被開發人員怼。一方面是開發人員性格過于剛直。另外就是産品經理,有時候确實不了解實現過程就亂提需求:比如,App主題色要随手機殼的顔色來變化。
但是,我也見過那種開發出身的産品經理,他不僅懂産品,也懂技術。
他經常把開發人員怼得一愣一愣的:怎麼實現不了?這邊有數據,那邊也有,做一個關聯,查詢時别不加限制,那樣太慢!
開發人員則紅着臉,遇到新需求時,先自己百度一下,做完了功課再去找這個産品經理辯論。最後,開發人員沮喪着回來,百度也不靠譜啊,原來是有實現思路的!
因此,我感覺産品經理需要了解技術的實現過程,以便在關鍵節點上,可以提出産品側的更優方案。
本文會講述實現OCR需要幾個步驟,以及每個步驟的關鍵點是什麼。我覺得産品經理有必要看。
1.3 初級小白:解疑答惑,入門行業有人覺得OCR好神奇,怎麼做到的?我不明白,誰來給我解釋解釋。這是對此感興趣的求知者。
也有人,非常喜歡圖像識别,自己想學,但是經常會被拒之門外。這是懷有滿腔熱情和憤懑的技術小白。
網絡上,确實有很多大牛,博士碩士研究生,但是因為他們的水平很高,我們很難與他們對話。我曾經被鄙視:一個傅裡葉變換,一句話就可以解釋清楚,你卻寫了幾千字,說了一堆廢話。
于是,我認識到“同等對話”很重要。如果我想要實現小康家庭的生活,那我去找全球商業大亨請教,可能起不到什麼效果,反而去跟樓下五金店的老闆拉拉家常,能有所收益。
現在,我弄明白了OCR識别。同時,我也想起之前的迷茫和無助。現在,或許還存在很多曾經的我,我要自己幫一下自己。
本文會講整個OCR的完整流程,以及其中的難點和解決方案(思路以及術語關鍵詞)。如果你是程序員的話,我在專業版裡,還有代碼詳解。
OCR這個行業,如果無法入門,掉頭就走,一旦入門,愛不釋手。
好了,前言我說完了,也算是導讀,如果覺得本文适合你,可以繼續往下看了。
二、OCR識别的全流程(科普版)OCR是一個簡稱,全稱叫Optical Character Recognition,中文是:光學字符識别。
它的本質是:把圖像形狀轉變為文本字符。
下面說一下,我在教育行業是如何應用OCR的。
信息化教學越來越普及,很多教學素材都要搬到信息化平台,比如試卷試題。那麼,紙質的試卷要電子化,就會用到OCR識别技術。
這麼一張圖,需要識别成結構化(圖片、文字、公式、表格可獨立提取出來)的數據,識别結果如下所示:
而且,識别結果還可以下載成word文檔,便于老師校對并進行二次編輯:
這就是OCR的一個典型應用。
除此之外,我們常見的各種證件識别、名片識别、車牌識别等,也涉及OCR技術。
我在入門OCR的時候,做過一個小功能,我把它作為一次學結和畢業小考,效果如下:
上面這個例子,在github上已經完全開源。此例子基本囊括了OCR的全過程,下面我就以它作為樣闆,來講一講OCR的全流程。
OCR技術的實現,總體上可以分為五步:預處理圖片、切割字符、識别字符、恢複版面、後處理文字。
中間的三步是核心,頭尾兩步最難。
2.1 預處理圖片
我們買回來水果,需要洗一下再吃。如果運氣不好的話,還需要挖掉蟲眼和糙皮才能吃。我們把吃水果前的這些步驟,叫做CSG(吃水果)的預處理。
在進行OCR之前,也需要對圖片進行預處理。因為,一般待識别的圖片千奇百怪,來源複雜:有拍照、有掃描、有截圖。
拿拍照來說,有夏至那天中午頭兒,在陽光直射下拍的;也有人在傍晚,拿着大頂轉着圈兒拍的。如果不進行預處理,OCR會很為難,就像你面對剛從糞池裡撈上來的大棗一樣為難。
2.1.1 光影的預處理一般情況下,我們定義白色為背景,黑色為字體。
但是,如果圖片上有了光影,就會存在模糊狀态。說它是背景吧,它不是白色的。要說它是文字吧,黑乎乎地一片兒,也認不出來有什麼字符。這導緻OCR經常人格分裂,這是……這不是……它是不是呢?智能出現了問題,人工一看,我給做個預處理吧,交給你的時候保證非黑即白,你專心做事就行。OCR很感動。
2.1.2 傾斜的預處理
理想條件下的文檔圖像,應該是水平的,這樣方便切割方塊字。
但是,現實世界中,不管是人,還是素材,都很難擺正自己的位置。
不正,切起來就複雜了。治圖,如同治人,需要分門别類(強制升華文章格調)。
上面這種傾斜最為常見,處理起來也最簡單。隻需要幾句代碼就能搞定,我會在以後專門介紹。基本原理就是找到文本的最小面積矩形(關鍵詞:minAreaRect),然後旋轉這個矩形,實現角度矯正,看下面這個動态圖。
但是,這種方法有時候也不靈,比如下面這張圖。
我們現在框一個矩形,完美!
我們再把矩形擺正,完蛋!
這種傾斜,無論怎麼擺矩形都不行,因為矩形區域内的文字又有傾斜!
這時候,就需要用另一種方法,叫做霍夫線變換(關鍵詞:HoughLinesP。有時候搜索一個問題,都不知道該搜啥,此處我提供了關鍵詞,其解決方案可直達靈魂)。
霍夫線變換就是在圖上找直線,因為圖中的若幹點,是可構成一條直線的。把這些直線畫出來,你會發現玄機,看下面的動态圖。
一段若幹行的文本,每一行的字都應該是在一條直線上的。
從結果倒推過程,如果找到了一行直線,那麼是不是就找到了一個文本行。
當把這些直線擺正時,就實現了文檔的矯正。看下面的動态圖。
2.1.3 扭曲的預處理
上面講的是平面的角度傾斜,此類情況在複印和掃描中較多(紙張放斜了)。
這不算嚴重,頂多就如同用涼水泡方便面,問題不大。
其實,我們遇到更多的圖像是照片。拍照,問題就多了,會存在空間的扭曲。看下面的動态圖(圖是動态的,如果不是,等一等,或者你遇到盜版的作者了,正版作者是ITF男孩)。
上面的圖,問題就比較嚴重了,就如同用煤油泡方便面,還非得讓别人吃,這叫扭曲。
空間的扭曲,體現在視覺上就是遠大近小。
我們來矯正下面這張圖,這張圖應該是站在長城上拍的長廊,越遠越小。
肯定能矯正,就是步驟有點多。但是,換算成代碼,也不會超過100行。下面這張動态圖裡,我把每一步對圖片處理的方法也都列上了。總共9步,每一步都可以單拉出一篇文章來講解(寫到這裡,我想出視頻教程了,給我點贊,鼓勵我)。
上面的2.1章節部分,講的都是最基礎的預處理操作。
如果你的圖片來源很複雜,尤其是包含各種場景下的拍照,或者也有從漫山遍野撿來的野生圖片、二手改裝圖片。那麼,你的預處理工作将會比較費勁,沒有難點,但是需要耗費人力物力,需要時間。
如果,你的圖片來源很簡單。就像我開頭講的,0到9數字識别還購買OCR服務的例子。他們公司是用電子采集筆在電子方格上寫數字,電子方格是統一的,筆是統一的,樣本非常标準。這種情況,不需要預處理,直接進入下一步,切割字符(媽呀,這個轉場,太絲滑了)。
2.2 切割字符假設,通過了預處理,我們的圖片都變成像下圖這樣規範。
我忽然想到,我們是要做OCR字符識别的(你……幹啥來的)。
于是,我們需要切割字符,把每一個字……都給他(咬着牙,發狠的表情)……挖出來。
為什麼要把每個字符都切割出來?因為OCR最終是對單個字符進行識别的(識别26,其實是識别“2”和“6”)。
并且,還需要對每個字符做好标記,因為識别完了,還得還原回去。識别完了,結果是一堆單蹦的“1”、“2”、“3”、“ ”、“-”字符。我們需要根據它們的相對位置,還原成“8-7=1”。所以,我們就知道了,哪個題目做對了,做錯了,從而給出批改結果。
2.2.1 投影法實現分割
上帝說要有光,就有了光。如果有姓尚的朋友,可以給孩子起名叫:尚有光。
有光以後,當光投過來時,物體的背後就有了影。有影子的地方就有實體,沒影子的地方就有空隙。
那位說了(我也不知道哪位),你扯這些幹什麼?這是三歲小孩子都懂的常識。
沒錯,三歲小孩子都知道。但是三十歲的大孩子不一定能想到,這個常識可以用來分割字符。
2.2.2 切行假設我們拿着一根頭發絲兒,橫着收集像素點,從左側插入,從右側推出。把所有黑點都壓縮到一起,把黑色素……嗯,黑色素堆到最右側。就像下面的圖這樣。
此時,我們就能清楚地知道哪個區域是有文字的行,哪個區域是白紙。這個價值兩百五的操作,可以實現行的切分。
這一招就是投影大法,三歲孩子都了解。
2.2.3 切列切行是橫着切,切列就得豎着切了。
一定要先切行,再切列。多數情況,行是有行距的,每一行都會有明顯的界限。但是列……如果把整個文檔做投影的話,基本上就淪陷了。
上面那樣做投影,拆不出單個字符。因為一篇文檔的字,就像城牆一樣,磨磚對縫,無法切分。
但是,換成對一行文本進行投影分析,就可以了。看下面這個圖,非常之清晰。
通過投影之間的間隙,我們就可以把每個字符切割開來。
2.2.4 切字有了行與列切分的方法,相信把字符切出來,應該是不難的。其實就是很簡單,代碼也不複雜。全都是數組的分析。
那麼切出來的字,最終是這樣。
不是白紙黑字嗎?為什麼都變成了黑底白字呢?
其實,這是故意的。為的就是要方便OCR進行識别。我們都知道(也可能不知道),在RGB色值中,0代表黑色,255代表白色。
不管計算機的算力多麼強大,一秒鐘能運算多少億萬次,它的底層還是二進制,也就是101010。你可以簡單地理解成它隻認識數字。你看到字母A是A,計算機沒有你那麼厲害,計算機偷偷地在顯示器上輸出A這個圖案,然後心裡暗自記下這個物體是65。
因此,任何文本、圖片、音視頻,最終都要被解析成數字,這樣計算機才能幹活。
扯這些有什麼用?你在逃避什麼?黑白颠倒的問題呢?
别急,馬上。我們希望計算機識别圖片上的字,而不是背景。所以,把背景置為黑色,也就0,把字符變成白色,也就是255,這樣有利于計算機更專注于分析字符的痕迹。因為,0默認是忽略掉的。
你看,說着說着,就談到了人工智能的機器學習。哈哈,又轉場了,真爽。
2.3 識别字符圖片究竟是怎麼變為字符的?它還能自己學習。
計算機通過學習一些樣本之後,遇到一些從未遇到過的同類樣本,也能正确地識别出結果,這很神奇。我想了一夜也沒想明白。
第二天,我帶着孩子去公園,公園門口有一對大獅子。孩子指着獅子說,狗!我說,哦,那不是狗,那是獅子,跟狗有點像是不是。又走了一段路,公園裡又出現一個麒麟的雕塑。孩子指着它說,獅子!我說,那不是獅子。孩子說,是狗。我說也不是狗,它叫:麒麟。我感覺到,孩子的大腦在反向矯正信息,這就是監督學習。
當我給他看狗的圖片時,我告訴她這是狗。
她根據自己的認知,找了幾個特征,構建了一個模型:長嘴 尖牙=狗。
雖然隻是看過圖片,但是出門遇到真狗,她根據這個模型也認識對了。
後來,她遇到了獅子,她修改了模型:長嘴 尖牙 鬃毛≠狗=獅子。
後來,又遇到了麒麟,這個公式變得越來越複雜……決策項越來越多。
人工智能,就是模拟的人類的神經元,構建神經網絡來嘗試尋找特征和結果的關系。如果對了,就給這個特征加分。如果,錯了,就給這個特征減分。
識别數字,也是一樣。
比如在學習識别數字6的時候,它随機認為隻要有一個圈圈特征,就是數字6。
驗證其他樣本時,發現這個随機特征是對的(不對就再換一個特征再試)。于是,它建立了一個模型:隻要有圈這個特征,就是6。
後來,這個模型遇到了數字0。加入新樣本後,人工智能發現,0也有圈,但它不是6,也有可能是0。得再找一個特征,于是,新增一條,有勾就是6。後來,它又遇到了9。那勾在上面的就是6。後來,它又遇到了字母b……反正計算機有的是算力,能在很短的時間内完成這些學習。上面我是摟着說的,其實即便在32*32像素的小圖片上,它随機上幾十個特征去做驗證,一點都不吃力。
這就是識别字符的原理。具體到代碼,也很簡單,因為人工智能框架目前已經非常成熟。雖然,這篇是科普版,不是專業版,不适合講代碼,但是我還是非常想貼上一段代碼,給大家看看。打破你的認知,人工智能的應用層很簡單,别被忽悠了。
舉個例子,識别10類常見物體:飛機、自行車、鳥,貓,鹿、狗、青蛙、馬、輪船、汽車。
它的核心代碼隻有……6行。
所以,OCR字符的識别從來不難。難的是兩頭,比如開頭的預處理,以及下面要說的後處理。
2.4 文本後處理識别出了字符,意義不大,有效地連接起來才能發揮作用。
一定要記住我上面說的這句話,默讀3遍以上。
其實,這句話沒啥用,隻是有助于緩解緊張的氣氛!
對于類似的話,我認為是廢話,因為沒有任何指導意義,但是說的也沒錯。
2.4.1 版面還原可能有人會覺得,我接下來講的會比較跳躍,有點作者着急去廁所的感覺。這并不是什麼寫作風格,這篇文章我快寫吐了,很想快點結束。或許我該搞一個系列專題,我比較喜歡講述體系化的東西,不喜歡一次冒一個點,那樣對别人沒有什麼深度價值。
也可能有人覺得,版面還原不難(是的,進入正題了),字符我都拆開了,坐标也記錄了,把識别的字符畫上,不就還原了?!
沒錯,說的很對,把識别的結果畫上去,視覺上是還原了。
但是,這依然屬于單個字符識别的那一步,隻不過做成了結果可視化,是坐标還原,并不是版面還原。
我們期望的拆分和還原應該是下面這樣:
“10 2= 4-3= 5 6=11”這些文本從數據結構上應該是一行。而且,“10 2=”從數據結構上是一個基本單位。因為,我們要對基本單位做運算和批改。這才叫還原,其實并不簡單。
有點震驚,我拆字的時候,沒有人跟我要求過這些規則。
舉個小例子,這個例子非常小,假設你識别出來了2個字,你現在有2個字符的數據:
請問,這兩個字,是不是在處于同一行?
你通過肉眼無法判定,得計算。
這就需要你用代碼編寫算法處理。如果你數學不好,那可能還真的是一個不小的挑戰。從圖上看,你的眼睛可能幾毫秒就識别出來了,但是計算機沒有眼睛,隻有大腦。它就等着你告訴它要怎麼去算什麼數據。
其實也好處理(話都讓你說了,難也是你說的),看兩個字在Y軸的重疊情況。如果重疊達到一定占比,那就可以認為這兩組數據是處于同一行。
其實字符與字符之間的關系還有很多情況。
根據情況的不同,我們就可以做不同的判定。
上圖所示,如果文本1的矩形區域和公式1的矩形區域,在橫向上有一定比例的重疊,那我們可以認為,它們是處于同一行。如果文本2的區域完全包含(重疊率100%)于表格1的區域中,那麼我們可以認為文本2屬于表格1。同樣,文本2和文本3在縱向的重疊率,可以作為它倆是否位于同一列的一個指标。
2.4.2 文本校正OCR識别的最終目的,是要獲得一份準确的、結構化的文本内容。
單個字符識别,其實是各自為戰,前後不商量。
就比如,遇到一個圓圈形狀的字符圖片。OCR識别就犯了難,它是數字“0”?漢字“〇”?大寫字母“O”?小寫字母“o”?中文句号“。”?還是“Q”忘了加尾巴……。
啥都對,啥都不對。
所以,需要矯正……校正。這兩個詞,都是高頻詞,尤其拼音打字jiaozheng,容易出錯。其實,也好分辨。看語境,如果我前後提到了“文稿”,那麼是“校正”的可能性就大。如果我剛剛說了“牙齒”、“視力”、“角度”啥的,那麼基本上就應該是“矯正”了。
OCR識别的最後一步校正也是一樣。如果無法确定是數字“0”還是字母“o”,可以觀察它相鄰的幾個字符,下面一圖勝千言。
單個字符識别不對沒關系,後期智能校正可以結合語境來幫你糾正。這個步驟就叫做後處理。
我想,OCR流程介紹的差不多了。下面該總結了。
三、總結其實,我已經迫不及待地想睡覺了。但是,睡覺前,我還是想輸出幾個觀點。
3.1 OCR的投入:自己開發 vs 調用第三方?需要企業領導視自身業務需求和研發能力來确定。
通過上面的流程講解,其實我們也了解到,做OCR并不難,這在業界已經非常成熟了。如果,你的業務需求很單一,另外也有一兩個喜歡研究技術的程序員(三年經驗起),其實可以投入幾個人、幾個月搞一搞試試看效果。就算不成功,起碼他們再跟第三方對接起來,也屬于專業級别了。
那麼,如果你的業務需求複雜多樣,是不是就要用第三方服務了。也不一定,需求太複雜,通用的第三方平台,不一定能滿足你的個性化需求。我之前遇到過一個例子,也是在教育行業。他們有一個場景是用在填空題手寫答案上。一般的手寫識别,你就算寫的80%正确,它會給你智能糾正,輸出字符。但是,教育行業不行,寫錯了就是寫錯了,不要糾正。比如,武術的“武”,學生如果右下角寫成了“戈”那樣多了一撇,不要輸出“武”,要輸出不是字,并記錄下學生的錯字圖片。這一下,沒有一家平台可以對接。其實,自己研發是可以做到的。但是,研發這玩意有什麼用?隻有自己用。
如果業務比較通用,且第三方費用不是很高的情況下,可以考慮購買服務。其實,不管是個人生活還是企業運轉,總歸都是要考慮成本的控制。最終都是資金限制了一切。所以,我說多少都是白扯。那種說,我有錢,但是找不到人才的老闆,請聯系我。
3.2 OCR的重點在哪裡?我認為是數據。
現今而言,瓶頸已經不是技術了,數據量決定識别率。短期内,技術沒有太多可提高的空間了。剩餘的就是拼數據量。
很多人覺得人工智能不智能,甚至智障。其實,有一部分原因就是訓練數據太少。就拿智能問答來說,很多人問的問題,人工智能回答不好。原因就是,你問的這些問題它從來沒有接觸過。
就像我和孩子去公園的例子,我一直給她看狗的圖像,突然問她麒麟是什麼,她會從狗的答案裡去找類似的應對。
我還是拿教育行業舉例(我熟啊),如果我們拿一本魯教版七年級地理上冊,交給人工智能學習。如果它學完了,你問它書本上的知識,它絕對是回答準确。但是,你如果問它七年級下冊的,它估計就蒙了。更何況,還有八年級、九年級呢?更何況學科還有物理、化學、生物呢?更何況,我們生活化的對話場景,不會出現在課本裡呢!想讓它聰明,得多少數據,誰又有這些數據?!
OCR也是一樣。識别那一塊兒,大人寫的字和小孩寫的字,是有差别的,想要識别準确,肯定是樣本越多越準确。後處理校正那一塊兒,無他,隻能是見多了才能識廣。
3.3 非得湊夠三條嗎?有人說,你講總結,最好不要超過三條,多了記不住。
但是,如果不夠3條呢?也不用湊。
本文寫了不少。是否對大家有幫助,現在還不好說。這得看大家的反饋了。
我曾經寫過一個Android開發的專欄。
但是,大家對于Android開發其實并不看好,閱讀量少,而且大家也嘲諷現在居然還有人學Android。那我寫這個專欄,其實幫不到很多人。也就是,沒有需求。那我完全可以投入同等精力,去寫另一個受衆更廣的專欄。
對于OCR相關的題材,我有知識儲備,包括github也開源了上面的自動批改項目。至于大家是否有需求,這個是無法預測的。我也會根據文章的閱讀和互動情況,調整後續的内容輸出。
是再出一篇專業版文章,還是出一系列專題,或者是不再更新。也希望大家給我一些反饋。
本文作者頭條—ITF男孩 @ITF男孩,禁止以二次發布的形式轉載,侵權必究。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!