飞机检测之practise_YOLOv2

YOLOv2检测飞机

数据(.xml和.jpg):IMPORT>exercises_data>airplaneDetec
代码(配置权重等简单文件):github.com/EchoIR/airplaneDetec

飞机序号:1001-2000(训练集),2206-2400(测试集合)

如果对YOLO感兴趣,可以跳墙去访问这个论坛,YOLO作者会亲自答疑:groups.google.com/forum/#!forum/darknet

1、官网pjreddie.com/darknet/yolo/
2、blog.csdn.net/syoung9029/article/details/55806450(主体)
3、blog.csdn.net/hysteric314/article/details/54097845(结合,改源码部分不需要了,若按照这部分去修改,训练,最后会出现问题)
4、www.jianshu.com/p/c1a009385f59(结合)
5、www.itdadao.com/articles/c15a1240673p0.html(参考其对.cfg文件的修改)

注意点:

YOLO本身使用的是VOC的数据集,所以可以按照VOC数据集的架构来构建自己的数据集。因为源码当中包含了一些数据路径的问题,目前看到的是每张图片对应的标签txt文件的路径,如下yolo.c中:

char labelpath[4096];
find_replace(path, "images", "labels", labelpath);
find_replace(labelpath, "JPEGImages", "labels", labelpath);
find_replace(labelpath, ".jpg", ".txt", labelpath);
find_replace(labelpath, ".JPEG", ".txt", labelpath);

以这种方式去寻找对应的txt文件的,也就是图片的文件夹必须是 JPEGImages 文件夹,那些txt文件必须存放在与 JPEGImages文件夹同路径下的labels文件夹下的。

准备数据

图,xml注释文件,路径的txt文件,每张图的txt文件:

 1、准备一个数据文件夹MyData
 2、jpg图片以序号命名,i.e., 0001.jpg,0002.jpg等,放在MyData下面的JPEGImages文件夹
 3、LableImage标记,这样xml文件也会以图像名命名,至于xml中包含的图片路径则无关紧要(Annotations文件夹),其中0//表示目标是否难以识别。
 4、train.txt, val.txt(其中只包含图片的名字,没有后缀名,creat_list.py)
 5、infrared_train.txt与infrared_val.txt(voc_label_change.py,同时在labels文件夹下每张图生成一个txt文件,其中一个框对应一行,包含类别(0对应第一类)以及中心点的坐标,还有长宽,注意都是归一化到[0,1]之间的,存于labels文件夹),两个python代码文件看懂了,没啥东西。

其实,最后就是三个,一是图像,二是找到图像的txt文件,三是可识别的标记信息(labels中的txt文件,xml也是为此)

注意:确定的是,我这里图片大小不一样,VOC的原始好像也不一样,可能在输入网络之前处理了还是啥的

训练

1、改网络设置,.cfg文件(应该跟caffe中的prototxt文件是一个意思),此处用到的是yolo-voc.cfg

/home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg

height=416#训练的时候的图片大小
width=416
batch= 4 #1 设置太大容易内存溢出,如果你的内存太小,运行出错的话,可以把这两个值(batch,subdivisions)改小一点,batch应该就是网络进行一次训练的batch,subdivisions应该是一次性load进多少这个样的batch.
learning_rate=0.0001          学习率大了容易发散
max_batches = 16000            训练集1千张图片,每张图学60次左

[convolutional]#这一部分,对照这网络结构看了,是一致的

size=1
stride=1
pad=1
filters=30//修改最后一层卷积层核参数个数,计算公式是依旧自己数据的类别数filter=num×(classes + coords + 1)=5×(1+4+1)=30
activation=linear

