国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

python實(shí)現(xiàn)識(shí)別手寫數(shù)字 python圖像識(shí)別算法

2020-01-04 16:02:48
字體:
供稿:網(wǎng)友

寫在前面

這一段的內(nèi)容可以說是最難的一部分之一了,因?yàn)槭?a href="/pc/xitong/win7/66099.html">識(shí)別圖像,所以涉及到的算法會(huì)相比之前的來說比較困難,所以我盡量會(huì)講得清楚一點(diǎn)。

而且因?yàn)樵诰帉懙倪^程中,把前面的一些邏輯也修改了一些,將其變得更完善了,所以一切以本篇的為準(zhǔn)。當(dāng)然,如果想要直接看代碼,代碼全部放在我的GitHub中,所以這篇文章主要負(fù)責(zé)講解,如需代碼請(qǐng)自行前往GitHub。

本次大綱

上一次寫到了數(shù)據(jù)庫的建立,我們能夠?qū)崟r(shí)的將更新的訓(xùn)練圖片存入CSV文件中。所以這次繼續(xù)往下走,該輪到識(shí)別圖片的內(nèi)容了。

首先我們需要從文件夾中提取出需要被識(shí)別的圖片test.png,并且把它經(jīng)過與訓(xùn)練圖片相同的處理得到1x10000大小的向量。因?yàn)閮烧咧g存在微小的差異,我也不是很想再往源代碼之中增加邏輯了,所以我就直接把增加待識(shí)別圖片的函數(shù)重新寫一個(gè)命名為GetTestPicture,內(nèi)容與GetTrainPicture類似,只不過少了“增加圖片名稱”這一個(gè)部分。

之后我們就可以開始進(jìn)行正式圖片識(shí)別內(nèi)容了。

主要是計(jì)算待識(shí)別圖片與所有訓(xùn)練圖片的距離。當(dāng)兩個(gè)圖片距離越近的時(shí)候,說明他們?cè)较嗨疲敲此麄兒苡锌赡軐懙木褪峭粋€(gè)數(shù)。所以利用這個(gè)原理,我們可以找出距離待識(shí)別圖像最近的幾個(gè)訓(xùn)練圖片,并輸出他們的數(shù)字分別是幾。比如說我想輸出前三個(gè),前三個(gè)分別是3,3,9,那就說明這個(gè)待識(shí)別圖片很有可能是3.

之后還可以對(duì)每一個(gè)位置加個(gè)權(quán)重,具體的就放在下一次再講,本節(jié)內(nèi)容已經(jīng)夠多了。

(第一篇文章之中我說過利用圖片洞數(shù)檢測(cè)。我嘗試了一下,認(rèn)為有些不妥,具體原因放在本文末。)

MAIN代碼

所以直接把主要代碼放上來,邏輯相對(duì)來說還是比較清晰的

import osimport OperatePicture as OPimport OperateDatabase as ODimport PictureAlgorithm as PAimport csv##Essential vavriable 基礎(chǔ)變量#Standard size 標(biāo)準(zhǔn)大小N = 100#Gray threshold 灰度閾值color = 200/255n = 10#讀取原CSV文件reader = list(csv.reader(open('Database.csv', encoding = 'utf-8')))#清除讀取后的第一個(gè)空行del reader[0]#讀取num目錄下的所有文件名fileNames = os.listdir(r"./num/")#對(duì)比fileNames與reader,得到新增的圖片newFileNamesnewFileNames = OD.NewFiles(fileNames, reader)print('New pictures are: ', newFileNames)#得到newFilesNames對(duì)應(yīng)的矩陣pic = OP.GetTrainPicture(newFileNames)#將新增圖片矩陣存入CSV中OD.SaveToCSV(pic, newFileNames)#將原數(shù)據(jù)庫矩陣與新數(shù)據(jù)庫矩陣合并pic = OD.Combination(reader, pic)#得到待識(shí)別圖片testFiles = os.listdir(r"./test/")testPic = OP.GetTestPicture(testFiles)#計(jì)算每一個(gè)待識(shí)別圖片的可能分類result = PA.CalculateResult(testPic, pic)for item in result:  for i in range(n):    print('第'+str(i+1)+'個(gè)向量為'+str(item[i+n])+',距離為'+str(item[i]))

相比上一篇文章的內(nèi)容,本篇文章里只增加了下面的的一段代碼,即得到待識(shí)別圖片名稱、得到待識(shí)別圖片向量、計(jì)算分類。

下面我們將著重講解CalculateResult函數(shù)的內(nèi)容,即識(shí)別圖片的算法。

算法內(nèi)容

算法大致講解

我們?cè)诖缶V之中已經(jīng)簡單介紹過了,所以我就直接把復(fù)制過來,并且再添加一些內(nèi)容。

