https://blog.csdn.net/Tramac/article/details/70158426
Python層作為輸入的四個(gè)必須的函數(shù):
setup(self, bottom, top)
reshape(self, bottom, top)
forward(self, bottom, top)
backward(self, bottom, top)
class VOCSegDataLayer(caffe.layer) #定義為Python層
該類的作用:獲取所需要的image對,即input image、label image,作為FCN的輸入。
①def setup(self, bottom, top)
setup()的參數(shù):voc_dir:數(shù)據(jù)的根目錄. split:train/val/test模式的選擇. mean:圖片的均值. randomize:初始化隨機(jī)數(shù)生成,作用? seed:隨機(jī)化seed,起點(diǎn),作用?
以下為該5個(gè)參數(shù)的初始化:
params = eval(self.param_str) #將字符串當(dāng)成有效的表達(dá)式來求值并返回計(jì)算結(jié)果
self.voc_dir = params['voc_dir']
self.split = params['split']
self.mean = np.array(params['mean']) #變成數(shù)組
self.random = params.get('randomize', True) #初始化self.random,默認(rèn)為True
self.seed = params.get('seed', None)
if len(top)!= 2: #判斷輸出是否為2(data和label)
? 報(bào)錯(cuò)
if len(bottom) != 0 #判斷輸入是否為0(數(shù)據(jù)層無bottom)
#load indices for images and labels(獲取image和lable的索引)
split_f = '{}/ImageSets/Segmentation/{}.txt'.format(self.voc_dir, self.split) #.format() 用{}代替%,()中的內(nèi)容按順序放入前面的{}中,txt文件中存的是圖片的索引
self.indices = open(split_f, 'r').read().splitline() #open()文件打開操作,'r'讀模式, 'w'寫模式,'a'追加, 'b'二進(jìn)制, '+'讀/寫. read()用于從文件讀取指定的字節(jié)數(shù),若未給定或?yàn)樨?fù)值則讀取所有. splitline()按照行('\r','\r\n','\n')分隔,返回一個(gè)包含各行作為元素的列表,默認(rèn)不包含換行符.
self.idx = 0
#如果不是train模式,則不需要參數(shù)self.random
if 'train' not in self.split: #not in 運(yùn)算符,如果在指定的序列中沒有找到值,返回True,否則返回False.
#如果是train模式,則需要初始化self.random.
if self.random:
? random.seed(self.seed) #seed()不能直接訪問,需要導(dǎo)入random模塊.()中的self.seed為改變隨機(jī)數(shù)生成器的種子seed.無返回值. 作用:設(shè)置生成隨機(jī)數(shù)用的起始值,調(diào)用任何其他random模塊函數(shù)之前調(diào)用這個(gè)函數(shù).
? self.idx = random.randint(0, len(self.indices)-1) #random.randint(a, b)用于生成一個(gè)指定范圍內(nèi)的整數(shù),用來打亂'txt'中文件的順序?
②def reshape(self, bottom, top): #獲取image+label對
self.data = self.load_image(self.indices[self.idx]) #self.indices前面得到的文件名列表,self.idx索引值
self.label = self.load_label(self.indices[self.idx])
#load_image()和load_label()定義的兩個(gè)數(shù)據(jù)接口函數(shù)
#reshape輸出的形狀
top[0].reshape(1, *self.data.shape) #image
top[1].reshape(1, *self.label.shape) #label
③def forward(self, bottom, top): #assign output分配輸出
top[0].data[...] = self.data #將self.data,self.label賦值到top.data?
top[1].data[...] = self.label
#選擇下一個(gè)輸入
if self.randon:
? self.idx = random.randint(0, len(self.indices)-1)
else:
? self.idx +=1 #若不是train,idx沒有隨機(jī),從0開始
? if self.idx == len(self.indices):
? ? ? self.idx = 0
④def backward(self, top, propagate_down, bottom)
pass #無反向過程
def load_image(self.idx): #調(diào)用時(shí),輸入的為indices[idx]
#獲取輸入的圖像,預(yù)處理來適配caffe:轉(zhuǎn)為float→改變通道(RGB→BGR)→減去均值→改為CxHxW
im = Image.open('{}/JPEGImage/{}.jpg'.format(self.voc_dir, idx)) #打開圖片
in_ = np.array(im, dtype = np.float32 #創(chuàng)建數(shù)組并制定數(shù)組中元素的類型
in_ = in_[:,:,::-1] #RGB-BGR?
in_ -= self.mean #減去均值
in_ = in_.transpose((2,0,1)) #改變通道順序
return in_
def load_label(self.idx) #獲取label,label為1xHxW單通道,整數(shù)數(shù)組,單通道是由loss決定的
im = Image.open('{}/SegmentationClass/{}.png'.format(self.voc_dir, idx))
label = np.array(im, dtype = np.unit8)
label = label[np.newaxis,...]
return label
#[...]代表許多產(chǎn)生一個(gè)完整的索引元組必要的分號,label本來為2維圖像,只有H,W,需要將其變?yōu)?維,即1xHxW.
---------------------
本文來自 Tramac 的CSDN 博客 ,全文地址請點(diǎn)擊:https://blog.csdn.net/Tramac/article/details/70158426?utm_source=copy