[region] #blog.csdn.net/xiaoye5606/article/details/72845051中有对参数的理解
anchors = 1.08,1.19, 3.42,4.41, 6.63,11.38, 9.42,5.11, 16.62,10.52
bias_match=1
classes=1 #类别数,本例为1类
coords=4 #BoundingBox的tx,ty,tw,th,tx与ty是相对于左上角的gird,同时是当前grid的比例,tw与th是宽度与高度取对数
num=5 #每个grid预测的BoundingBox个数
softmax=1
jitter=.3
rescore=1
...
random=1#最后一行的random,是一个开关。如果设置为1的话,就是在训练的时候每一batch图片会随便改成320-640(32整倍数)大小的图片。目的和上面的色度,曝光度等一样。如果设置为0的话,所有图片就只修改成默认的大小 416*416

batch=32,subdivisions=4:

飞机检测之practise_YOLOv2_第1张图片

2、voc.names: 仅写上airplane并保存
3、voc.data:

classes= 1
train  = /home/echo/EXERCISEs/airplaneDetec/infrared_train.txt
valid  = /home/echo/EXERCISEs/airplaneDetec/infrared_val.txt
names = /home/echo/EXERCISEs/airplaneDetec/voc.names
backup = /home/echo/EXERCISEs/airplaneDetec/backup #注意,backup文件夹事先得建立好

ps:yolo v1中这些细节是直接在源代码的yolo.c中修改的,源代码如下

飞机检测之practise_YOLOv2_第2张图片

v1往往需要更改源码,比如这里的类别,训练样本的路径文件和模型保存路径均在此指定,修改后从新编译。而yolov2似乎摈弃了这种做法,所以训练的命令也与v1版本的不一样。

4、对于源文件的修改:

(1)detector.c中关于多少次保存一次中间模型 
(2)image.c中void draw_detections()可以修改展示画的框的大小之类的,粗细 
(3)全部完成之后,重新进行编译,make -j8

此处,我个人认为darknet19_448.conv.23是针对imageNet的1000类对象的识别网络,是否可以基于此刻的权重再进行只对飞机的识别训练,然后再训练检测网络???(算了,看了人家的貌似都是基于此去微调的,那我就微调吧)

我这边介于我的图片大小一般都是256*256大小的,所以把网络中参数改成了288*288,batch改成了4,max_batches = 16000 #80200,这样最后算下来,大概又60。我用的网络是: darknet19.conv.23,自己生成预训练模型的前23层的权重,partial命令可以分割权重文件,fine-tune的时候也会用到:

./darknet partial cfg/darknet19.cfg darknet19.weights darknet19.conv.23 23

或者下载人家生成的darknet19.conv.23.注意:以上我利用的只是人家训练好的分类的网络,后面会根据我的检测类别数等去增加相应检测的部分,我估计微调并不能基于别人检测的全部网络,只能是前面分类的部分,因为由于检测类别数目等不的一样,检测网络可能不一样,SSD同样如此。YOLOv2从这里可以看出:

filters=30//修改最后一层卷积层核参数个数,计算公式是依旧自己数据的类别数filter=num×(classes + coords + 1)=5×(1+4+1)=30 
$./darknet detector train /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg darknet19.conv.23

训练至1000测试:

./darknet detector test /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_final.weights /home/echo/EXERCISEs/airplaneDetec/1994.jpg 

这样训练是可以的,继续训练:

./darknet detector train /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_final.weights 2>1 | tee paul_train_log.txt

2>1表示将标准错误输出到标准输出中 

tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。

但是这里注意的是,我之前断在中间的目的是看看训练出的模型是否可以正常使用,若使用txt文件记录训练信息,还是从头开始训练的好,否则txt文件中的训练信息只能是从半途训练的那里开始喽!

还要注意的是改yolo.c与detector.c代码,使得其中不要输出”yolo-paul Learning Rate: 1e-05, Momentum: 0.9, Decay: 0.0005”以及“resizeing dim”之类

测试图片:
测试视频:

./darknet detector demo /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_final.weights data/video.avi

损失函数曲线: 

