拍照怎麼搜題?(下)

/*算法

 *上一篇,咱們講到了怎樣對圖像進行處理微信

 *接下來。咱們聊聊怎樣對圖像進行識別網絡

 *沒看過上一篇的同窗。請微信關注:simplemainpost


 */字體


====圖像的識別 ====編碼

 

咱們已經拿到一個個的字符的圖案了,現在要作的。就是怎樣把這些圖案轉化成計算機可認知的二進制編碼。因爲此次僅僅涉及到英文和標點,因此實際要作的。就是將圖案轉化爲asc碼。spa

 

識別的方法有許多。接下來我給你們介紹一下我用的幾種方法。爲了使得識別率提高。通常還會有其它更好或者更有效的方法,假設這裏沒講述到。請你們諒解~排序

 

對於每一個待識別的字符圖案。都有他本身的特徵(比方:i長的很是瘦,O長的很是圓,T橫豎都有等等),識別的時候,就可以藉助他們的特徵,從而抽絲剝繭的把他們認出來。it

 

問:那詳細怎麼作呢?數據挖掘

答:咱們將多種字體的所有英文和標點生成標準圖案,再將待識別的圖案和他們進行比對,看這些待匹配的圖案和哪一個標準圖案最像,那就能找出最有可能的asc碼。

 

那就開始吧!

 

步驟一:生成模板圖案

咱們用多種常見字體,將所有英文和標點生成標準圖案。這裏簡稱模板圖案。

爲何要多種字體呢?因爲對於同一個字符,在不一樣字體下,可能長的全然不同,比方相同是gal,不一樣字體效果例如如下:


拿到這些標準模板圖案之後。咱們就有了例如如下圖的這些位圖:


但是有了這些位圖還不夠,咱們還要作一些其它工做,來保證後面的匹配工做能正常進行。接下來咱們就看看還要作什麼工做。

 

步驟二:歸一化 +記錄meta信息

咱們將模板圖案先去掉上下左右空白的背景,讓前景圖案頂格。

接着再統一寬高,將圖案壓縮或拉伸爲p*q大小的圖案(比方都壓縮或者拉伸到50像素*50像素)。這樣咱們才幹很是比如對。

說白了,就是你們都用統一的標準,不然你穿XL號的衣服。我穿S號的。咱們的衣服就根本沒有可比性。

 

好了,有了統一的比對標準,是否是一切就都好了呢?

 

你們一看這樣的問題,基本就可以條件反射的斷定:回答是否認的(就跟讀書那會兒作推斷題同樣^_^)。那問題出在哪兒呢?

 

有些圖案作了歸一化之後。就失真了。比方逗號[,]和引號[’],去掉周圍的白邊。最後就都長成例如如下圖像了:


另外一些字符就會長的很是像了,比方大寫的Z和小寫的z。歸一化之後,就變成例如如下這樣了,人看都惱火。讓計算機怎麼來推斷,對吧。



因此,除了歸一化,咱們還要記錄圖案自己的信息,比方原始的長寬,原始的位圖等等,這些信息在匹配的時候,可以提供額外的信息,來幫助算法推斷有效性。

 

好了。作完上面兩步。咱們就獲得了標準圖案的歸一化位圖和meta信息。同一時候,咱們對上一篇文章中作完垂直分割的待匹配圖案也作歸一化和meta信息記錄的工做。有了這兩樣東西。咱們就可以開展如下的匹配工做了。

 

步驟三:模板圖案和待匹配圖案的匹配

接下來,就用咱們的匹配算法,對待匹配的圖案和標準圖案進行匹配了。

圖像的識別算法有很是多很是多,依據不一樣的應用場景,會有很是多不一樣的選擇,包含直接匹配的。也有經過數據挖掘來識別。每一種方法沒有絕對的好壞,僅僅有看是否更適合。

 

