Python徒手實(shí)現(xiàn)識(shí)別手寫數(shù)字—簡易圖片數(shù)據(jù)庫

Python徒手實(shí)現(xiàn)識(shí)別手寫數(shù)字—簡易圖片數(shù)據(jù)庫

寫在前面

上一篇文章Python徒手實(shí)現(xiàn)識(shí)別手寫數(shù)字—圖像的處理中我們講了圖片的處理海蔽,將圖片經(jīng)過剪裁尸变,拉伸等操作以后將每一個(gè)圖片變成了1x10000大小的向量怯伊。但是如果只是這樣的話设易,我們每一次運(yùn)行的時(shí)候都需要將他們計(jì)算一遍乱凿,當(dāng)圖片特別多的時(shí)候會(huì)消耗大量的時(shí)間莫矗。

所以我們需要將這些向量存入一個(gè)文件當(dāng)中,每次先看看圖庫中有沒有新增的圖片柄驻,如果有新增的圖片狐树,那么就將新增的圖片變成1x10000向量再存入文件之中,然后從文件中讀取全部圖片向量即可鸿脓。當(dāng)圖庫中沒有新增圖片的時(shí)候抑钟,那么就直接調(diào)用文件中的圖片向量進(jìn)行計(jì)算就好。這樣子算是節(jié)省了大量的時(shí)間野哭。

所以本文就是從零開始建立一個(gè)這樣的圖片存儲(chǔ)管理系統(tǒng)在塔。

實(shí)現(xiàn)邏輯

第一次讀入圖片

我們的圖庫中擁有一大堆圖片,每一張圖片上面都是一個(gè)手寫的數(shù)字拨黔,圖片的名稱為[數(shù)字內(nèi)容]_[序號(hào)]蛔溃。比如說一個(gè)圖片的名稱為2_3,代表這一張圖片里面的數(shù)字是2篱蝇,并且是“數(shù)字是2的第3張圖片”贺待。

存在一個(gè)csv文件作為我們的建議的圖片數(shù)據(jù)庫,名稱為Data.csv零截。

首先我們讀取圖庫中所有圖片的名稱麸塞,保存在fileNames中。然后讀取Data.csv中所有數(shù)據(jù)涧衙。

提取出Data.csv的最后一列(一共10002列哪工,第10001列說明該數(shù)字是什么數(shù)字奥此,第10002列是圖片的名稱),也就是數(shù)據(jù)庫中存儲(chǔ)的所有圖片的名稱雁比,存儲(chǔ)在item中稚虎。

將新加入圖庫的圖片名稱保存在newFileNames中。如果Data.csv為空偎捎,那么就直接令newFileNames = fileNames祥绞。也就是說如果數(shù)據(jù)庫中什么也沒有,那么圖庫中所有圖片都是新加入的鸭限。

如果Data.csv不為空蜕径,那么就將item里面的內(nèi)容與fileNames的內(nèi)容比較,如果出現(xiàn)了fileNames里面有的名稱item中沒有败京,那么就將這些名稱放進(jìn)newFileNames中兜喻。如果item里有的名稱fileNames中沒有,那就不管赡麦。

也就是說朴皆,我令我們的數(shù)據(jù)庫只進(jìn)不出。

現(xiàn)在我們得到了新加入圖庫的圖片的名稱newFileNames泛粹。

將newFileNames中的名稱的圖片帶入上一文中函數(shù)GetTrainPicture進(jìn)行處理遂铡,得到了一個(gè)nx10001的矩陣,每一行代表一個(gè)新加入的圖片晶姊,前10000列是圖片向量扒接,第10001列是該圖片的數(shù)字,保存在pic中们衙。

將這些圖片壓入到數(shù)據(jù)庫的后面钾怔。

讀取之前數(shù)據(jù)庫原有的圖片向量,并與pic合并蒙挑,得到目前擁有的所有的訓(xùn)練圖片向量pic宗侦。

image.png

以上就是本章寫的所有內(nèi)容,下面放出代碼來詳細(xì)解釋一下忆蚀。

代碼解析

主文件

import os
import numpy as np
import OperatePicture as OP
import OperateDataBase as OD
import csv