1、日志文件里有:Resizing  576之类的,就是训练检测的时候,进行的多尺度的训练288-608貌似,每10patches,做一下resize去训练。

使用train_loss_visualization.py脚本可以绘制loss变化曲线:www.itdadao.com/articles/c15a1240673p0.html

./darknet detector train cfg/paul.data cfg/yolo-paul.cfg yolo-paul_800.conv.23 2>1 | tee paul_train_log.txt

算了,我这里不方便展示,因为我不仅仅是记录了前面两行:

yolo-paulLearning Rate: 1e-05, Momentum: 0.9, Decay: 0.0005

中间还有很多的resizing xx,以后训练的时候主要该代码,不要展示出来

评估性能:

www.itdadao.com/articles/c15a1240673p0.html
blog.csdn.net/hysteric314/article/details/54097845

./darknet detector recall /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_final.weights

需要注意的是,在使用这个指令之前,我先修改一下src/detector.c 这一函数:

 (1)修改阈值:float thresh = .25;//函数validate_detector_recall,默认的值是.001,这个默认值设的很小,会让系统识别出更多的框来,导致proposals值激增,还会让recall值变高。最终我改成了 .25。
 (2)修改验证集路径: list *plist = get_paths("/home/echo/EXERCISEs/airplaneDetec/infrared_val.txt");
 (3)重新编译然后执行命令:

./darknet detector recall /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_final.weights

 ID:  192 Correct:  577 Total:  910RPs/Img: 3.93IOU: 51.77%Recall:63.41%proposals:  758Precision:76.12%
ID:  193 Correct:  578 Total:  912RPs/Img: 3.92IOU: 51.77%Recall:63.38%proposals:  760Precision:76.05% 
ID:  194 Correct:  578 Total:  916RPs/Img: 3.91IOU: 51.65%Recall:63.10%proposals:  762Precision:75.85% 

Correct :可以理解为正确地画了多少个框,遍历每张图片的Ground Truth,网络会预测出很多的框,对每一Groud Truth框与所有预测出的框计算IoU,在所有IoU中找一个最大值,如果最大值超过一个预设的阈值,则correct加一。

Total:一共有多少个Groud Truth框。Rps/img:p 代表proposals, r 代表region。 意思就是平均下来每个图片会有预测出多少个框。预测框的决定条件是,预测某一类的概率大于阈值。在validation_yolo_recall函数中,默认的这一个阈值是0.001,这一阈值设置的比较低,这就会导致会预测出很多个框,但是这样做是可以提升recall的值,一般yolo用于画框的默认值是.25,使用这个阈值会让画出来的框比较准确。而validation_yolo_recall使用的阈值改成。25的时候

Rps/img 值会降低,recall的值会降低,所以validation_yolo_recall默认使用一个较低的阈值,有可能作者的目的就是为了提高recall值,想在某种程度上体现网络的识别精度比较高。

IoU、Recall、Precision:解释起来比较麻烦,请看我的博客有详细说明: blog.csdn.net/hysteric314/article/details/54093734

%----------------------至此,完成基本训练,效果不是特别好----------------------------------

效果分析:

1. 将所有验证集图片的检测结果存在文件夹results下面:

代码见dete_all.sh:github.com/EchoIR/airplaneDetec/tree/yolov2_crop,稍微改写一下就好了

(1)1792*1280 
(2)目标过小 
(3)靠的很近的 
(4)周边有点像的轮廓

现在我的想法: 
这个目前还没有具体做,先去试试SSD

后面我修改了部分飞机的框,继续之前的再训一下试试(注意:此刻我改一下损失函数的要求,不输出resizing之类的,方便画曲线):

重新生成txt文件以及更改原来max_batches双倍,因为 yolo-voc_finalv1.weights中包含训练到多少次的信息应该,会不去训练。

