计算机视觉:单阶段目标检测模型YOLO-V3
計(jì)算機(jī)視覺(jué):單階段目標(biāo)檢測(cè)模型YOLO-V3
- 單階段目標(biāo)檢測(cè)模型YOLO-V3
- YOLO-V3 模型設(shè)計(jì)思想
- 產(chǎn)生候選區(qū)域
- 生成錨框
- 生成預(yù)測(cè)框
- 對(duì)候選區(qū)域進(jìn)行標(biāo)注
- 標(biāo)注錨框是否包含物體
- 標(biāo)注預(yù)測(cè)框的位置坐標(biāo)標(biāo)簽
- 標(biāo)注錨框包含物體類(lèi)別的標(biāo)簽
- 標(biāo)注錨框的具體程序
單階段目標(biāo)檢測(cè)模型YOLO-V3
上面介紹的R-CNN系列算法需要先產(chǎn)生候選區(qū)域,再對(duì)候選區(qū)域做分類(lèi)和位置坐標(biāo)的預(yù)測(cè),這類(lèi)算法被稱為兩階段目標(biāo)檢測(cè)算法。近幾年,很多研究人員相繼提出一系列單階段的檢測(cè)算法,只需要一個(gè)網(wǎng)絡(luò)即可同時(shí)產(chǎn)生候選區(qū)域并預(yù)測(cè)出物體的類(lèi)別和位置坐標(biāo)。
與R-CNN系列算法不同,YOLO-V3使用單個(gè)網(wǎng)絡(luò)結(jié)構(gòu),在產(chǎn)生候選區(qū)域的同時(shí)即可預(yù)測(cè)出物體類(lèi)別和位置,不需要分成兩階段來(lái)完成檢測(cè)任務(wù)。另外,YOLO-V3算法產(chǎn)生的預(yù)測(cè)框數(shù)目比Faster R-CNN少很多。Faster R-CNN中每個(gè)真實(shí)框可能對(duì)應(yīng)多個(gè)標(biāo)簽為正的候選區(qū)域,而YOLO-V3里面每個(gè)真實(shí)框只對(duì)應(yīng)一個(gè)正的候選區(qū)域。這些特性使得YOLO-V3算法具有更快的速度,能到達(dá)實(shí)時(shí)響應(yīng)的水平。
Joseph Redmon等人在2015年提出YOLO(You Only Look Once,YOLO)算法,通常也被稱為YOLO-V1;2016年,他們對(duì)算法進(jìn)行改進(jìn),又提出YOLO-V2版本;2018年發(fā)展出YOLO-V3版本。
YOLO-V3 模型設(shè)計(jì)思想
YOLO-V3算法的基本思想可以分成兩部分:
- 按一定規(guī)則在圖片上產(chǎn)生一系列的候選區(qū)域,然后根據(jù)這些候選區(qū)域與圖片上物體真實(shí)框之間的位置關(guān)系對(duì)候選區(qū)域進(jìn)行標(biāo)注。跟真實(shí)框足夠接近的那些候選區(qū)域會(huì)被標(biāo)注為正樣本,同時(shí)將真實(shí)框的位置作為正樣本的位置目標(biāo)。偏離真實(shí)框較大的那些候選區(qū)域則會(huì)被標(biāo)注為負(fù)樣本,負(fù)樣本不需要預(yù)測(cè)位置或者類(lèi)別。
- 使用卷積神經(jīng)網(wǎng)絡(luò)提取圖片特征并對(duì)候選區(qū)域的位置和類(lèi)別進(jìn)行預(yù)測(cè)。這樣每個(gè)預(yù)測(cè)框就可以看成是一個(gè)樣本,根據(jù)真實(shí)框相對(duì)它的位置和類(lèi)別進(jìn)行了標(biāo)注而獲得標(biāo)簽值,通過(guò)網(wǎng)絡(luò)模型預(yù)測(cè)其位置和類(lèi)別,將網(wǎng)絡(luò)預(yù)測(cè)值和標(biāo)簽值進(jìn)行比較,就可以建立起損失函數(shù)。
YOLO-V3算法訓(xùn)練過(guò)程的流程圖如 圖8 所示:
圖8:YOLO-V3算法訓(xùn)練流程圖
- 圖8 左邊是輸入圖片,上半部分所示的過(guò)程是使用卷積神經(jīng)網(wǎng)絡(luò)對(duì)圖片提取特征,隨著網(wǎng)絡(luò)不斷向前傳播,特征圖的尺寸越來(lái)越小,每個(gè)像素點(diǎn)會(huì)代表更加抽象的特征模式,直到輸出特征圖,其尺寸減小為原圖的132\frac{1}{32}321?。
- 圖8 下半部分描述了生成候選區(qū)域的過(guò)程,首先將原圖劃分成多個(gè)小方塊,每個(gè)小方塊的大小是32×3232 \times 3232×32,然后以每個(gè)小方塊為中心分別生成一系列錨框,整張圖片都會(huì)被錨框覆蓋到。在每個(gè)錨框的基礎(chǔ)上產(chǎn)生一個(gè)與之對(duì)應(yīng)的預(yù)測(cè)框,根據(jù)錨框和預(yù)測(cè)框與圖片上物體真實(shí)框之間的位置關(guān)系,對(duì)這些預(yù)測(cè)框進(jìn)行標(biāo)注。
- 將上方支路中輸出的特征圖與下方支路中產(chǎn)生的預(yù)測(cè)框標(biāo)簽建立關(guān)聯(lián),創(chuàng)建損失函數(shù),開(kāi)啟端到端的訓(xùn)練過(guò)程。
接下來(lái)具體介紹流程中各節(jié)點(diǎn)的原理和代碼實(shí)現(xiàn)。
產(chǎn)生候選區(qū)域
如何產(chǎn)生候選區(qū)域,是檢測(cè)模型的核心設(shè)計(jì)方案。目前大多數(shù)基于卷積神經(jīng)網(wǎng)絡(luò)的模型所采用的方式大體如下:
- 按一定的規(guī)則在圖片上生成一系列位置固定的錨框,將這些錨框看作是可能的候選區(qū)域。
- 對(duì)錨框是否包含目標(biāo)物體進(jìn)行預(yù)測(cè),如果包含目標(biāo)物體,還需要預(yù)測(cè)所包含物體的類(lèi)別,以及預(yù)測(cè)框相對(duì)于錨框位置需要調(diào)整的幅度。
生成錨框
將原始圖片劃分成m×nm\times nm×n個(gè)區(qū)域,如下圖所示,原始圖片高度H=640H=640H=640, 寬度W=480W=480W=480,如果我們選擇小塊區(qū)域的尺寸為32×3232 \times 3232×32,則mmm和nnn分別為:
m=64032=20m = \frac{640}{32} = 20m=32640?=20
n=48032=15n = \frac{480}{32} = 15n=32480?=15
如 圖9 所示,將原始圖像分成了20行15列小方塊區(qū)域。
圖9:將圖片劃分成多個(gè)32x32的小方塊
YOLO-V3算法會(huì)在每個(gè)區(qū)域的中心,生成一系列錨框。為了展示方便,我們先在圖中第十行第四列的小方塊位置附近畫(huà)出生成的錨框,如 圖10 所示。
注意:
這里為了跟程序中的編號(hào)對(duì)應(yīng),最上面的行號(hào)是第0行,最左邊的列號(hào)是第0列
圖10:在第10行第4列的小方塊區(qū)域生成3個(gè)錨框
圖11 展示在每個(gè)區(qū)域附近都生成3個(gè)錨框,很多錨框堆疊在一起可能不太容易看清楚,但過(guò)程跟上面類(lèi)似,只是需要以每個(gè)區(qū)域的中心點(diǎn)為中心,分別生成3個(gè)錨框。
圖11:在每個(gè)小方塊區(qū)域生成3個(gè)錨框
生成預(yù)測(cè)框
在前面已經(jīng)指出,錨框的位置都是固定好的,不可能剛好跟物體邊界框重合,需要在錨框的基礎(chǔ)上進(jìn)行位置的微調(diào)以生成預(yù)測(cè)框。預(yù)測(cè)框相對(duì)于錨框會(huì)有不同的中心位置和大小,采用什么方式能得到預(yù)測(cè)框呢?我們先來(lái)考慮如何生成其中心位置坐標(biāo)。
比如上面圖中在第10行第4列的小方塊區(qū)域中心生成的一個(gè)錨框,如綠色虛線框所示。以小方格的寬度為單位長(zhǎng)度,
此小方塊區(qū)域左上角的位置坐標(biāo)是:
cx=4c_x = 4cx?=4
cy=10c_y = 10cy?=10
此錨框的區(qū)域中心坐標(biāo)是:
center_x=cx+0.5=4.5center\_x = c_x + 0.5 = 4.5center_x=cx?+0.5=4.5
center_y=cy+0.5=10.5center\_y = c_y + 0.5 = 10.5center_y=cy?+0.5=10.5
可以通過(guò)下面的方式生成預(yù)測(cè)框的中心坐標(biāo):
bx=cx+σ(tx)b_x = c_x + \sigma(t_x)bx?=cx?+σ(tx?)
by=cy+σ(ty)b_y = c_y + \sigma(t_y)by?=cy?+σ(ty?)
其中txt_xtx?和tyt_yty?為實(shí)數(shù),σ(x)\sigma(x)σ(x)是我們之前學(xué)過(guò)的Sigmoid函數(shù),其定義如下:
σ(x)=11+exp(?x)\sigma(x) = \frac{1}{1 + exp(-x)}σ(x)=1+exp(?x)1?
由于Sigmoid的函數(shù)值在0~10 \thicksim 10~1之間,因此由上面公式計(jì)算出來(lái)的預(yù)測(cè)框的中心點(diǎn)總是落在第十行第四列的小區(qū)域內(nèi)部。
當(dāng)tx=ty=0t_x=t_y=0tx?=ty?=0時(shí),bx=cx+0.5b_x = c_x + 0.5bx?=cx?+0.5,by=cy+0.5b_y = c_y + 0.5by?=cy?+0.5,預(yù)測(cè)框中心與錨框中心重合,都是小區(qū)域的中心。
錨框的大小是預(yù)先設(shè)定好的,在模型中可以當(dāng)作是超參數(shù),下圖中畫(huà)出的錨框尺寸是
ph=350p_h = 350ph?=350
pw=250p_w = 250pw?=250
通過(guò)下面的公式生成預(yù)測(cè)框的大小:
bh=phethb_h = p_h e^{t_h}bh?=ph?eth?
bw=pwetwb_w = p_w e^{t_w}bw?=pw?etw?
如果tx=ty=0,th=tw=0t_x=t_y=0, t_h=t_w=0tx?=ty?=0,th?=tw?=0,則預(yù)測(cè)框跟錨框重合。
如果給tx,ty,th,twt_x, t_y, t_h, t_wtx?,ty?,th?,tw?隨機(jī)賦值如下:
tx=0.2,ty=0.3,tw=0.1,th=?0.12t_x = 0.2, t_y = 0.3, t_w = 0.1, t_h = -0.12tx?=0.2,ty?=0.3,tw?=0.1,th?=?0.12
則可以得到預(yù)測(cè)框的坐標(biāo)是(154.98, 357.44, 276.29, 310.42),如 圖12 中藍(lán)色框所示。
說(shuō)明:
這里坐標(biāo)采用xywhxywhxywh的格式。
圖12:生成預(yù)測(cè)框
這里我們會(huì)問(wèn):當(dāng)tx,ty,tw,tht_x, t_y, t_w, t_htx?,ty?,tw?,th?取值為多少的時(shí)候,預(yù)測(cè)框能夠跟真實(shí)框重合?為了回答問(wèn)題,只需要將上面預(yù)測(cè)框坐標(biāo)中的bx,by,bh,bwb_x, b_y, b_h, b_wbx?,by?,bh?,bw?設(shè)置為真實(shí)框的位置,即可求解出ttt的數(shù)值。
令:
σ(tx?)+cx=gtx\sigma(t^*_x) + c_x = gt_xσ(tx??)+cx?=gtx?
σ(ty?)+cy=gty\sigma(t^*_y) + c_y = gt_yσ(ty??)+cy?=gty?
pwetw?=gthp_w e^{t^*_w} = gt_hpw?etw??=gth?
pheth?=gtwp_h e^{t^*_h} = gt_wph?eth??=gtw?
可以求解出 (tx?,ty?,tw?,th?)(t^*_x, t^*_y, t^*_w, t^*_h)(tx??,ty??,tw??,th??)
如果ttt是網(wǎng)絡(luò)預(yù)測(cè)的輸出值,將t?t^*t?作為目標(biāo)值,以他們之間的差距作為損失函數(shù),則可以建立起一個(gè)回歸問(wèn)題,通過(guò)學(xué)習(xí)網(wǎng)絡(luò)參數(shù),使得ttt足夠接近t?t^*t?,從而能夠求解出預(yù)測(cè)框的位置坐標(biāo)和大小。
預(yù)測(cè)框可以看作是在錨框基礎(chǔ)上的一個(gè)微調(diào),每個(gè)錨框會(huì)有一個(gè)跟它對(duì)應(yīng)的預(yù)測(cè)框,我們需要確定上面計(jì)算式中的tx,ty,tw,tht_x, t_y, t_w, t_htx?,ty?,tw?,th?,從而計(jì)算出與錨框?qū)?yīng)的預(yù)測(cè)框的位置和形狀。
對(duì)候選區(qū)域進(jìn)行標(biāo)注
每個(gè)區(qū)域可以產(chǎn)生3種不同形狀的錨框,每個(gè)錨框都是一個(gè)可能的候選區(qū)域,對(duì)這些候選區(qū)域我們需要了解如下幾件事情:
-
錨框是否包含物體,這可以看成是一個(gè)二分類(lèi)問(wèn)題,使用標(biāo)簽objectness來(lái)表示。當(dāng)錨框包含了物體時(shí),objectness=1,表示預(yù)測(cè)框?qū)儆谡?lèi);當(dāng)錨框不包含物體時(shí),設(shè)置objectness=0,表示錨框?qū)儆谪?fù)類(lèi)。
-
如果錨框包含了物體,那么它對(duì)應(yīng)的預(yù)測(cè)框的中心位置和大小應(yīng)該是多少,或者說(shuō)上面計(jì)算式中的tx,ty,tw,tht_x, t_y, t_w, t_htx?,ty?,tw?,th?應(yīng)該是多少,使用location標(biāo)簽。
-
如果錨框包含了物體,那么具體類(lèi)別是什么,這里使用變量label來(lái)表示其所屬類(lèi)別的標(biāo)簽。
選取任意一個(gè)錨框?qū)λM(jìn)行標(biāo)注,也就是需要確定其對(duì)應(yīng)的objectness, (tx,ty,tw,th)(t_x, t_y, t_w, t_h)(tx?,ty?,tw?,th?)和label,下面將分別講述如何確定這三個(gè)標(biāo)簽的值。
標(biāo)注錨框是否包含物體
如 圖13 所示,這里一共有3個(gè)目標(biāo),以最左邊的人像為例,其真實(shí)框是(40.93,141.1,186.06,374.63)(40.93, 141.1, 186.06, 374.63)(40.93,141.1,186.06,374.63)。
圖13:選出與真實(shí)框中心位于同一區(qū)域的錨框
真實(shí)框的中心點(diǎn)坐標(biāo)是:
center_x=40.93+186.06/2=133.96center\_x = 40.93 + 186.06 / 2 = 133.96center_x=40.93+186.06/2=133.96
center_y=141.1+374.63/2=328.42center\_y = 141.1 + 374.63 / 2 = 328.42center_y=141.1+374.63/2=328.42
i=133.96/32=4.18625i = 133.96 / 32 = 4.18625i=133.96/32=4.18625
j=328.42/32=10.263125j = 328.42 / 32 = 10.263125j=328.42/32=10.263125
它落在了第10行第4列的小方塊內(nèi),如圖13所示。此小方塊區(qū)域可以生成3個(gè)不同形狀的錨框,其在圖上的編號(hào)和大小分別是A1(116,90),A2(156,198),A3(373,326)A_1(116, 90), A_2(156, 198), A_3(373, 326)A1?(116,90),A2?(156,198),A3?(373,326)。
用這3個(gè)不同形狀的錨框跟真實(shí)框計(jì)算IoU,選出IoU最大的錨框。這里為了簡(jiǎn)化計(jì)算,只考慮錨框的形狀,不考慮其跟真實(shí)框中心之間的偏移,具體計(jì)算結(jié)果如 圖14 所示。
圖14:選出與真實(shí)框與錨框的IoU
其中跟真實(shí)框IoU最大的是錨框A3A_3A3?,形狀是(373,326)(373, 326)(373,326),將它所對(duì)應(yīng)的預(yù)測(cè)框的objectness標(biāo)簽設(shè)置為1,其所包括的物體類(lèi)別就是真實(shí)框里面的物體所屬類(lèi)別。
依次可以找出其他幾個(gè)真實(shí)框?qū)?yīng)的IoU最大的錨框,然后將它們的預(yù)測(cè)框的objectness標(biāo)簽也都設(shè)置為1。這里一共有20×15×3=90020 \times 15 \times 3 = 90020×15×3=900個(gè)錨框,只有3個(gè)預(yù)測(cè)框會(huì)被標(biāo)注為正。
由于每個(gè)真實(shí)框只對(duì)應(yīng)一個(gè)objectness標(biāo)簽為正的預(yù)測(cè)框,如果有些預(yù)測(cè)框跟真實(shí)框之間的IoU很大,但并不是最大的那個(gè),那么直接將其objectness標(biāo)簽設(shè)置為0當(dāng)作負(fù)樣本,可能并不妥當(dāng)。為了避免這種情況,YOLO-V3算法設(shè)置了一個(gè)IoU閾值iou_threshold,當(dāng)預(yù)測(cè)框的objectness不為1,但是其與某個(gè)真實(shí)框的IoU大于iou_threshold時(shí),就將其objectness標(biāo)簽設(shè)置為-1,不參與損失函數(shù)的計(jì)算。
所有其他的預(yù)測(cè)框,其objectness標(biāo)簽均設(shè)置為0,表示負(fù)類(lèi)。
對(duì)于objectness=1的預(yù)測(cè)框,需要進(jìn)一步確定其位置和包含物體的具體分類(lèi)標(biāo)簽,但是對(duì)于objectness=0或者-1的預(yù)測(cè)框,則不用管他們的位置和類(lèi)別。
標(biāo)注預(yù)測(cè)框的位置坐標(biāo)標(biāo)簽
當(dāng)錨框objectness=1時(shí),需要確定預(yù)測(cè)框位置相對(duì)于它微調(diào)的幅度,也就是錨框的位置標(biāo)簽。
在前面我們已經(jīng)問(wèn)過(guò)這樣一個(gè)問(wèn)題:當(dāng)tx,ty,tw,tht_x, t_y, t_w, t_htx?,ty?,tw?,th?取值為多少的時(shí)候,預(yù)測(cè)框能夠跟真實(shí)框重合?其做法是將預(yù)測(cè)框坐標(biāo)中的bx,by,bh,bwb_x, b_y, b_h, b_wbx?,by?,bh?,bw?設(shè)置為真實(shí)框的坐標(biāo),即可求解出ttt的數(shù)值。
令:
σ(tx?)+cx=gtx\sigma(t^*_x) + c_x = gt_xσ(tx??)+cx?=gtx?
σ(ty?)+cy=gty\sigma(t^*_y) + c_y = gt_yσ(ty??)+cy?=gty?
pwetw?=gtwp_w e^{t^*_w} = gt_wpw?etw??=gtw?
pheth?=gthp_h e^{t^*_h} = gt_hph?eth??=gth?
對(duì)于tx?t_x^*tx??和ty?t_y^*ty??,由于Sigmoid的反函數(shù)不好計(jì)算,我們直接使用σ(tx?)\sigma(t^*_x)σ(tx??)和σ(ty?)\sigma(t^*_y)σ(ty??)作為回歸的目標(biāo)。
dx?=σ(tx?)=gtx?cxd_x^* = \sigma(t^*_x) = gt_x - c_xdx??=σ(tx??)=gtx??cx?
dy?=σ(ty?)=gty?cyd_y^* = \sigma(t^*_y) = gt_y - c_ydy??=σ(ty??)=gty??cy?
tw?=log(gtwpw)t^*_w = log(\frac{gt_w}{p_w})tw??=log(pw?gtw??)
th?=log(gthph)t^*_h = log(\frac{gt_h}{p_h})th??=log(ph?gth??)
如果(tx,ty,th,tw)(t_x, t_y, t_h, t_w)(tx?,ty?,th?,tw?)是網(wǎng)絡(luò)預(yù)測(cè)的輸出值,將(dx?,dy?,tw?,th?)(d_x^*, d_y^*, t_w^*, t_h^*)(dx??,dy??,tw??,th??)作為(σ(tx),σ(ty),th,tw)(\sigma(t_x), \sigma(t_y), t_h, t_w)(σ(tx?),σ(ty?),th?,tw?)的目標(biāo)值,以它們之間的差距作為損失函數(shù),則可以建立起一個(gè)回歸問(wèn)題,通過(guò)學(xué)習(xí)網(wǎng)絡(luò)參數(shù),使得ttt足夠接近t?t^*t?,從而能夠求解出預(yù)測(cè)框的位置。
標(biāo)注錨框包含物體類(lèi)別的標(biāo)簽
對(duì)于objectness=1的錨框,需要確定其具體類(lèi)別。正如上面所說(shuō),objectness標(biāo)注為1的錨框,會(huì)有一個(gè)真實(shí)框跟它對(duì)應(yīng),該錨框所屬物體類(lèi)別,即是其所對(duì)應(yīng)的真實(shí)框包含的物體類(lèi)別。這里使用one-hot向量來(lái)表示類(lèi)別標(biāo)簽label。比如一共有10個(gè)分類(lèi),而真實(shí)框里面包含的物體類(lèi)別是第2類(lèi),則label為(0,1,0,0,0,0,0,0,0,0)(0,1,0,0,0,0,0,0,0,0)(0,1,0,0,0,0,0,0,0,0)
對(duì)上述步驟進(jìn)行總結(jié),標(biāo)注的流程如 圖15 所示。
圖15:標(biāo)注流程示意圖
通過(guò)這種方式,我們?cè)诿總€(gè)小方塊區(qū)域都生成了一系列的錨框作為候選區(qū)域,并且根據(jù)圖片上真實(shí)物體的位置,標(biāo)注出了每個(gè)候選區(qū)域?qū)?yīng)的objectness標(biāo)簽、位置需要調(diào)整的幅度以及包含的物體所屬的類(lèi)別。位置需要調(diào)整的幅度由4個(gè)變量描述(tx,ty,tw,th)(t_x, t_y, t_w, t_h)(tx?,ty?,tw?,th?),objectness標(biāo)簽需要用一個(gè)變量描述objobjobj,描述所屬類(lèi)別的變量長(zhǎng)度等于類(lèi)別數(shù)C。
對(duì)于每個(gè)錨框,模型需要預(yù)測(cè)輸出(tx,ty,tw,th,Pobj,P1,P2,...,PC)(t_x, t_y, t_w, t_h, P_{obj}, P_1, P_2,... , P_C)(tx?,ty?,tw?,th?,Pobj?,P1?,P2?,...,PC?),其中PobjP_{obj}Pobj?是錨框是否包含物體的概率,P1,P2,...,PCP_1, P_2,... , P_CP1?,P2?,...,PC?則是錨框包含的物體屬于每個(gè)類(lèi)別的概率。接下來(lái)讓我們一起學(xué)習(xí)如何通過(guò)卷積神經(jīng)網(wǎng)絡(luò)輸出這樣的預(yù)測(cè)值。
標(biāo)注錨框的具體程序
上面描述了如何對(duì)預(yù)錨框進(jìn)行標(biāo)注,但讀者可能仍然對(duì)里面的細(xì)節(jié)不太了解,下面將通過(guò)具體的程序完成這一步驟。
# 標(biāo)注預(yù)測(cè)框的objectness def get_objectness_label(img, gt_boxes, gt_labels, iou_threshold = 0.7,anchors = [116, 90, 156, 198, 373, 326],num_classes=7, downsample=32):"""img 是輸入的圖像數(shù)據(jù),形狀是[N, C, H, W]gt_boxes,真實(shí)框,維度是[N, 50, 4],其中50是真實(shí)框數(shù)目的上限,當(dāng)圖片中真實(shí)框不足50個(gè)時(shí),不足部分的坐標(biāo)全為0真實(shí)框坐標(biāo)格式是xywh,這里使用相對(duì)值gt_labels,真實(shí)框所屬類(lèi)別,維度是[N, 50]iou_threshold,當(dāng)預(yù)測(cè)框與真實(shí)框的iou大于iou_threshold時(shí)不將其看作是負(fù)樣本anchors,錨框可選的尺寸anchor_masks,通過(guò)與anchors一起確定本層級(jí)的特征圖應(yīng)該選用多大尺寸的錨框num_classes,類(lèi)別數(shù)目downsample,特征圖相對(duì)于輸入網(wǎng)絡(luò)的圖片尺寸變化的比例"""img_shape = img.shapebatchsize = img_shape[0]num_anchors = len(anchors) // 2input_h = img_shape[2]input_w = img_shape[3]# 將輸入圖片劃分成num_rows x num_cols個(gè)小方塊區(qū)域,每個(gè)小方塊的邊長(zhǎng)是 downsample# 計(jì)算一共有多少行小方塊num_rows = input_h // downsample# 計(jì)算一共有多少列小方塊num_cols = input_w // downsamplelabel_objectness = np.zeros([batchsize, num_anchors, num_rows, num_cols])label_classification = np.zeros([batchsize, num_anchors, num_classes, num_rows, num_cols])label_location = np.zeros([batchsize, num_anchors, 4, num_rows, num_cols])scale_location = np.ones([batchsize, num_anchors, num_rows, num_cols])# 對(duì)batchsize進(jìn)行循環(huán),依次處理每張圖片for n in range(batchsize):# 對(duì)圖片上的真實(shí)框進(jìn)行循環(huán),依次找出跟真實(shí)框形狀最匹配的錨框for n_gt in range(len(gt_boxes[n])):gt = gt_boxes[n][n_gt]gt_cls = gt_labels[n][n_gt]gt_center_x = gt[0]gt_center_y = gt[1]gt_width = gt[2]gt_height = gt[3]if (gt_height < 1e-3) or (gt_height < 1e-3):continuei = int(gt_center_y * num_rows)j = int(gt_center_x * num_cols)ious = []for ka in range(num_anchors):bbox1 = [0., 0., float(gt_width), float(gt_height)]anchor_w = anchors[ka * 2]anchor_h = anchors[ka * 2 + 1]bbox2 = [0., 0., anchor_w/float(input_w), anchor_h/float(input_h)]# 計(jì)算iouiou = box_iou_xywh(bbox1, bbox2)ious.append(iou)ious = np.array(ious)inds = np.argsort(ious)k = inds[-1]label_objectness[n, k, i, j] = 1c = gt_clslabel_classification[n, k, c, i, j] = 1.# for those prediction bbox with objectness =1, set label of locationdx_label = gt_center_x * num_cols - jdy_label = gt_center_y * num_rows - idw_label = np.log(gt_width * input_w / anchors[k*2])dh_label = np.log(gt_height * input_h / anchors[k*2 + 1])label_location[n, k, 0, i, j] = dx_labellabel_location[n, k, 1, i, j] = dy_labellabel_location[n, k, 2, i, j] = dw_labellabel_location[n, k, 3, i, j] = dh_label# scale_location用來(lái)調(diào)節(jié)不同尺寸的錨框?qū)p失函數(shù)的貢獻(xiàn),作為加權(quán)系數(shù)和位置損失函數(shù)相乘scale_location[n, k, i, j] = 2.0 - gt_width * gt_height# 目前根據(jù)每張圖片上所有出現(xiàn)過(guò)的gt box,都標(biāo)注出了objectness為正的預(yù)測(cè)框,剩下的預(yù)測(cè)框則默認(rèn)objectness為0# 對(duì)于objectness為1的預(yù)測(cè)框,標(biāo)出了他們所包含的物體類(lèi)別,以及位置回歸的目標(biāo)return label_objectness.astype('float32'), label_location.astype('float32'), label_classification.astype('float32'), \scale_location.astype('float32') # 讀取數(shù)據(jù) reader = multithread_loader('/home/aistudio/work/insects/train', batch_size=2, mode='train') img, gt_boxes, gt_labels, im_shape = next(reader()) # 計(jì)算出錨框?qū)?yīng)的標(biāo)簽 label_objectness, label_location, label_classification, scale_location = get_objectness_label(img, gt_boxes, gt_labels,iou_threshold=0.7,anchors=[116, 90, 156,198, 373, 326],num_classes=7,downsample=32) img.shape, gt_boxes.shape, gt_labels.shape, im_shape.shape ((2, 3, 320, 320), (2, 50, 4), (2, 50), (2, 2)) label_objectness.shape, label_location.shape, label_classification.shape, scale_location.shape ((2, 3, 10, 10), (2, 3, 4, 10, 10), (2, 3, 7, 10, 10), (2, 3, 10, 10))上面的程序?qū)崿F(xiàn)了對(duì)錨框進(jìn)行標(biāo)注,對(duì)于每個(gè)真實(shí)框,選出了與它形狀最匹配的錨框,將其objectness標(biāo)注為1,并且將[dx?,dy?,th?,tw?][d_x^*, d_y^*, t_h^*, t_w^*][dx??,dy??,th??,tw??]作為正樣本位置的標(biāo)簽,真實(shí)框包含的物體類(lèi)別作為錨框的類(lèi)別。而其余的錨框,objectness將被標(biāo)注為0,無(wú)需標(biāo)注出位置和類(lèi)別的標(biāo)簽。
- 注意:這里還遺留一個(gè)小問(wèn)題,前面我們說(shuō)了對(duì)于與真實(shí)框IoU較大的那些錨框,需要將其objectness標(biāo)注為-1,不參與損失函數(shù)的計(jì)算。我們先將這個(gè)問(wèn)題放一放,等到后面建立損失函數(shù)的時(shí)候再補(bǔ)上。
總結(jié)
以上是生活随笔為你收集整理的计算机视觉:单阶段目标检测模型YOLO-V3的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: AI识虫:林业病虫害数据集和数据预处理方
- 下一篇: maskrcnn用于目标检测_用于目标检