(该方法,本人亲测有效)
正题开始:
小目标检测为什么难?
1、小目标通用的定义来自 COCO 数据集,定义小于 32x32 pix 的为小目标。但是实际项目里目标尺寸可能比这个更小
2、图像上小目标数目过多。由于小目标本身分辨率低,图像模糊,携带的信息少。由此所导致特征表达能力弱,小目标的像素点越少,目标图片经过卷积后的特征就更少了,那么用于目标检测和分类的特征就更少了。
3、在网络卷积核确定的情况下,随着网络层数的增加,单个高层特征反应原始图片像素的范围就越大,视野就越宽,高层信息越是能够反应原始图片中物体的宏观轮廓。随着网络层数的增加和感受野的变大,微观的信息就会丢失, 这样对于小目标的信息就会聚合到一个点,小目标原本包含的像素就少,随着感受野的增加,聚合后的特征就更少了,比如1010像素的小目标,经过卷积后的特征可能就只有11,甚至出现多个10*10像素的小目标,经过多次卷积核,合并成了一个特征。这样,小目标就无法识别。
小目标解决方法
首先是数据的预处理,大图切成小图,(怎么切,或者根据框去切图,或者根据图像切片去切图,千万别把小目标给抠出来了,你是做检测算法,又不是用来分类)再划分数据集:
# -*- coding: utf-8 -*
import xml.etree.ElementTree as ET
import cv2
import os
import copy
def crop_img(img_path,xml_path,img_save_path,xml_save_path):
i =000
if not os.path.exists(img_save_path):
os.mkdir(img_save_path)
if not os.path.exists(xml_save_path):
os.mkdir(xml_save_path)
for file in os.listdir(img_path):
_img_path = img_path + "/" + str(file)
# _xml_path = xml_path + "/" + str(file.split(".")[0] + ".xml")
_xml_path = xml_path + "/" + str(file[:-4] + ".xml")
img = cv2.imread(_img_path)
print(img.shape)
tree = ET.parse(_xml_path)
root = tree.getroot()
person_list = []
for child in root:
if child.tag == "object":
if child[0].text == "my_object_name":
xmin1 = int(child[2][0].text)
ymin1 = int(child[2][1].text)
xmax1 = int(child[2][2].text)
ymax1 = int(child[2][3].text)
b_w=int(xmax1-xmin1)*0.1
b_h = int(ymax1 - ymin1) * 0.1
xmin=int(xmin1-b_w)
xmax=int(xmax1+b_w)
ymin = int(ymin1 - b_h)
ymax = int(ymax1 + b_h)
if xmin<0:xmin=0
else:xmin=xmin
if xmax>img.shape[1]:xmax=img.shape[1]
else:xmax=xmax
if ymin<0:ymin=0
else:ymin=ymin
if ymax>img.shape[0]:ymax=img.shape[0]
else:ymax=ymax
if (ymax-ymin)*(xmax-xmin) >= 30000