版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第Python圖片存儲和訪問的三種方式詳解目錄前言數(shù)據(jù)準(zhǔn)備一個可以玩的數(shù)據(jù)集圖像存儲的設(shè)置LMDBHDF5單一圖像的存儲存儲到磁盤存儲到LMDB存儲HDF5存儲方式對比多個圖像的存儲多圖像調(diào)整代碼準(zhǔn)備數(shù)據(jù)集對比單一圖像的讀取從磁盤讀取從LMDB讀取從HDF5讀取讀取方式對比多個圖像的讀取多圖像調(diào)整代碼準(zhǔn)備數(shù)據(jù)集對比讀寫操作綜合比較數(shù)據(jù)對比并行操作
前言
ImageNet是一個著名的公共圖像數(shù)據(jù)庫,用于訓(xùn)練對象分類、檢測和分割等任務(wù)的模型,它包含超過1400萬張圖像。
在Python中處理圖像數(shù)據(jù)的時候,例如應(yīng)用卷積神經(jīng)網(wǎng)絡(luò)(也稱CNN)等算法可以處理大量圖像數(shù)據(jù)集,這里就需要學(xué)習(xí)如何用最簡單的方式存儲、讀取數(shù)據(jù)。
對于圖像數(shù)據(jù)處理應(yīng)該有有個定量的比較方式,讀取和寫入文件需要多長時間,以及將使用多少磁盤內(nèi)存。
分別用不同的方式去處理、解決圖像的存儲、性能優(yōu)化的問題。
數(shù)據(jù)準(zhǔn)備
一個可以玩的數(shù)據(jù)集
我們熟知的圖像數(shù)據(jù)集CIFAR-10,由60000個32x32像素的彩色圖像組成,這些圖像屬于不同的對象類別,例如狗、貓和飛機。相對而言CIFAR不是一個非常大的數(shù)據(jù)集,但如使用完整的TinyImages數(shù)據(jù)集,那么將需要大約400GB的可用磁盤空間。
文中的代碼應(yīng)用的數(shù)據(jù)集下載地址CIFAR-10數(shù)據(jù)集。
這份數(shù)據(jù)是使用cPickle進(jìn)行了序列化和批量保存。pickle模塊可以序列化任何Python對象,而無需進(jìn)行任何額外的代碼或轉(zhuǎn)換。但是有一個潛在的嚴(yán)重缺點,即在處理大量數(shù)據(jù)時會帶來安全風(fēng)險無法評估。
圖像加載到NumPy數(shù)組中
importnumpyasnp
importpickle
frompathlibimportPath
#文件路徑
data_dir=Path("data/cifar-10-batches-py/")
#解碼功能
defunpickle(file):
withopen(file,"rb")asfo:
dict=pickle.load(fo,encoding="bytes")
returndict
images,labels=[],[]
forbatchindata_dir.glob("data_batch_*"):
batch_data=unpickle(batch)
fori,flat_iminenumerate(batch_data[b"data"]):
im_channels=[]
#每個圖像都是扁平化的,通道按R,G,B的順序排列
forjinrange(3):
im_channels.append(
flat_im[j*1024:(j+1)*1024].reshape((32,32))
#重建原始圖像
images.append(np.dstack((im_channels)))
#保存標(biāo)簽
labels.append(batch_data[b"labels"][i])
print("加載CIFAR-10訓(xùn)練集:")
print(f"-np.shape(images){np.shape(images)}")
print(f"-np.shape(labels){np.shape(labels)}")
圖像存儲的設(shè)置
安裝三方庫Pillow用于圖像處理。
pipinstallPillow
LMDB
LMDB也稱為閃電數(shù)據(jù)庫,代表閃電內(nèi)存映射數(shù)據(jù)庫,因為速度快并且使用內(nèi)存映射文件。它是鍵值存儲,而不是關(guān)系數(shù)據(jù)庫。
安裝三方庫lmdb用于圖像處理。
pipinstalllmdb
HDF5
HDF5代表HierarchicalDataFormat,一種稱為HDF4或HDF5的文件格式。起源于美國國家超級計算應(yīng)用中心,是一種可移植、緊湊的科學(xué)數(shù)據(jù)格式。
安裝三方庫h5py用于圖像處理。
pipinstallh5py
單一圖像的存儲
3種不同的方式進(jìn)行數(shù)據(jù)讀取操作
frompathlibimportPath
disk_dir=Path("data/disk/")
lmdb_dir=Path("data/lmdb/")
hdf5_dir=Path("data/hdf5/")
同時加載的數(shù)據(jù)可以創(chuàng)建文件夾分開保存
disk_dir.mkdir(parents=True,exist_ok=True)
lmdb_dir.mkdir(parents=True,exist_ok=True)
hdf5_dir.mkdir(parents=True,exist_ok=True)
存儲到磁盤
使用Pillow完成輸入是一個單一的圖像image,在內(nèi)存中作為一個NumPy數(shù)組,并且使用唯一的圖像ID對其進(jìn)行命名image_id。
單個圖像保存到磁盤
fromPILimportImage
importcsv
defstore_single_disk(image,image_id,label):
"""將單個圖像作為.png文件存儲在磁盤上。
---------------
image圖像數(shù)組,(32,32,3)格式
image_id圖像的整數(shù)唯一ID
label圖像標(biāo)簽
Image.fromarray(image).save(disk_dir/f"{image_id}.png")
withopen(disk_dir/f"{image_id}.csv","wt")ascsvfile:
writer=csv.writer(
csvfile,delimiter="",quotechar="|",quoting=csv.QUOTE_MINIMAL
writer.writerow([label])
存儲到LMDB
LMDB是一個鍵值對存儲系統(tǒng),其中每個條目都保存為一個字節(jié)數(shù)組,鍵將是每個圖像的唯一標(biāo)識符,值將是圖像本身。
鍵和值都應(yīng)該是字符串。常見的用法是將值序列化為字符串,然后在讀回時將其反序列化。
用于重建的圖像尺寸,某些數(shù)據(jù)集可能包含不同大小的圖像會使用到這個方法。
classCIFAR_Image:
def__init__(self,image,label):
self.channels=image.shape[2]
self.size=image.shape[:2]
self.image=image.tobytes()
self.label=label
defget_image(self):
"""將圖像作為numpy數(shù)組返回"""
image=np.frombuffer(self.image,dtype=np.uint8)
returnimage.reshape(*self.size,self.channels)
單個圖像保存到LMDB
importlmdb
importpickle
defstore_single_lmdb(image,image_id,label):
"""將單個圖像存儲到LMDB
---------------
image圖像數(shù)組,(32,32,3)格式
image_id圖像的整數(shù)唯一ID
label圖像標(biāo)簽
map_size=image.nbytes*10
#CreateanewLMDBenvironment
env=lmdb.open(str(lmdb_dir/f"single_lmdb"),map_size=map_size)
#Startanewwritetransaction
withenv.begin(write=True)astxn:
#Allkey-valuepairsneedtobestrings
value=CIFAR_Image(image,label)
key=f"{image_id:08}"
txn.put(key.encode("ascii"),pickle.dumps(value))
env.close()
存儲HDF5
一個HDF5文件可以包含多個數(shù)據(jù)集??梢詣?chuàng)建兩個數(shù)據(jù)集,一個用于圖像,一個用于元數(shù)據(jù)。
importh5py
defstore_single_hdf5(image,image_id,label):
"""將單個圖像存儲到HDF5文件
---------------
image圖像數(shù)組,(32,32,3)格式
image_id圖像的整數(shù)唯一ID
label圖像標(biāo)簽
#創(chuàng)建一個新的HDF5文件
file=h5py.File(hdf5_dir/f"{image_id}.h5","w")
#在文件中創(chuàng)建數(shù)據(jù)集
dataset=file.create_dataset(
"image",np.shape(image),h5py.h5t.STD_U8BE,data=image
meta_set=file.create_dataset(
"meta",np.shape(label),h5py.h5t.STD_U8BE,data=label
file.close()
存儲方式對比
將保存單個圖像的所有三個函數(shù)放入字典中。
_store_single_funcs=dict(
disk=store_single_disk,
lmdb=store_single_lmdb,
hdf5=store_single_hdf5
以三種不同的方式存儲保存CIFAR中的第一張圖像及其對應(yīng)的標(biāo)簽。
fromtimeitimporttimeit
store_single_timings=dict()
formethodin("disk","lmdb","hdf5"):
t=timeit(
"_store_single_funcs[method](image,0,label)",
setup="image=images[0];label=labels[0]",
number=1,
globals=globals(),
store_single_timings[method]=t
print(f"存儲方法:{method},使用耗時:{t}")
來一個表格看看對比。
存儲方法存儲耗時使用內(nèi)存Disk2.1ms8KLMDB1.7ms32KHDF58.1ms8K
多個圖像的存儲
同單個圖像存儲方法類似,修改代碼進(jìn)行多個圖像數(shù)據(jù)的存儲。
多圖像調(diào)整代碼
將多個圖像保存為.png文件就可以理解為多次調(diào)用store_single_method()這樣。但這不適用于LMDB或HDF5,因為每個圖像都有不同的數(shù)據(jù)庫文件。
將一組圖像存儲到磁盤
store_many_disk(images,labels):
"""參數(shù):
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
num_images=len(images)
#一張一張保存所有圖片
fori,imageinenumerate(images):
Image.fromarray(image).save(disk_dir/f"{i}.png")
#將所有標(biāo)簽保存到csv文件
withopen(disk_dir/f"{num_images}.csv","w")ascsvfile:
writer=csv.writer(
csvfile,delimiter="",quotechar="|",quoting=csv.QUOTE_MINIMAL
forlabelinlabels:
writer.writerow([label])
將一組圖像存儲到LMDB
defstore_many_lmdb(images,labels):
"""參數(shù):
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
num_images=len(images)
map_size=num_images*images[0].nbytes*10
#為所有圖像創(chuàng)建一個新的LMDB數(shù)據(jù)庫
env=lmdb.open(str(lmdb_dir/f"{num_images}_lmdb"),map_size=map_size)
#在一個事務(wù)中寫入所有圖像
withenv.begin(write=True)astxn:
foriinrange(num_images):
#所有鍵值對都必須是字符串
value=CIFAR_Image(images[i],labels[i])
key=f"{i:08}"
txn.put(key.encode("ascii"),pickle.dumps(value))
env.close()
將一組圖像存儲到HDF5
defstore_many_hdf5(images,labels):
"""參數(shù):
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
num_images=len(images)
#創(chuàng)建一個新的HDF5文件
file=h5py.File(hdf5_dir/f"{num_images}_many.h5","w")
#在文件中創(chuàng)建數(shù)據(jù)集
dataset=file.create_dataset(
"images",np.shape(images),h5py.h5t.STD_U8BE,data=images
meta_set=file.create_dataset(
"meta",np.shape(labels),h5py.h5t.STD_U8BE,data=labels
file.close()
準(zhǔn)備數(shù)據(jù)集對比
使用100000個圖像進(jìn)行測試
cutoffs=[10,100,1000,10000,100000]
images=np.concatenate((images,images),axis=0)
labels=np.concatenate((labels,labels),axis=0)
#確保有100,000個圖像和標(biāo)簽
print(np.shape(images))
print(np.shape(labels))
創(chuàng)建一個計算方式進(jìn)行對比
_store_many_funcs=dict(
disk=store_many_disk,lmdb=store_many_lmdb,hdf5=store_many_hdf5
fromtimeitimporttimeit
store_many_timings={"disk":[],"lmdb":[],"hdf5":[]}
forcutoffincutoffs:
formethodin("disk","lmdb","hdf5"):
t=timeit(
"_store_many_funcs[method](images_,labels_)",
setup="images_=images[:cutoff];labels_=labels[:cutoff]",
number=1,
globals=globals(),
store_many_timings[method].append(t)
#打印出方法、截止時間和使用時間
print(f"Method:{method},Timeusage:{t}")
PLOT顯示具有多個數(shù)據(jù)集和匹配圖例的單個圖
importmatplotlib.pyplotasplt
defplot_with_legend(
x_range,y_data,legend_labels,x_label,y_label,title,log=False
"""參數(shù):
--------------
x_range包含x數(shù)據(jù)的列表
y_data包含y值的列表
legend_labels字符串圖例標(biāo)簽列表
x_labelx軸標(biāo)簽
y_labely軸標(biāo)簽
plt.style.use("seaborn-whitegrid")
plt.figure(figsize=(10,7))
iflen(y_data)!=len(legend_labels):
raiseTypeError(
"數(shù)據(jù)集的數(shù)量與標(biāo)簽的數(shù)量不匹配"
all_plots=[]
fordata,labelinzip(y_data,legend_labels):
iflog:
temp,=plt.loglog(x_range,data,label=label)
else:
temp,=plt.plot(x_range,data,label=label)
all_plots.append(temp)
plt.title(title)
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.legend(handles=all_plots)
plt.show()
#Gettingthestoretimingsdatatodisplay
disk_x=store_many_timings["disk"]
lmdb_x=store_many_timings["lmdb"]
hdf5_x=store_many_timings["hdf5"]
plot_with_legend(
cutoffs,
[disk_x,lmdb_x,hdf5_x],
["PNGfiles","LMDB","HDF5"],
"Numberofimages",
"Secondstostore",
"Storagetime",
log=False,
plot_with_legend(
cutoffs,
[disk_x,lmdb_x,hdf5_x],
["PNGfiles","LMDB","HDF5"],
"Numberofimages",
"Secondstostore",
"Logstoragetime",
log=True,
單一圖像的讀取
從磁盤讀取
defread_single_disk(image_id):
"""參數(shù):
---------------
image_id圖像的整數(shù)唯一ID
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
image=np.array(Image.open(disk_dir/f"{image_id}.png"))
withopen(disk_dir/f"{image_id}.csv","r")ascsvfile:
reader=csv.reader(
csvfile,delimiter="",quotechar="|",quoting=csv.QUOTE_MINIMAL
label=int(next(reader)[0])
returnimage,label
從LMDB讀取
defread_single_lmdb(image_id):
"""參數(shù):
---------------
image_id圖像的整數(shù)唯一ID
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
#打開LMDB環(huán)境
env=lmdb.open(str(lmdb_dir/f"single_lmdb"),readonly=True)
#開始一個新的事務(wù)
withenv.begin()astxn:
#進(jìn)行編碼
data=txn.get(f"{image_id:08}".encode("ascii"))
#加載的CIFAR_Image對象
cifar_image=pickle.loads(data)
#檢索相關(guān)位
image=cifar_image.get_image()
label=cifar_image.label
env.close()
returnimage,label
從HDF5讀取
defread_single_hdf5(image_id):
"""參數(shù):
---------------
image_id圖像的整數(shù)唯一ID
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
#打開HDF5文件
file=h5py.File(hdf5_dir/f"{image_id}.h5","r+")
image=np.array(file["/image"]).astype("uint8")
label=int(np.array(file["/meta"]).astype("uint8"))
returnimage,label
讀取方式對比
fromtimeitimporttimeit
read_single_timings=dict()
formethodin("disk","lmdb","hdf5"):
t=timeit(
"_read_single_funcs[method](0)",
setup="image=images[0];label=labels[0]",
number=1,
globals=globals(),
read_single_timings[method]=t
print(f"讀取方法:{method},使用耗時:{t}")
存儲方法存儲耗時Disk1.7msLMDB4.4msHDF52.3ms
多個圖像的讀取
將多個圖像保存為.png文件就可以理解為多次調(diào)用read_single_method()這樣。但這不適用于LMDB或HDF5,因為每個圖像都有不同的數(shù)據(jù)庫文件。
多圖像調(diào)整代碼
從磁盤中讀取多個都圖像
defread_many_disk(num_images):
"""參數(shù):
---------------
num_images要讀取的圖像數(shù)量
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
images,labels=[],[]
#循環(huán)遍歷所有ID,一張一張地讀取每張圖片
forimage_idinrange(num_images):
images.append(np.array(Image.open(disk_dir/f"{image_id}.png")))
withopen(disk_dir/f"{num_images}.csv","r")ascsvfile:
reader=csv.reader(
csvfile,delimiter="",quotechar="|",quoting=csv.QUOTE_MINIMAL
forrowinreader:
labels.append(int(row[0]))
returnimages,labels
從LMDB中讀取多個都圖像
defread_many_lmdb(num_images):
"""參數(shù):
---------------
num_images要讀取的圖像數(shù)量
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
images,labels=[],[]
env=lmdb.open(str(lmdb_dir/f"{num_images}_lmdb"),readonly=True)
#開始一個新的事務(wù)
withenv.begin()astxn:
#在一個事務(wù)中讀取,也可以拆分成多個事務(wù)分別讀取
forimage_idinrange(num_images):
data=txn.get(f"{image_id:08}".encode("ascii"))
#CIFAR_Image對象,作為值存儲
cifar_image=pickle.loads(data)
#檢索相關(guān)位
images.append(cifar_image.get_image())
labels.append(cifar_image.label)
env.close()
returnimages,labels
從HDF5中讀取多個都圖像
defread_many_hdf5(num_images):
"""參數(shù):
---------------
num_images要讀取的圖像數(shù)量
返回結(jié)果:
---------------
images圖像數(shù)組(N,32,32,3)格式
labels標(biāo)簽數(shù)組(N,1)格式
images,labels=[],[]
#打開HDF5文件
file=h5py.File(hdf5_dir/f"{num_images}_many.h5","r+")
images=np.array(fi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 商場保底疫情減免申請書
- 置換車輛申請書文本
- 大學(xué)歷史學(xué)科期中測驗安排試卷及答案
- 大學(xué)軟件測試工程師技能考核試卷及答案
- 污水處理廠再生水回用工程項目建議書
- 螢石礦采選項目運營管理方案
- 地下管網(wǎng)改造全過程監(jiān)管方案
- 糧食與農(nóng)資應(yīng)急儲備庫項目技術(shù)方案
- 工程設(shè)計優(yōu)化與成本控制方案
- 工程監(jiān)理考試題及答案
- 2025-2026人教版數(shù)學(xué)七年級上冊期末模擬試卷(含答案)
- 廣告行業(yè)法律法規(guī)與行業(yè)規(guī)范(標(biāo)準(zhǔn)版)
- 2026年國安民警副科級面試題及實戰(zhàn)解答
- 2026年紀(jì)檢監(jiān)察室工作面試題集
- ICH《M10:生物分析方法驗證及樣品分析》
- 國家開放大學(xué)電大24210丨學(xué)前兒童科學(xué)教育活動指導(dǎo)(統(tǒng)設(shè)課)期末終考題庫
- 【讀后續(xù)寫】2021年11月稽陽聯(lián)考讀后續(xù)寫講評:Saving the Daisies 名師課件-陳星可
- 教育培訓(xùn)班項目可行性研究報告
- 人參健康食品營銷策劃
- 2024年人參項目營銷策劃方案
- 工會職工大會制度實施細(xì)則范本
評論
0/150
提交評論