版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第python目標檢測yolo2詳解及預測代碼復現(xiàn)目錄前言實現(xiàn)思路1、yolo2的預測思路(網(wǎng)絡(luò)構(gòu)建思路)2、先驗框的生成3、利用先驗框?qū)W(wǎng)絡(luò)的輸出進行解碼4、進行得分排序與非極大抑制篩選實現(xiàn)結(jié)果
前言
最近在學習yolo1、yolo2和yolo3,寫這篇博客主要是為了讓自己對yolo2的結(jié)構(gòu)有更加深刻的理解,同時要理解清楚先驗框的含義。
盡量配合代碼觀看會更容易理解。
下載鏈接:/s/1NAqme8dD2Zoeo1Yd1xQVFw
提取碼:oq05
實現(xiàn)思路
1、yolo2的預測思路(網(wǎng)絡(luò)構(gòu)建思路)
YOLOv2使用了一個新的分類網(wǎng)絡(luò)DarkNet19作為特征提取部分,DarkNet19包含19個卷積層、5個最大值池化層。網(wǎng)絡(luò)使用了較多的3x3卷積核,在每一次池化操作后把通道數(shù)翻倍。借鑒了networkinnetwork的思想,把1x1的卷積核置于3x3的卷積核之間,用來壓縮特征。使用batchnormalization穩(wěn)定模型訓練,加速收斂,正則化模型。
與此同時,其保留了一個shortcut用于存儲之前的特征。
最后輸出的conv_dec的shape為(13,13,425),其中13x13是把整個圖分為13x13的網(wǎng)格用于預測,425可以分解為(85x5),在85中,其可以分為80和5兩部分,由于yolo2常用的是coco數(shù)據(jù)集,其中具有80個類,剩余的5指的是x、y、w、h和其置信度。x5的5中,意味著預測結(jié)果包含5個框,分別對應5個先驗框。
其實際情況就是,輸入N張416x416的圖片,在經(jīng)過多層的運算后,會輸出一個shape為(N,13,13,425)的數(shù)據(jù),對應每個圖分為13x13的網(wǎng)格后5個先驗框的位置。
defconv2d(self,x,filters_num,filters_size,pad_size=0,stride=1,batch_normalize=True,activation=leaky_relu,use_bias=False,name='conv2d'):
#是否進行pad
ifpad_size0:
x=tf.pad(x,[[0,0],[pad_size,pad_size],[pad_size,pad_size],[0,0]])
#pad后進行卷積
out=tf.layers.conv2d(x,filters=filters_num,kernel_size=filters_size,strides=stride,padding='VALID',activation=None,use_bias=use_bias,name=name)
#BN應該在卷積層conv和激活函數(shù)activation之間,
#后面有BN層的conv就不用偏置bias,并激活函數(shù)activation在后
#如果需要標準化則進行標準化
ifbatch_normalize:
out=tf.layers.batch_normalization(out,axis=-1,momentum=0.9,training=False,name=name+'_bn')
ifactivation:
out=activation(out)
returnout
defmaxpool(self,x,size=2,stride=2,name='maxpool'):
returntf.layers.max_pooling2d(x,pool_size=size,strides=stride,name=name)
defpassthrough(self,x,stride):
#變小變長
returntf.space_to_depth(x,block_size=stride)
defdarknet(self):
x=tf.placeholder(dtype=tf.float32,shape=[None,416,416,3])
#416,416,3-416,416,32
net=self.conv2d(x,filters_num=32,filters_size=3,pad_size=1,
name='conv1')
#416,416,32-208,208,32
net=self.maxpool(net,size=2,stride=2,name='pool1')
#208,208,32-208,208,64
net=self.conv2d(net,64,3,1,name='conv2')
#208,208,64-104,104,64
net=self.maxpool(net,2,2,name='pool2')
#104,104,64-104,104,128
net=self.conv2d(net,128,3,1,name='conv3_1')
net=self.conv2d(net,64,1,0,name='conv3_2')
net=self.conv2d(net,128,3,1,name='conv3_3')
#104,104,128-52,52,128
net=self.maxpool(net,2,2,name='pool3')
net=self.conv2d(net,256,3,1,name='conv4_1')
net=self.conv2d(net,128,1,0,name='conv4_2')
net=self.conv2d(net,256,3,1,name='conv4_3')
#52,52,128-26,26,256
net=self.maxpool(net,2,2,name='pool4')
#26,26,256-26,26,512
net=self.conv2d(net,512,3,1,name='conv5_1')
net=self.conv2d(net,256,1,0,name='conv5_2')
net=self.conv2d(net,512,3,1,name='conv5_3')
net=self.conv2d(net,256,1,0,name='conv5_4')
net=self.conv2d(net,512,3,1,name='conv5_5')
#這一層特征圖,要進行后面passthrough,保留一層特征層
shortcut=net
#26,26,512-13,13,512
net=self.maxpool(net,2,2,name='pool5')#
#13,13,512-13,13,1024
net=self.conv2d(net,1024,3,1,name='conv6_1')
net=self.conv2d(net,512,1,0,name='conv6_2')
net=self.conv2d(net,1024,3,1,name='conv6_3')
net=self.conv2d(net,512,1,0,name='conv6_4')
net=self.conv2d(net,1024,3,1,name='conv6_5')
#下面這部分主要是trainingfordetection
net=self.conv2d(net,1024,3,1,name='conv7_1')
#13,13,1024-13,13,1024
net=self.conv2d(net,1024,3,1,name='conv7_2')
#shortcut增加了一個中間卷積層,先采用64個1*1卷積核進行卷積,然后再進行passthrough處理
#得到了26*26*512-26*26*64-13*13*256的特征圖
shortcut=self.conv2d(shortcut,64,1,0,name='conv_shortcut')
shortcut=self.passthrough(shortcut,2)
#連接之后,變成13*13*(1024+256)
net=tf.concat([shortcut,net],axis=-1)
#channel整合到一起,concatenatedwiththeoriginalfeatures,passthrough層與ResNet網(wǎng)絡(luò)的shortcut類似,以前面更高分辨率的特征圖為輸入,然后將其連接到后面的低分辨率特征圖上,
net=self.conv2d(net,1024,3,1,name='conv8')
#detectionlayer:最后用一個1*1卷積去調(diào)整channel,該層沒有BN層和激活函數(shù),變成:S*S*(B*(5+C)),在這里為:13*13*425
output=self.conv2d(net,filters_num=self.f_num,filters_size=1,batch_normalize=False,activation=None,
use_bias=True,name='conv_dec')
returnoutput,x
2、先驗框的生成
對于yolo1來講,其最后輸出的結(jié)果的shape為(7,7,30),對應著兩個框及其種類,盡管網(wǎng)絡(luò)可以不斷的訓練最后實現(xiàn)框的位置的調(diào)整,但是如果我們能夠給出一些框的尺寸備用,效果理論上會更好(實際上也是),這就是先驗框的來歷。
但是yolo2的框并不是隨便就得到的,它是通過計算得到的。
在尋常的kmean算法中,使用的是歐氏距離來完成聚類,但是先驗框顯然不可以這樣,因為大框的歐氏距離更大,yolo2使用的是處理后的IOU作為歐氏距離。
最后得到五個聚類中心便是先驗框的寬高。
importnumpyasnp
importxml.etree.ElementTreeasET
importglob
importrandom
defcas_iou(box,cluster):
x=np.minimum(cluster[:,0],box[0])
y=np.minimum(cluster[:,1],box[1])
intersection=x*y
area1=box[0]*box[1]
area2=cluster[:,0]*cluster[:,1]
iou=intersection/(area1+area2-intersection)
returniou
defavg_iou(box,cluster):
returnnp.mean([np.max(cas_iou(box[i],cluster))foriinrange(box.shape[0])])
defkmeans(box,k):
#取出一共有多少框
row=box.shape[0]
#每個框各個點的位置
distance=np.empty((row,k))
#最后的聚類位置
last_clu=np.zeros((row,))
np.random.seed()
#隨機選5個當聚類中心
cluster=box[np.random.choice(row,k,replace=False)]
#cluster=random.sample(row,k)
whileTrue:
#計算每一行距離五個點的iou情況。
foriinrange(row):
distance[i]=1-cas_iou(box[i],cluster)
#取出最小點
near=np.argmin(distance,axis=1)
if(last_clu==near).all():
break
#求每一個類的中位點
forjinrange(k):
cluster[j]=np.median(
box[near==j],axis=0)
last_clu=near
returncluster
defload_data(path):
data=[]
#對于每一個xml都尋找box
forxml_fileinglob.glob('{}/*xml'.format(path)):
tree=ET.parse(xml_file)
height=int(tree.findtext('./size/height'))
width=int(tree.findtext('./size/width'))
#對于每一個目標都獲得它的寬高
forobjintree.iter('object'):
xmin=int(float(obj.findtext('bndbox/xmin')))/width
ymin=int(float(obj.findtext('bndbox/ymin')))/height
xmax=int(float(obj.findtext('bndbox/xmax')))/width
ymax=int(float(obj.findtext('bndbox/ymax')))/height
xmin=np.float64(xmin)
ymin=np.float64(ymin)
xmax=np.float64(xmax)
ymax=np.float64(ymax)
#得到寬高
data.append([xmax-xmin,ymax-ymin])
returnnp.array(data)
if__name__=='__main__':
anchors_num=5
#載入數(shù)據(jù)集,可以使用VOC的xml
path='../SSD-Tensorflow-master/VOC2012/Annotations'
#載入所有的xml
#存儲格式為轉(zhuǎn)化為比例后的width,height
data=load_data(path)
#使用k聚類算法
out=kmeans(data,anchors_num)
print('acc:{:.2f}%'.format(avg_iou(data,out)*100))
print(out)
print('box',out[:,0]*13,out[:,1]*13)
ratios=np.around(out[:,0]/out[:,1],decimals=2).tolist()
print('ratios:',sorted(ratios))
得到結(jié)果為:
acc:61.32%
[[0.0440.07733333]
[0.1060.17866667]
[0.4080.616]
[0.8160.83]
[0.20.38933333]]
box[0.5721.3785.30410.6082.6][1.005333332.322666678.00810.795.06133333]
ratios:[0.51,0.57,0.59,0.66,0.98]
3、利用先驗框?qū)W(wǎng)絡(luò)的輸出進行解碼
yolo2的解碼過程與SSD類似,但是并不太一樣,相比之下yolo2的解碼過程更容易理解,因為其僅有單層的特征層。
1、將網(wǎng)絡(luò)的輸出reshape成[-1,13*13,5,80+5],代表169個中心點每個中心點的5個先驗框的情況。
2、將80+5的5中的xywh分離出來,0、1是xy相對中心點的偏移量;2、3是寬和高的情況;4是置信度。
3、建立13x13的網(wǎng)格,代表圖片進行13x13處理后網(wǎng)格的中心點。
4、利用計算公式計算實際的bbox的位置。
解碼部分代碼如下:
defdecode(self,net):
self.anchor_size=tf.constant(self.anchor_size,tf.float32)
#net的shape為[batch,169,5,85]
net=tf.reshape(net,[-1,13*13,self.num_anchors,self.num_class+5])
#85里面0、1為xy的偏移量,2、3是wh的偏移量,4是置信度,5-84是每個種類的概率
#偏移量、置信度、類別
#中心坐標相對于該cell坐上角的偏移量,sigmoid函數(shù)歸一化到(0,1)
#[batch,169,5,2]
xy_offset=tf.nn.sigmoid(net[:,:,:,0:2])
wh_offset=tf.exp(net[:,:,:,2:4])
obj_probs=tf.nn.sigmoid(net[:,:,:,4])
class_probs=tf.nn.softmax(net[:,:,:,5:])
#在featuremap對應坐標生成anchors,13,13
height_index=tf.range(self.feature_map_size[0],dtype=tf.float32)
width_index=tf.range(self.feature_map_size[1],dtype=tf.float32)
x_cell,y_cell=tf.meshgrid(height_index,width_index)
x_cell=tf.reshape(x_cell,[1,-1,1])#和上面[H*W,num_anchors,num_class+5]對應
y_cell=tf.reshape(y_cell,[1,-1,1])
#x_cell和y_cell是網(wǎng)格分割中心
#xy_offset是相對中心的偏移情況
bbox_x=(x_cell+xy_offset[:,:,:,0])/13
bbox_y=(y_cell+xy_offset[:,:,:,1])/13
bbox_w=(self.anchor_size[:,0]*wh_offset[:,:,:,0])/13
bbox_h=(self.anchor_size[:,1]*wh_offset[:,:,:,1])/13
bboxes=tf.stack([bbox_x-bbox_w/2,bbox_y-bbox_h/2,bbox_x+bbox_w/2,bbox_y+bbox_h/2],
axis=3)
returnbboxes,obj_probs,class_probs
4、進行得分排序與非極大抑制篩選
這一部分基本上是所有目標檢測通用的部分。
1、將所有box還原成圖片中真實的位置。
2、得到每個box最大的預測概率對應的種類。
3、將每個box最大的預測概率乘上置信度得到每個box的分數(shù)。
4、對分數(shù)進行篩選與排序。
5、非極大抑制,去除重復率過大的框。
實現(xiàn)代碼如下:
defbboxes_cut(self,bbox_min_max,bboxes):
bboxes=np.copy(bboxes)
bboxes=np.transpose(bboxes)
bbox_min_max=np.transpose(bbox_min_max)
#cutthebox
bboxes[0]=np.maximum(bboxes[0],bbox_min_max[0])#xmin
bboxes[1]=np.maximum(bboxes[1],bbox_min_max[1])#ymin
bboxes[2]=np.minimum(bboxes[2],bbox_min_max[2])#xmax
bboxes[3]=np.minimum(bboxes[3],bbox_min_max[3])#ymax
bboxes=np.transpose(bboxes)
returnbboxes
defbboxes_sort(self,classes,scores,bboxes,top_k=400):
index=np.argsort(-scores)
classes=classes[index][:top_k]
scores=scores[index][:top_k]
bboxes=bboxes[index][:top_k]
returnclasses,scores,bboxes
defbboxes_iou(self,bboxes1,bboxes2):
bboxes1=np.transpose(bboxes1)
bboxes2=np.transpose(bboxes2)
int_ymin=np.maximum(bboxes1[0],bboxes2[0])
int_xmin=np.maximum(bboxes1[1],bboxes2[1])
int_ymax=np.minimum(bboxes1[2],bboxes2[2])
int_xmax=np.minimum(bboxes1[3],bboxes2[3])
int_h=np.maximum(int_ymax-int_ymin,0.)
int_w=np.maximum(int_xmax-int_xmin,0.)
#計算IOU
int_vol=int_h*int_w#交集面積
vol1=(bboxes1[2]-bboxes1[0])*(bboxes1[3]-bboxes1[1])#bboxes1面積
vol2=(bboxes2[2]-bboxes2[0])*(bboxes2[3]-bboxes2[1])#bboxes2面積
IOU=int_vol/(vol1+vol2-int_vol)#IOU=交集/并集
returnIOU
#NMS,或者用tf.image.non_max_suppression
defbboxes_nms(self,classes,scores,bboxes,nms_threshold=0.2):
keep_bboxes=np.ones(scores.shape,dtype=np.bool)
foriinrange(scores.size-1):
ifkeep_bboxes[i]:
overlap=self.bboxes_iou(bboxes[i],bboxes[(i+1):])
keep_overlap=np.logical_or(overlapnms_threshold,
classes[(i+1):]!=classes[i])#IOU沒有超過0.5或者是不同的類則保存下來
keep_bboxes[(i+1):]=np.logical_and(keep_bboxes[(i+1):],keep_overlap)
idxes=np.where(keep_bboxes)
returnclasses[idxes],scores[idxes],bboxes[idxes]
defpostprocess(self,bboxes,obj_probs,class_probs,image_shape=(416,416),threshold=0.5):
bboxes=np.reshape(bboxes,[-1,4])
#將所有box還原成圖片中真實
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- apg工藝生產(chǎn)管理制度
- 釀造車間生產(chǎn)管理制度
- 生產(chǎn)技術(shù)方面制度
- 安全生產(chǎn)法電工管理制度
- 班組安全生產(chǎn)制度范本
- 代加工生產(chǎn)規(guī)章制度
- 生產(chǎn)計劃管理規(guī)章制度
- 生產(chǎn)服務(wù)管理制度范本
- 2026山東泰安市屬事業(yè)單位初級綜合類崗位招聘參考考試試題附答案解析
- 2026甘肅白銀市平川區(qū)容通水務(wù)有限公司招聘9人參考考試題庫附答案解析
- 清真生產(chǎn)過程管控制度
- 2026年淺二度燒傷處理
- 北京通州產(chǎn)業(yè)服務(wù)有限公司招聘考試備考題庫及答案解析
- 河北省NT名校聯(lián)合體2025-2026學年高三上學期1月月考英語(含答案)
- 2025-2026學年滬科版八年級數(shù)學上冊期末測試卷(含答案)
- 途虎養(yǎng)車安全培訓課件
- 衛(wèi)生管理研究論文
- 2025-2026學年人教版(新教材)小學數(shù)學二年級下冊(全冊)教學設(shè)計(附教材目錄P161)
- 委托市場調(diào)研合同范本
- 畜牧安全培訓資料課件
- 2025年度黨支部書記述職報告
評論
0/150
提交評論