假設(shè)我們?cè)诙S平面上有兩個(gè)點(diǎn)A=(1,1)和B=(5,5),我現(xiàn)在再放一個(gè)點(diǎn)C=(2,2),那么請(qǐng)問,C點(diǎn)離哪一個(gè)更近?

學(xué)過初中數(shù)學(xué)的都會(huì)知道肯定是離A點(diǎn)更近。所以我們換一種說法,我們現(xiàn)在有兩個(gè)類A和B,A類中包括了點(diǎn)(1,1),B類中包括了點(diǎn)(5,5),所以對(duì)于點(diǎn)(2,2),它可能屬于哪一類?

因?yàn)檫@個(gè)點(diǎn)離A類的點(diǎn)更近一點(diǎn),所以它可能屬于A類。這就是結(jié)論。那么對(duì)于3維空間,A類是點(diǎn)(1,1,1)和B類是(5,5,5),那么對(duì)于點(diǎn)(2,2,2)肯定也是屬于A類。

可以看出,我們這里是將兩個(gè)點(diǎn)的距離來作為判斷屬于哪一類的標(biāo)準(zhǔn)。那么對(duì)于我們將圖片拉成的1xn維向量,他實(shí)際上投影到n維空間上就是一個(gè)點(diǎn),所以我們將訓(xùn)練向量分成10類,分別代表十個(gè)數(shù)字,那么被識(shí)別數(shù)字靠近哪一個(gè)類,那說明它有可能屬于這一個(gè)類。

那么我們這里可以假設(shè)對(duì)于被識(shí)別向量,列出距離他最近的前十個(gè)向量分別屬于哪一類別,然后根據(jù)名次加上一個(gè)權(quán)重,并計(jì)算出一個(gè)值。該值代表了可能是屬于哪一個(gè)類,因此這就是我們得出的最終的一個(gè)結(jié)果——被識(shí)別python/288944.html">手寫數(shù)字圖片的值。

以上是第一篇文章中的內(nèi)容,下面我著重講一下數(shù)學(xué)方面的內(nèi)容。

考慮到某些地方不能夠輸入數(shù)學(xué)公式(或不方便輸入),我還是把這一段內(nèi)容貼成圖片出來。

python,識(shí)別,手寫數(shù)字,圖像識(shí)別算法,python圖像識(shí)別

之后直接挑出前幾個(gè)離被識(shí)別圖片最近的向量數(shù)字,基本上這幾個(gè)數(shù)字就是被識(shí)別圖片的數(shù)字了。但這樣做未免有些簡單,所以下一篇文章我會(huì)再深入一下,這張先講計(jì)算距離的內(nèi)容。

主代碼

下面的代碼中文件夾test用來存放待識(shí)別圖片,并通過函數(shù)GetTestPicture來得到圖片向量,之后和訓(xùn)練圖片pic一起放進(jìn)計(jì)算距離的函數(shù)CalculateResult中計(jì)算每一個(gè)待識(shí)別向量和其他所有圖片向量的距離。

#得到待識(shí)別圖片testFiles = os.listdir(r"./test/")testPic = OP.GetTestPicture(testFiles)#計(jì)算每一個(gè)待識(shí)別圖片的可能分類result = PA.CalculateResult(testPic, pic)for item in result:  for i in range(n):    print('第'+str(i+1)+'個(gè)向量為'+str(item[i+n])+',距離為'+str(item[i]))

函數(shù)CalculateResult在文件PictureAlgorithm.py中,這個(gè)文件里面包含了兩個(gè)函數(shù)為CalculateDistance函數(shù)和CalculateResult函數(shù),代表識(shí)別圖片所用到的算法。

函數(shù)CalculateResult

這個(gè)函數(shù)的邏輯比較簡單,也沒什么好說的,主要的聯(lián)系就是這個(gè)計(jì)算距離的CalculateDistance函數(shù)。

def CalculateResult(test, train):  '''計(jì)算待識(shí)別圖片test的可能分類'''  #得到每個(gè)圖片的前n相似圖片  testDis = CalculateDistance(test[:,0:N**2], train[:,0:N**2], train[:,N**2], n)  #將testDis變成列表  tt = testDis.tolist()  #輸出每一個(gè)待識(shí)別圖片的所有前n個(gè)  for i in tt:    for j in i:      print(j)

函數(shù)CalculateDistance

函數(shù)中我導(dǎo)入了四個(gè)參數(shù):被識(shí)別向量test,訓(xùn)練向量train,與訓(xùn)練向量對(duì)應(yīng)的每個(gè)向量對(duì)應(yīng)代表的數(shù)字num,想要導(dǎo)出的前n個(gè)距離最近的向量。

