兩個名詞:目標的真實邊界(ground_truth bounding box)。而以畫素為中心生成多個大小和寬高比(aspect ratio)的邊界框,稱為anchor box。
基於深度學習的目標檢測不使用傳統的滑窗生成所有的視窗作為候選區域,fasterrcnn提出的rpn網路,處理較少但準確的候選區域。錨框即可理解為某個檢測點處的候選區域。
假設影象高\(h\),寬為\(w\)。以每個畫素為中心,大小\(s \in (0,1]\),寬高比\(r \gt 0\)。那麼錨框的寬為\(ws\sqrt\),高為\(\frac}\)。(設錨框寬高為\(x\)和\(y\)。面積\(xy=s^2\),比例\(x/y=r\),計算出來\(x=s*\sqrt~~,y=\frac}\),這裡的計算出的都是歸一化後的寬度和高度是相對原圖,因此各自乘以原影象寬度和高度。)。
設定一組大小和寬高比,\(s_1,...s_n\)和\(r_1,....r_m\)。顯然有\(mn\)種組合,影象有\(wh\)個畫素點,那麼一共有\(whmn\)個錨框。數量太多,只關注含有\(r1\)和\(s1\)的框。即組合是\((s_1,r_k)\)和\((s_k,r_1)\),一共\(n+m-1\)個框。
一幅影象生成的anchor存放在乙個陣列裡面,尺寸是(寬,高,anchor個數,4),弄成這種尺寸是便於視覺化,如果知道某個畫素點的所有anchor座標,直接索引訪問即可。
def multiboxprior(featuremap, sizes=[0.75,0.5,0.25], ratios=[1,2,0.5]):
# 生成anchor表示為 xmin ymin xmax ymax
pairs =
# 組合配對m+n-1個錨框 後續使用根號r較多,因此這裡直接開根號了
for r in ratios:
for s in sizes[1:]:
# pairs是每一組anchor的設定
# 對於(s,r)的錨框,對應的寬高是ws*sqrt(r)和hs/sqrt(r)
# 返回的錨框變數y的形狀(寬,高,以相同畫素為中心的框個數,4) y[100,100,0,:]即為(100,100)畫素位置第乙個錨框座標
pairs = np.array(pairs)
# 錨框的相對寬高 s*根號r 和 s/根號r
x = pairs[:, 0] * pairs[:, 1] # s*根號r
y = pairs[:, 0] / pairs[:, 1] # s/根號r
# 以畫素點為中心,兩邊的偏移量
# 上面的x y 是anchor的寬高,下面計算的是兩邊的偏移,因此除以了2
# base_anchors 中心點(0,0) 錨框的對角座標,相對偏移
# 如果中心畫素座標(i,j) 那麼點應該是(i-x,j-y,i+x,j+y)
# base_anchors每一行就是一種錨框相對中心的偏移量 -x -y +x +y
base_anchors = np.stack([-x, -y, x, y], axis=1) / 2
#print(base_anchors)
h,w = featuremap.shape[-2:] # 特徵圖的寬高,特徵圖尺寸nchw
# anchor_boxes尺寸如下 每乙個點要有len(pairs)個錨框
anchor_boxs = np.zeros(shape=(h,w,len(pairs),4))
for i in range(h):
for j in range(w):
# 這一步是複製中心點座標,生成多行。。便於後面與base_anchors相加
xx = [i / w ]*len(pairs)
yy = [j / h]*len(pairs)
# 中心點的座標 就是(i,j) 歸一化到[0,1]
center_ = np.stack([xx, yy, xx, yy],axis=1)
a = center_ + base_anchors
anchor_boxs[i,j,:,:] = a
return anchor_boxs
生成anchor的**如上,原理是遍歷訪問每乙個畫素點,將畫素座標與anchor的相對偏移座標加起來就行。for迴圈效率有點低,但很好理解。對每一組(s,r)計算base_anchor,即相對中心點的偏移,如圖所示。那麼對於每乙個畫素點,它的anchor,直接就是畫素座標加上對應偏移即可
這樣計算出來的anchor是相對座標。還原到原圖的畫素座標,只需要乘以寬或高即可。
實際上可以用numpy操作, 這個文章裡的實現更簡潔。
顯示某個畫素點處的anchor如下。
def show_box(img,bbox,x,y):
# 這裡為了方便。。img是cv2讀取的
boxes = bbox[x,y,:,:] # 獲取畫素座標(x,y)處的anchor
h, w = img.shape[0], img.shape[1]
for box in boxes:
# 左上的座標
top_x = int(box[0]*w)
top_y = int(box[1]*h )
# 右下的座標
bottom_x = int(box[2]*w)
bottom_y = int(box[3]*h)
# 防止越界處理一下。。
top_x = 0 if top_x < 0 else top_x
top_y = 0 if top_y <0 else top_y
bottom_x = w if bottom_x > w else bottom_x
bottom_y = h if bottom_y > h else bottom_y
cv2.rectangle(img,(top_x,top_y),(bottom_x,bottom_y),(255,0,0),2)
return img
最後,測試一張,繪製某點的anchor。
# 綠色框標註一下要測試的那個畫素點(155,120)處
cv2.rectangle(tmp,(150,120),(155,125),(0,255,0),3)
# multiboxprior輸入的是nchw格式。這裡只有一張圖,是hwc,交換一下。
目標檢測中的Anchor
前言 在計算機視覺四大基本任務 檢測 分類 定位 分割 中,影象的目標檢測受到的了研究者們越來越多的關注。今天我們就來聊一聊在目標檢測中一項重要的機制 anchor。anchor機制在凱明大神提出的faster rcnn 2015年提出 時興起。下面將從三方面來敘述anchor.目錄1.什麼是anc...
目標檢測 目標檢測通用框架總結
目標檢測框架個人總結 以下是筆記中包含的內容 目標檢測網路框架總結 yolov4中有圖 從最開始的神經網路到現在深度更深,模組更多的目標檢測深度學習神經網路,如今大致可以分為two stage detector 典型的為rcnn系列 和 one stage detector 典型為yolo系列 每個...
SSD目標檢測之預設框的生成 Python
ssd物體檢測 arxiv1512.02325 ssd作為較新出現的物體檢測演算法,擁有網路搭建簡單 無需細節調參的優秀特點。其不僅用於物體檢測,還可應用於文字檢測任務。近期實現的textbox arxiv1611.06779 文字檢測借鑑了ssd的default boxes。雖然演算法不難理解,但...