./darknet detector train /home/echo/EXERCISEs/airplaneDetec/voc.data /home/echo/EXERCISEs/airplaneDetec/yolo-voc.cfg /home/echo/EXERCISEs/airplaneDetec/backup/yolo-voc_finalv1.weights 2>1 | tee paul_train_logv1.txt

结果:

0.67%proposals:  869Precision:73.76%
ID:  192 Correct:  644 Total:  915RPs/Img: 4.52IOU: 56.78%Recall:70.38%proposals:  873Precision:73.77%
ID:  193 Correct:  646 Total:  917RPs/Img: 4.51IOU: 56.80%Recall:70.45%proposals:  875Precision:73.83%
ID:  194 Correct:  647 Total:  921RPs/Img: 4.50IOU: 56.69%Recall:70.25%proposals:  877Precision:73.77% 

貌似更好一点,看看cost曲线:

这边我的又跟人家的不一样了,好像没法画曲线,去看输出的这些到底是啥

Loaded: 0.000027 seconds
Region Avg IOU: 0.661700, Class: 1.000000, Obj: 0.639071, No Obj: 0.005527, Avg
Recall: 0.750000,  count: 8 16001: 4.816259, 4.816259 avg, 0.000100 rate, 0.116868 seconds, 64004 images
Loaded: 0.000021 seconds
Region Avg IOU: 0.800858, Class: 1.000000, Obj: 0.724595, No Obj: 0.004369, Avg
Recall: 1.000000,  count: 8 16002: 1.480956, 4.482729 avg, 0.000100 rate, 0.235721 seconds, 64008 images
16002:第多少batch  1.480956: loss  4.482729 :  avg loss(貌似这里吧有一个计算公式)  0.000100:学习率  64008:训练到第多少图片
至于train_loss_visualization.py画损失函数,已经解决,看来训练得还不够好%



如下补充一些./darknet之类的命令:

./darknet detect cfg/yolo.cfg yolo.weights data/dog.jpg


#yolo.cfg:网络构建,以及训练的学习率等参数
实际上是如下的缩写:

./darknet detector test cfg/coco.data cfg/yolo.cfg yolo.weights data/dog.jpgcoco.data

里面有类别,以及各类的名称等等

8、评估性能:

 ./darknet detector recall cfg/voc.data cfg/yolo_voc.cfg backup/yolo_voc_final.weights

先解读一下官网的各个文件,知道是如何调用的:

其中VOCdevkit/VOC2007/ImageSets/Main/下的各个txt文件存的是:图片名 -1/1(1表示该类出现在该图片中,-1表示没有),_trainval.txt是_train.txt与val_txt放在一起的。

voc_label.py中所需文件:是train.txt以及val.txt中存的图片的序号
voc_label.py最后生成的文件:

路径文件以及 a .txt file for each image with a line for each ground truth object in the image that looks like:——》这些文件存放在labels文件夹中

voc_label.py解读很简单

然后修改voc.data进行训练,一下步骤很简单,到这里,我咋感觉以上的博客改源码是不对的呢,我得看看各个参数如何调用的:

./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23

训完,模型保存在backup中。

简单测一张图:

./darknet detector test cfg/voc.data cfg/yolo-voc.cfg backup/yolo-voc_final.weights data/dog.jpg

可是效果好差,太差了呀!!!

假设自己训练特征提取模型的话,跑到DarkNet的ImageNet Classification网址pjreddie.com/darknet/imagenet/#darknet19_448

./darknet classifier predict cfg/imagenet1k.data cfg/extraction.cfg extraction.weights data/dog.jpg

输出top5:

Loading weights from weights/extraction.weights...Done!
data/dog.jpg: Predicted in 0.007347 seconds.
26.44%: malamute
17.46%: Eskimo dog
15.82%: Siberian husky
3.64%: dogsled
1.82%: German shepherd

网址中有好几个特征提取模型

这边用于检测的图像大小不一影响不大,但是用于分类的图片大小不一,如何???

你可能感兴趣的:(飞机检测之practise_YOLOv2)