錨框的計算公式
假設原圖的高為H,寬為W
詳細公式推導
以同一個像素點為錨框,可以生成 (n個縮放 + m個寬高比 -1 )個錨框
錨框的作用:
不用直接去預測真實框的四個坐標,而是:
1.先生成多個錨框。
2.預測每個錨框里是否含有要預測的目標。
3.如果是,預測從這個錨框到真實框的偏移(一般是中心點的偏移)。
計算錨框與真實框的IOU
def box_iou(boxes1,boxes2):''':param boxes1: shape = (boxes1的數量,4):param boxes2: shape = (boxes2的數量,4):param areas1: boxes1中每個框的面積 ,shape = (boxes1的數量):param areas2: boxes2中每個框的面積 ,shape = (boxes2的數量):return:'''# 定義一個Lambda函數,輸入boxes,內容是計算得到框的面積box_area = lambda boxes:((boxes[:,2] - boxes[:0]) * (boxes[:3] - boxes[:0]))# 計算面積areas1 = box_area(boxes1)areas2 = box_area(boxes2)# 計算交集 要把所有錨框的左上角坐標 與 真實框的所有左上角坐標 作比較,大的就是交集的左上角 ,加個None 可以讓錨框與所有真實框作對比inter_upperlefts = torch.max(boxes1[:,None,:2],boxes2[:,:2])# 把所有錨框的右下角坐標 與 真實框的所有右下角坐標 作比較,小的就是交集的右下角坐標 ,加個None 可以讓錨框與所有真實框作對比inter_lowerrights = torch.min(boxes1[:,None,2:],boxes2[:,2:])# 如果右下角-左上角有元素小于0,那就說明沒有交集,clamp(min-0)會將每個元素與0比較,小于0的元素將會被替換成0inters = (inter_lowerrights - inter_upperlefts).clamp(min=0) # 得到w和hinter_areas = inters[:,:,0] * inters[:,:,1] # 每個樣本的 w*h# 求錨框與真實框的并集# 將所有錨框與真實框相加,他們會多出來一個交集的面積,所以要減一個交集的面積union_areas = areas1[:,None] * areas2 - inter_areasreturn inter_areas/union_areas
給訓練集標注錨框
每個錨框包含的信息有:每個錨框的類別 和 偏移量。
偏移量指的是:真實邊界相對于錨框的偏移量。
預測時:為每張圖片生成多個錨框,預測所有錨框的類別和偏移量。
舉例
假設有4
個真實框 B1,B2,B3,B4。
9
個錨框A1,A2,A3,A4,A5,A6,A7,A8,A9。
如上,每個真實框都要與所有的錨框計算IOU,如X23,在第三列,擁有最大的IOU,如果該IOU大于閾值,那么第2個錨框的類別就是B3,分配完類別之后,第二個錨框和第3個真實框將不再參與,表現為上面的矩陣去掉第二行第三列。
補充:
訓練集不是光使用標注的真實的框做標簽來訓練嗎?為啥要錨框當做訓練樣本?
應該是擴大訓練集的方式,如果只有一張圖片,上面標注上了一個真實的框,那么就只有一個訓練樣本,如果生成一些錨框,根據真實的框,計算IOU,來給生成的錨框標記上相應的類別和與真實框的中心值偏移量,那么這些錨框也成為了訓練樣本。
lambda匿名函數
它可以用于簡潔地定義一個單行的函數
add = lambda x, y: x + y
print(add(2, 3)) # 輸出結果為 5
torch.max(boxes1[:, None, :2], boxes2[:, :2])
import torch # 定義兩個張量
boxes1 = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) # 形狀為(2, 4)
boxes2 = torch.tensor([[2, 3,4,5], [6, 7,8,9]])
print(boxes1.shape, boxes2.shape)
torch.Size([2, 4]) torch.Size([2, 4])
print(boxes1[:, None, :2])
print(boxes1[:, None, :2].shape)
tensor([[[1, 2]],[[5, 6]]])
torch.Size([2, 1, 2]) 變成了兩個通道,每個通道有個一行兩列的元素
boxes2[:,:2]
tensor([[2, 3],[6, 7]])
print(torch.max(boxes1[:, None, :2], boxes2[:, :2]))
torch.max(boxes1[:, None, :2], boxes2[:, :2]).shape
tensor([[[2, 3],[6, 7]],[[5, 6],[6, 7]]])
torch.Size([2, 2, 2]) 變成兩個通道,每個通道有兩行,每行有兩列的元素
print(torch.max(boxes1[:, :2], boxes2[:, :2]))
tensor([[2, 3],[6, 7]])