Brief
水下目标检测正好在这段时间学习一些二维的检测方法,这一篇记录该比赛的过程。
YOLOV3
一开始还是打算直接使用一些比较经典又比较容易改的网络结构,下面根据此次题目的一些特性,逐步记录该过程。
数据集lable处理
数据
首先是去官网上下载数据集,有 下面两个数据集train.zip
和测试数据集,然后我们需要的是把这个train
解压后放到标准yolo自己创建的文件夹的JPEGImages
下,然后分出交叉验证的数据集,用以下代码:
import os
import random
trainval_percent = 0.1
train_percent = 0.9
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)
ftrainval = open('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/val.txt', 'w')
for i in list:
name = total_xml[i][:-4] + '\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftest.write(name)
else:
fval.write(name)
else:
ftrain.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
label制作
我所使用的yolov3版本是 这个版本,这里的label格式应该是每行5个字段,第一个为类别字段,剩下四个为gt的中心点坐标和长宽值,而官方给出的描述文件如下形式:
<annotation>
<frame>12-10GP02019301</frame>
<object>
<name>holothurian</name>
<bndbox>
<xmin>701</xmin>
<ymin>416</ymin>
<xmax>831</xmax>
<ymax>575</ymax>
</bndbox>
</object>
<object>...</object>
<object>...</object>
<object>...</object>
<object>...</object>
<object>...</object>
</annotation>
因此,我们需要对该标签文件进行代码转化,代码为:
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import cv2
sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
classes = ["holothurian", "echinus", "scallop", "starfish", "waterweeds"]
imgpath='/home/jty/competetation/data/VOC2007/JPEGImages'
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def convert_annotation(year, image_id):
in_file = open('VOC%s/Annotations/%s.xml'%(year, image_id))
out_file = open('VOC%s/labels/%s.txt'%(year, image_id), 'w')
tree=ET.parse(in_file)
root = tree.getroot()
img = cv2.imread(imgpath + "/" + image_id+'.jpg')
w = int(img.shape[1])
h = int(img.shape[0])
for obj in root.iter('object'):
#difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
for year, image_set in sets:
if not os.path.exists('VOC%s/labels/'%(year)):
os.makedirs('VOC%s/labels/'%(year))
image_ids = open('VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
list_file = open('%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
print(image_id)
convert_annotation(year, image_id)
list_file.close()
需要注意的是
执行代码:
python voc_label.py
cat 2007_train.txt 2007_val.txt > train.txt
这样就可以了。会生成yolov3需要的Label形式
代码
代码下载源码:
git clone https://github.com/pjreddie/darknet
修改模式:
cd darknet
vim Makefile #如果使用CPU模式。则不用修改Makefile文件
把该文件的前三行的0都改成1就表示使用GPU
最后
make
一些修改
这里可以直接参考 [博客]()
进行修改就可了。最后运行:
wget https://pjreddie.com/media/files/darknet53.conv.74
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
训练截图:
预测一下:
./darknet detect cfg/yolov3-voc.cfg /home/jty/competetation/yolov3/darknet/backup/yolov3-voc_20000.weights /home/jty/competetation/data/test-A-image/000799.jpg
yolov3 版本2
采用非原作者的darknet,这里采用一个pytorch的版本,原因是python版本的比c版本的好改一点,后续工作容易开展.
train如下:
值得注意的是 pytorch 版本1.3.1是不能成功的,因此修改成了1.2.0
提交效果
没有在Imagenet的预训练的基础上,效果:
0.0效果不是很高,需要很大的改进。
预训练+SE
添加通道增强和imagenet上的预训练模型.
仅仅是添加了imagenet上的预训练的权重值得到的效果并不理想,因此采用9:1的交叉验证方法,队友完成了评价函数。
数据预处理
- 采用
retinex
数据增强算法,首先采用的是单尺度的数据增强。 - 得到的数据质量并不能很明显的提升。QAQ,先试试效果吧
- 采用水下图像质量增强算法
法 直接按照repo中的提示安装,测试: - 提高Loss 权重
根据评价指标,在IOU>0.8的指标时是几乎无法得到分数的,可能需要调整Loss的权重占比 - 数据增广
- “海草类”加入
- IOU LOSS函数
经过多次测试,yolo的精度还是不能突破0.3,所以后续采用RCNN的方法。
Cascade RCNN
这个是大佬给出的baseline,效果是真的不错呀。
预测语句:
CUDA_VISIBLE_DEVICES=1 ./tools/dist_test.sh configs/underwater/cas_r50/cascade_rcnn_r50_fpn_1x.py ./workdirs/cascade_rcnn_r50_fpn_1x/latest.pth 1 --json_out ./results/cas_r50.json
转化为csv
python tools/post_process/json2submit.py --test_json cas_r50.bbox.json --submit_file cas_r50.csv
提交上传:
后续工作
- 增强和数据补充
- 模型融合
- DCN