##Essential vavriable 基礎(chǔ)變量
#Standard size 標(biāo)準(zhǔn)大小
N = 100
#Gray threshold 灰度閾值
color = 100/255

#讀取原CSV文件
reader = list(csv.reader(open('DataBase.csv', encoding = 'utf-8')))
#清除讀取后的第一個(gè)空行
del reader[0]
#讀取num目錄下的所有文件名
fileNames = os.listdir(r"./num/")
#對比fileNames與reader矾利,得到新增的圖片newFileNames
newFileNames = OD.NewFiles(fileNames, reader)
print('New pictures are: 'newFileNames)
#得到newFilesNames對應(yīng)的矩陣
pic = OP.GetTrainPicture(newFileNames)
#將新增圖片矩陣存入CSV中
OD.SaveToCSV(pic, newFileNames)
#將原數(shù)據(jù)庫矩陣與新數(shù)據(jù)庫矩陣合并
pic = OD.Combination(reader, pic)

我將兩節(jié)內(nèi)容分別封裝在兩個(gè)py文件里面,上一篇文章中的圖片的切割與處理等所有內(nèi)容我放在文件OperatePicture里面了馋袜,這一節(jié)的數(shù)據(jù)庫處理放在了文件OperateDatabase里面男旗。

因?yàn)檎麄€(gè)代碼的邏輯我在上面已經(jīng)捋過一遍了,所以我不再解釋其中的內(nèi)容桃焕,接下來針對每個(gè)函數(shù)開始講解剑肯。

OperateDatabase代碼

從上面的主文件中捧毛,我們首先用到了函數(shù)NewFiles观堂,主要是對比fileNames和reader這兩個(gè)文件中圖片的名稱有什么不同让网,返回值是新增的圖片的名稱的列表。下面是代碼

def NewFiles(fileNames, reader):
    '''判斷是否有不同于數(shù)據(jù)庫中的新文件加入'''
    #如果數(shù)據(jù)庫中沒有數(shù)據(jù)师痕,則返回filenames
    if len(reader) == 0:
        return fileNames
    else:
        #從數(shù)據(jù)庫中提取所有名稱
        files = [item[10001] for item in reader]
        #需要加入的圖片名稱
        newFileNames = []
        for item in fileNames:
            #判斷當(dāng)前名稱是否存在數(shù)據(jù)庫中
            #如果不存在溃睹,則加入newFileNames
            if item not in files:
                newFileNames.append(item)
        return newFileNames

首先判斷reader是否有內(nèi)容,如果沒有內(nèi)容胰坟,說明是第一次執(zhí)行因篇,那么會(huì)直接把fileNames返回。否則才會(huì)進(jìn)入下面進(jìn)行比較笔横。

返回了newFileNames之后竞滓,就會(huì)把這個(gè)列表中的所有名稱的圖片通過GetTrainPicture函數(shù)得到一個(gè)1x10001大小的矩陣,具體過程請看我上一篇文章講的內(nèi)容吹缔。

之后為了把新的數(shù)據(jù)存入CSV文件中商佑,我們利用函數(shù)SaveToCSV將pic存入文件中,具體代碼如下厢塘。

def SaveToCSV(pic, fileNames):
    '''將pic與對應(yīng)的dileNames存入CSV文件'''
    writer = csv.writer(open('Database.csv', 'a', newline = ''), dialect = 'excel')
    #將fileNames變?yōu)榱斜?    f = [item for item in fileNames]
    #每一行依次寫入文件中
    for i in range(len(pic)):
        #將改行圖片向量轉(zhuǎn)為list
        item = pic[i].tolist()
        #將這個(gè)圖片向量對應(yīng)的名稱f放入列表最后一個(gè)
        item.append(f[i])
        writer.writerow(item)

當(dāng)函數(shù)運(yùn)行過后茶没,會(huì)把pic矩陣對應(yīng)的內(nèi)容直接給續(xù)寫入CSV文件中,相當(dāng)于數(shù)據(jù)庫操縱的寫入晚碾,并不會(huì)覆蓋之前原有的數(shù)據(jù)抓半。