def CalculateDistance(test, train, num, n):  '''計(jì)算每個(gè)圖片前n相似圖片'''  #前n個(gè)放距離,后n個(gè)放數(shù)字  dis = np.zeros(2*n*len(test)).reshape(len(test), 2*n)  for i, item in enumerate(test):    #計(jì)算出每個(gè)訓(xùn)練圖片與該待識(shí)別圖片的距離    itemDis = np.sqrt(np.sum((item-train)**2, axis=1))    #對(duì)距離進(jìn)行排序,找出前n個(gè)    sortDis = np.sort(itemDis)    dis[i, 0:n] = sortDis[0:n]    for j in range(n):      #找到前幾個(gè)在原矩陣中的位置      maxPoint = list(itemDis).index(sortDis[j])      #找到num對(duì)應(yīng)位置的數(shù)字,存入dis中      dis[i, j+n] = num[maxPoint]  return dis

首先建立一個(gè)行數(shù)為test內(nèi)被識(shí)別向量數(shù)量,列數(shù)為2*n的矩陣,每一行前n個(gè)放距離,后n個(gè)放數(shù)字。之后針對(duì)每一個(gè)被識(shí)別向量進(jìn)行循環(huán)。

首先直接計(jì)算每個(gè)訓(xùn)練圖片與該識(shí)別圖片的距離,直接可以用一行代碼表示

itemDis = np.sqrt(np.sum((item-train)**2, axis=1))

這一行代碼就是上文中的算法過程,我個(gè)人覺得還是比較復(fù)雜的,可以詳細(xì)的拆開看一下,我這里不細(xì)講了。下面的內(nèi)容就是開始排序并且找到距離最近的前幾個(gè)向量。

這里的邏輯是:先排序,找到距離最小的前n個(gè),存入矩陣。找到前n個(gè)在原矩陣中的位置,并找到對(duì)應(yīng)位置上num的數(shù)字,存入dis的后n個(gè)。

這樣子就相當(dāng)于完成了所有內(nèi)容,返回dis即可。

實(shí)際測(cè)試

我自己動(dòng)手寫了一些數(shù)字,如圖所示。所以實(shí)際上我們的數(shù)據(jù)庫還是比較小的。

python,識(shí)別,手寫數(shù)字,圖像識(shí)別算法,python圖像識(shí)別

所以我又寫了一個(gè)數(shù)字作為待識(shí)別圖像,通過程序運(yùn)行以后,我們的以直接輸出前十個(gè)最相似的向量:

第1個(gè)向量為2.0,距離為33.62347223932534
第2個(gè)向量為2.0,距離為35.64182105224185
第3個(gè)向量為2.0,距離為38.69663119274146
第4個(gè)向量為2.0,距離為43.52904133387693
第5個(gè)向量為2.0,距離為43.69029199677604
第6個(gè)向量為1.0,距離為43.730883339256714
第7個(gè)向量為6.0,距離為44.94800943845918
第8個(gè)向量為2.0,距離為45.033283944455924
第9個(gè)向量為4.0,距離為45.43926712996951
第10個(gè)向量為7.0,距離為45.64893989116544

之后我又依次從1-9試了一遍,我自己手寫的數(shù)字全部識(shí)別正確,可以看出準(zhǔn)確率還是挺高的。所以做到這一步相當(dāng)于已經(jīng)完成度很高了。

所以我就試了一下從網(wǎng)上找的圖片,發(fā)現(xiàn)幾乎沒有正確的了。說明我們的數(shù)據(jù)庫還是太小,只認(rèn)得我的字體。不過話說這樣,也可以做一個(gè)字體識(shí)別的程序。

所以如果要提高準(zhǔn)確率,那么擴(kuò)大圖庫是必須的。這一次就到這里。

總結(jié)

所有源代碼我都放在了我的GitHub中,如果有興趣的話可以去看看。

到這里就相當(dāng)于算法內(nèi)容寫完了,比較簡單,只用了一個(gè)類似于K最近鄰的算法。

下一篇文章將會(huì)講一個(gè)給前n個(gè)排名加權(quán)的想法,這樣來提高準(zhǔn)確度。

所以這一次就先到這里為止,謝謝。

如果喜歡的話,麻煩點(diǎn)一個(gè)喜歡和關(guān)注一下噢,謝謝~

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到python教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 略阳县| 桦甸市| 襄汾县| 西平县| 临江市| 怀来县| 广西| 于都县| 大同县| 剑川县| 山东省| 吴堡县| 连平县| 嘉峪关市| 金湖县| 南昌县| 玉环县| 凌海市| 阜城县| 方山县| 洛川县| 高要市| 西乌珠穆沁旗| 大邑县| 永福县| 章丘市| 湟源县| 海晏县| 忻州市| 周至县| 化德县| 新化县| 水城县| 泽普县| 英超| 乌鲁木齐市| 东明县| 大丰市| 华蓥市| 淮北市| 江安县|