我之前看過一篇文章,是講驗證碼識別的。驗證碼爲了防止機器識別,會對字符進行旋轉、扭曲、干擾等處理。爲了識別這些變態的字符,那篇文章列舉了多達10幾種的識別算法。當時看得我不斷的驚歎:我擦……。假設之後有時間,我嘗試看看能不能把那篇文章找出來分享給你們。

 

咱們這裏因爲僅僅涉及到英文和標點,因此用了下面幾種方法:

1、字符像素匹配

2、投影區塊匹配

3、九宮格匹配

4、重心匹配

5、寬高比匹配

 

每一個匹配算法都有自身的優缺點(稍後會講到),所以他們都能得出一個誰跟誰最像。待匹配圖案是誰的可能性最大的推斷。

儘管這個推斷絕大多數狀況下是對的,但是也有bad case的狀況。

因此,咱們要綜合來看所有的推斷,將每一個算法的匹配值進行加權求和。得出最後的一個類似度的值。這個類似度有可能就是終於的一個結果。只是這個結果可能也是有錯誤的(bad case),因此假設繼續日後作的時候,咱們要不斷去給咱們的評價推斷系統以反饋。豐富咱們識別的樣本。同一時候對識別算法和加權參數進行修正(這個會比較花時間,我此次就沒作了^_^

 

經過上面的算法,咱們就將待匹配的圖案和每一個標準圖案進行算法比對的類似度值求出來。作個排序。取類似度最大的那個,基本就獲得咱們終於想要的那個。

 

後來出於好奇。我專門問了做業幫的朋友,想看看他們怎麼作的。

大致方法相似。同一時候他們還用了其它的一些手段,比方:卷積神經網絡(CNN)等。後面有時間了,我再專門去研究研究。

 

好了,大致上的步驟,老王是否是都講清楚了呢?接下來,就是詳細講講這幾個匹配算法,作完這幾個算法。咱們的識別工做就基本告一段落。來吧,跟着老王一塊兒往下看。

 

 

方法一:字符像素匹配

這是最直觀也最easy想到的方法。

咱們將待匹配圖案和標準的每一個圖案進行一個像素一個像素的比對,假設位圖都是0或者都是1,則計數加一,終於獲得計數數值k。用k除以像素個數w * h就獲得了一個類似值 d = k / (w * h)。假設d越大,則類似度越高(爲了描寫敘述起來easy些,後面我都用一些簡單的位圖來作示意):

 

模板圖案:


待匹配圖案:


咱們的模板圖案和待匹配圖案都被歸一化到10*10的尺寸。他們有99個點是重合的,有一個點不重合:(0,0)那個點。

這種話,他們的類似度就是d = 99 / 100 = 99%

 

理想狀況下,假設所有點都匹配的話,他們的就會有100點重合,那d = 100 / 100 = 100%。另一個極端,就是一個點都不重合,那麼d = 0 / 100 = 0%。對吧。

因此。咱們這個算法的值域就是[0,1]

對於99%的類似度,咱們以爲已經很是高了,因此他倆匹配的可能性就很是高。

 

如此這樣,咱們將待匹配的圖案和模板圖案一一計算,獲得d1 d2 ... dn這樣一個結果序列,降序排列的第一個,就是這個算法以爲最有可能的圖案。

 

這個算法直觀。實現簡單,只是這個算法有一個問題:就是待匹配圖案假設略微有一些誤差或者干擾,對算法自己的影響就會很大。

比方,咱們在圖像處理的時候,某一行裏多了一個干擾點。就有可能形成這一行的匹配度降低。例如如下圖:



咱們在圖像處理的時候,最後一行多了一個噪點。而後作圖像歸一化之後,整個圖像的最右邊就往左邊擠佔了一個像素。這樣和模板圖案進行算法對照的時候,匹配值就變成了90。整個匹配度就變成d = 90 / 100 = 90%

 

所以,這個算法對圖像精確度要求很是高,抗干擾能力弱。只是,在圖像處理比較好的絕大多數狀況下,他的匹配度仍是不錯的。

 

方法二:投影區塊匹配

上一種方法就是對圖像的信息太過敏感。略微一點干擾就會形成影響。因此,咱們有一個新的方法。將信息作匯聚。而後再比較信息的類似性。

 

咱們將圖像在x軸上作投影,累加位圖爲1的值。而後再將x軸等分紅n份(比方n=5)。分別將這等分的n份裏所有的值累加,獲得k1 k2 ... kn,而後將標準圖案和待匹配圖案的這nk值進行求差。差值越小,則類似度越高。同理,在y軸也作相同的投影和求差值。

 

咱們仍是對這個10 * 10的位圖進行分析,將這個位圖分別往xy軸上投影。將位圖中爲1的累加,所以獲得在x軸上的10個數字和y軸上的10個數字,例如如下:

 

模板圖案:


待匹配圖案1


待匹配圖案2


而後咱們把x軸和y軸上的數字。分別分紅連續的5組(每兩個一組),組內的數字累加:

模板圖案:

x軸:(8 8) (66) (6 6) (6 6) (8 8) -> 16 12 12 12 16

y軸:(10 10) (22) (10 10) (2 2) (10 10) -> 20 4 20 4 20

咱們將上面的值命名爲:

x0[1] x0[2] ... x0[5] = 16 12 12 12 16

y0[1] y0[2] ... y0[5] = 20 4 20 4 20

 

待匹配圖案1

x軸:(7 8) (66) (6 6) (6 6) (8 8) -> 15 12 12 12 16

y軸:(9 10) (22) (10 10) (2 2) (10 10) -> 19 4 20 4 20

咱們將上面的值命名爲:

x1[1] x1[2] ... x1[5] = 15 12 12 12 16

y1[1] y1[2] ... y1[5] = 19 4 20 4 20

 

待匹配圖案2

x軸:(7 8) (66) (6 6) (6 8) (8 1) -> 15 12 12 14 9

y軸:(8 9) (22) (9 9) (2 2) (9 10) -> 17 4 18 4 19

x2[1] x2[2] ... x2[5] = 15 12 12 14 9

y2[1] y2[2] ... y2[5] = 17 4 18 4 19

 

而後。咱們將相應的值作下面操做:

待匹配圖案1和標準圖案對照:

adx1 =Σ((x1[i] - x0[i]) / 20) ^ 2 = 0.0025

bdy1 =Σ((y1[i] - y0[i]) / 20) ^ 2 = 0.0025

cd1  = 1 - (dx1 + dy1) / 2 = 99.75%

(當中i=15, 20是每一組點的個數)

 

待匹配圖案2和標準圖案對照:

adx2 =Σ((x2[i] - x0[i]) / 20) ^ 2 = 0.1325

bdy2 =Σ((y2[i] - y0[i]) / 20) ^ 2 = 0.035

cd2  = 1 - (dx2 + dy2) / 2 = 91.6%

 

從絕對差值來看。這樣的方案要比前一種對於圖像的敏感度要小,特別是假設每組的個數不少其它的時候,這樣的敏感度就越弱。

 

這個算法主要是在作圖像有效信息分佈的比對,信息相對要粗放一些,抗干擾度要好一些。

只是但是帶來的問題,就是信息是統計信息。比較粗,有些圖案比對會不許確,比方:ao

 

方法三:九宮格匹配

咱們將圖案劃分紅3*3的格子,而後在每個格子裏統計位圖值爲1的個數,獲得k1 k2 ... k9一共9個值。而後再將標準圖案和待匹配圖案對k值求差。差值越小,則類似度越高。

這個算法相似上一種。不一樣的是。他將x軸和y軸的信息作了匯聚。鑑於計算方法相似,咱們這裏就再也不贅述。

 

方法四:重心匹配

還記得咱們以前說的一個case嗎?逗號[,]和引號[’]事實上除了位置不同之外。事實上長的很像。我最早作匹配的時候,匹配出來的結果就是要麼都是逗號,要麼都是引號。相似的還有橫線[-]和下劃線[_]等。

那咱們要作的,事實上就可以計算位圖中1值的重心在x方向和y方向的分佈。一比對就可以輕鬆的判別了。

比方逗號的重心在y軸上的分佈是更如下一些,而引號則是更上面一些。

 

詳細重心的計算方式有很是多,最簡單的就是:

x軸:將每個1點的x座標分別相加,而後除以1點的個數,再除以寬度作歸一化。

y軸:將每個1點的y座標分別相加,而後除以1點的個數。再除以高度作歸一化。

for (int x = 0; x < width; x++)

{

   for (int y = 0; y < height; y++)

    {

      if (data[x][y] == 1)

       {

           yValue += y;

           count++;

       }

    }

}

double avg = count > 0 ? yValue / count : 0;

avg = avg / height;

 

 

方法五:寬高比匹配

爲何要作這樣一個匹配呢?咱們先看一個case

 

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1

 

請問。這個10*10的圖案,是什麼字符?


這多是一個句號[.],也多是一個豎線[|]。還有多是某些字體的逗號[,]。因爲在作歸一化的時候,都變成了一個全是1的圖案。而逗號和句號的重心有可能還差點兒相同。這個時候,咱們就可以用原始信息中的寬高比來作比對。比方,句號[.]的寬高比接近1:1,豎線[|]的寬高比多是1:20,逗號[,]的寬高比多是1:2等等。

有了這個推斷。就可以將類似的這些圖案區分開來了。

 

經過以上幾種算法,咱們就會拿到每個算法計算出來的每個待識別圖案和標準圖案的類似值。

對於每個待識別圖案,咱們將每個算法的類似值作一個加權合併,就獲得了終於的類似度值,從而來肯定這個待識別的圖案和哪一個標準圖案最類似,找出最有可能的asc碼值。


好了,最後咱們再來看看文章開始的時候。給你們展現的效果:


最後識別出來之後,沒有作不論什麼的單詞校訂工做:

===================================

Three months after [he government stopped issulng (&%) or renewing permits for In[ernet cafes because of security (%#) concerns, some cafe owners are having flnanclal (ff%%) concerns of their own.

===================================

 

你們肉眼看。識別率仍是不錯的。只是有一些字符比方(Ili)(t[)等這些字符組內的圖案特別easy識別錯誤。爲了解決這些問題,可以增長單詞的校訂算法。

常用的LCS(最長公共子序列)或者BKTree等等。

因爲需要作全字典匹配,因此,BKTree的效率會更好一些。(這些基礎算法就臨時不在這裏細講。有興趣的同窗可以查閱baidu

 

有了糾錯算法,基本能很是好的將圖案識別出來。

 

 

====總結 ====

 

以上僅僅是一個主要的拍照識圖的算法。除了上述說的這些方法。事實上在實際應用中。還會對數據作反饋訓練。

比方有些字符會引起錯誤。咱們會將這些圖案反饋給系統,下次遇到相似的圖案的時候,系統就會匹配到更精準的信息。

同一時候,對於參數的調整。也可以引入反饋和修正。

 

而假設要增長中文的話。整個難度和複雜度還會提高很多,使用的方法可能都還有不同。鑑於此次調研的時間,老王同志就沒有再作深刻的研究了。

再等一段時間。老王可能會把這個作的更深刻仔細。此次就先到這裏吧~ ^o^

 

最後仍是老規矩,上美圖:


void next()
{
    你們可以關注老王的微信公衆號:simplemain

    老王近期寫的技術乾貨都在裏面,也可以提問題一塊兒探討~
    不肯意打字的盆友們,可以長按一下二維碼關注哈~


}

相關文章
相關標籤/搜索