之后我們需要將數(shù)據(jù)庫原有的一大堆數(shù)據(jù)reader和新加進(jìn)來的數(shù)據(jù)pic合并到pic里面,所以利用Combination函數(shù)將兩個(gè)矩陣合并格嘁,代碼如下

def Combination(reader, pic):
    '''將兩個(gè)矩陣reader與pic合并'''
    #兩個(gè)矩陣的總行數(shù)
    l = len(reader) + len(pic)
    #初始化新的矩陣
    newPic = np.zeros(l*10001).reshape(l, 10001)
    #將reader最后的那個(gè)字符串名稱去掉
    for item in reader:
        item.pop()
    #將reader轉(zhuǎn)化為numpy的矩陣形式
    reader = np.array(reader)
    #新矩陣前半部分放reader笛求,后半部分放pic
    if len(reader) != 0:
        newPic[0:len(reader), :] = reader
    newPic[len(reader):len(pic), :] = pic
    return newPic

因?yàn)閞eader最后一行還包括了一個(gè)圖片的名稱,所以先利用pop將其去掉糕簿,之后轉(zhuǎn)化為矩陣形式涣易,然后再直接放入矩陣中。這個(gè)矩陣操作可能沒有見過冶伞,下面我詳細(xì)解釋一下新症。

假如我現(xiàn)在有一個(gè)2x3的矩陣和一個(gè)2x2的矩陣

m = [[1 2 3]
     [4 5 6]]
n = [[7 8]
     [9 1]]

我可以進(jìn)行如下操作

#操作一
m[:, 0:2] = n
print(m)
#操作二
m[:, 1:3] = n
print(m)

#以下為輸出結(jié)果
#操作一
[[7 8 3]
 [9 1 6]]
#操作二
[[7 7 8]
 [9 9 1]]

可以看出操作一直接把m的第一二列給替換成n,操作二把m的第二三列替換成了n响禽。具體過程可以百度查一下numpy的矩陣的操作徒爹,也可以自己總結(jié)規(guī)律,不細(xì)講了芋类。

以上就是這一篇的全部代碼隆嗅。

小結(jié)

這一篇我相當(dāng)于用CSV文件制作了一個(gè)非常簡陋的數(shù)據(jù)庫,能夠執(zhí)行的操作只有識(shí)別已有內(nèi)容NewFiles與添加內(nèi)容SaveToCSV侯繁,并沒有插入胖喳、刪改等操作。主要是我覺得這兩個(gè)函數(shù)目前已經(jīng)夠用贮竟,因此只寫了這兩個(gè)操作丽焊,所以再需求已經(jīng)被滿足的情況下就不再拓展了较剃。

所有的源代碼已經(jīng)上傳到了我的GitHub上,可以前去下載技健,謝謝閱讀写穴。

如果喜歡的話麻煩點(diǎn)一個(gè)喜歡哦,加關(guān)注可以得到超厲害的更新提醒雌贱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啊送,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子欣孤,更是在濱河造成了極大的恐慌馋没,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件降传,死亡現(xiàn)場離奇詭異披泪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搬瑰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門款票,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泽论,你說我怎么就攤上這事艾少。” “怎么了翼悴?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵缚够,是天一觀的道長。 經(jīng)常有香客問我鹦赎,道長谍椅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任古话,我火速辦了婚禮雏吭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘陪踩。我一直安慰自己杖们,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布肩狂。 她就那樣靜靜地躺著摘完,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傻谁。 梳的紋絲不亂的頭發(fā)上孝治,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼谈飒。 笑死岂座,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的步绸。 我是一名探鬼主播掺逼,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼吃媒,長吁一口氣:“原來是場噩夢啊……” “哼瓤介!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赘那,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤刑桑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后募舟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祠斧,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年拱礁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琢锋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呢灶,死狀恐怖吴超,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸯乃,我是刑警寧澤鲸阻,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站缨睡,受9級特大地震影響鸟悴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奖年,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一细诸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陋守,春花似錦揍堰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至之碗,卻和暖如春蝙眶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工幽纷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留式塌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓友浸,卻偏偏與公主長得像峰尝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子收恢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容