Yolov3通过k-means聚类得到自己数据的anchors

本文代码参考:
https://github.com/lars76/kmeans-anchor-boxes

Yolov3中默认的9个anchors是作者通过对voc数据聚类得到的。

anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319

不过,当我们训练自己的数据时,如果也采用默认的anchors,可能就不太适合了,
这里我们需要对自己的数据重新做聚类,得到适合自己数据的anchors。

本文聚类的数据是VOC2012里面的person类别数据,关于数据抽取,可以参考我上一篇博客:
https://blog.csdn.net/c2250645962/article/details/104840953

代码如下:

import glob
import xml.etree.ElementTree as ET

import numpy as np

from kmeans import kmeans, avg_iou

ANNOTATIONS_PATH = "./VOCPerson/Annotations"
CLUSTERS = 9

def load_dataset(path):
	dataset = []
	for xml_file in glob.glob("{}/*xml".format(path)):
		# print(xml_file)
		tree = ET.parse(xml_file)

		height = int(tree.findtext("./size/height"))
		width = int(tree.findtext("./size/width"))

		for obj in tree.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

			dataset.append([xmax - xmin, ymax - ymin])

	return np.array(dataset)


data = load_dataset(ANNOTATIONS_PATH)
print('data shape is {}'.format(data.shape))
out = kmeans(data, k=CLUSTERS)

yolov3clusters = [[10,13],[16,30],[33,23],[30,61],[62,45],[59,119],[116,90],[156,198],[373,326]]
yolov3out= np.array(yolov3clusters)/416.0

print("self data Accuracy: {:.2f}%".format(avg_iou(data, out) * 100))
print("yolov3 Accuracy: {:.2f}%".format(avg_iou(data, yolov3out) * 100))
# 生成resize到416对应的anchor
print("Boxes:\n {}-{}".format(out[:, 0]*416, out[:, 1]*416))
# print("Boxes:\n {}".format(out))

ratios = np.around(out[:, 0] / out[:, 1], decimals=2).tolist()
print("Ratios:\n {}".format(sorted(ratios)))

注意代码中的

yolov3clusters = [[10,13],[16,30],[33,23],[30,61],[62,45],[59,119],[116,90],[156,198],[373,326]]
yolov3out= np.array(yolov3clusters)/416.0

这两行是拿yolov3默认的9个anchors出来,为了后面跟自己聚类得到的anchors做计算avg_iou比较。

只需要改变ANNOTATIONS_PATH = "./VOCPerson/Annotations"为自己数据的标注文件路径即可。
我这里的标注文件如下图:
Yolov3通过k-means聚类得到自己数据的anchors_第1张图片

运行结果如下:

data shape is (14470, 2)
self data Accuracy: 71.85%
yolov3 Accuracy: 60.80%
Boxes:
 [ 24.128  12.48   92.352 213.824 107.328  42.432 143.104 342.784  58.24 ]-[ 61.01333333  29.952      270.67733333 332.8        159.744
 108.71466667 289.536      382.13953488 193.63363363]
Ratios:
 [0.3, 0.34, 0.39, 0.4, 0.42, 0.49, 0.64, 0.67, 0.9]

由结果可以看出,使用yolov3默认的9个anchors计算得到的平均iou是60.80%,
而自己聚类得到的9个anchors计算得到的平均iou是71.85%。

9个anchor取整分别是(24,61),(13,30),(92,271),(214,333),(107,160),(42,108),(143,290),(343,382),(58,193)

对他们排序,然后得到用于替换原来默认anchors如下:

anchors = 13,3024,6142,10858,19392271107,160143,290214,333343,382 

那么,使用自己聚类得到的anchors去训练效果应该会更好。

将聚类得到的9个anchors,按照大小排列替代yolov3的cfg文件中的9个anchors即可。

你可能感兴趣的:(深度学习)