标签就是网络要学习的东西。
怎么生成标签呢?
首先,需要有数据。
数据包括:图片数据,目标框数据
这个图有两个人一只狗,对应两类三个目标框:
images/87.jpg 0 304 245 140 133 1 97 235 124 153 1 199 156 354 311
怎么把目标框生成YOLOV3的标签呢?
3层循环,第一层循环遍历每种特征图尺寸(13, 26, 52),第二层循环遍历原图的每个目标框(n个),第三层循环遍历对应特征图尺寸的建议框(3个)。每个目标框都和建议框计算iou、中心点偏移率以及宽高偏移率,并把类别的标签做成one_hot形式,全部存入对应特征图上对应点的通道内。
看代码比较简单:
import numpy as np
import math
CLASS_NUM = 2 # 类别数目
IMG_WIDTH = 416 # 图片边长
BOXES = "images/87.jpg 0 304 245 140 133 1 97 235 124 153 1 199 156 354 311" # 目标框数据
# 建议框
ANCHORS_GROUP_KMEANS = {
52: [[10, 13], [16, 30], [33, 23]],
26: [[30, 61], [62, 45], [59, 119]],
13: [[116, 90], [156, 198], [373, 326]]}
# 建议框面积
ANCHORS_GROUP_KMEANS_AREA = {
13: [x * y for x, y in ANCHORS_GROUP_KMEANS[13]],
26: [x * y for x, y in ANCHORS_GROUP_KMEANS[26]],
52: [x * y for x, y in ANCHORS_GROUP_KMEANS[52]],
}
# 定义one_hot函数
def one_hot(cls_num, i):
b = np.zeros(cls_num)
b[i] = 1.
return b
# 定义生成标签函数
def gen_label():
labels = {}
strs = BOXES.split()
_boxes = np.array(list(map(float, strs[1:]))) # 转变数据类型
boxes = np.split(_boxes, len(_boxes) // 5) # 切分成n组,得到n个目标框
for feature_size, anchors in ANCHORS_GROUP_KMEANS.items(): # 遍历3种特征图尺寸
# 对每种特征图尺寸,建一个对应形状的张量用以存放标签
labels[feature_size] = np.zeros(shape=(feature_size, feature_size, 3, 5 + CLASS_NUM))
for box in boxes: # 遍历目标框
cls, cx, cy, w, h = box # 目标类别,中心点坐标x&y, 宽,高
# cx_index:索引,与网格一一对应。cx_offset:中心点相对于网格左上角的偏移率
cx_offset, cx_index = math.modf(cx * feature_size / IMG_WIDTH)
# cfg.IMG_WIDTH / feature_size实际上就是步长
cy_offset, cy_index = math.modf(cy * feature_size / IMG_WIDTH)
for i, anchor in enumerate(anchors): # 遍历3种建议框
anchor_area = ANCHORS_GROUP_KMEANS_AREA[feature_size][i] # 每种特征图对应的3种建议框的面积
p_w, p_h = w / anchor[0], h / anchor[1] # 目标框相对于建议框的偏移率
p_area = w * h # 目标框的面积
iou = min(p_area, anchor_area) / max(p_area, anchor_area) # 小框比大框
# 标签存入对应尺寸特征图对应点的通道内
labels[feature_size][int(cy_index), int(cx_index), i] = np.array(
[iou, cx_offset, cy_offset, np.log(p_w), np.log(p_h), *one_hot(CLASS_NUM, int(cls))])
return labels[13], labels[26], labels[52]
if __name__ == '__main__':
label_13, label_26, label_52 = gen_label()
print(label_13.shape) # (13, 13, 3, 7)