文档说明
该文档包括对 yolov3 代码进行修改,使得神经网络只检测单类物品、使用 yolov3 训练自己
的数据集、裁剪检测目标三部分的内容。相关注意事项在最后已经标红。
只检测 person
1、 修改源代码:
#修改成 1
cd darknet
cd cfg
vim coco.data 并作如下修改:
classes= 1
train = /home/pjreddie/data/coco/trainvalno5k.txt
valid = coco_testdev
#valid = data/coco_val_5k.list
names = data/coco.names
backup = /home/pjreddie/backup/
原因:在 coco.c 中定义的标签,人为第一个,所以改为 1.
返回上一级目录:
cd examples
vim detector.c
void test_detector(char *datacfg, char *cfgfile, char weightfile, char filename, float
thresh)函数中
draw_detections(im, l.wl.hl.n, thresh, boxes, probs, names, alphabet, 1); //最后一个参
数修改成 1。line=481
void run_detector(int argc, char **argv)//该函数中,倒数第三行.line=542
int classes = option_find_int(options, “classes”, 1);//最后一个参数修改成 1
返回上一级目录
2、 重新编译代码
Make clean
Make
3、 测试
./darknet detect cfg/yolov3.cfg yolov3.weights data/此处为检测的文件名
检测之后发现只有人被检测出来了。
Yolov3 训练自己的数据
1. 修改 yolov3-voc.cfg 文件
将文件开头的数据 test 下边两行注释,打开 train 下边的两行。
进入 yolov3/darknet/cfg 文件夹, 使用 vim 修改 yolov3-voc.cfg 文件,修改的
参数共 6 个,3 个 classes 数量, 3 个 filters 参数:
yolov3-voc.cfg 参数修改说明图如图 1 下所示:
图 1
yolov3-voc.cfg 参数修改说明图
需要修改的地方如上所示,具体为[yolo]这个符号出现之处的 classes 参
数改为自己所需要的训练数据种类,然后将上边的 filters 参数修改为 3*(标签
种类数目+5),我这里是三类所以修改为 24.
具有上述形式的地方共三处。
2.创建.data 文件输入相关参数:(名字可以随便取例如 our.data)
这一部分仍然在 cfg 文件夹下进行,修改示例如下图 2 所示:
图 2 .data 文件示例图
这个文件用于配置训练时使用的参数,classes 表示标签种类;
train 存训练数据的.txt 文件
valid 是验证数据的存储文件
names 是 voc.names 的地址,这个也可以不用修改
backup 是保存训练模型的地址,这个不用修改
3.修改 voc.names 文件
这个文件在 yolov3/darknet/data 文件夹下:
修改后的示例图如下图 3 所示
图 3 voc.names 修改示例图
该文件用于保存标签的名字,就是自己训练过程中标签种类名,一行一个必
须换行写。
4.下载文件 darknet53.conv.74
wget https://pjreddie.com/media/files/darknet53.conv.74
5、上传自己的数据集和图片到上边的 our.data 里边参数设置的位置,包括图
片数据集和 txt 文件。
6、训练神经网络:
./darknet detector train cfg/our.data cfg/yolov3-voc.cfg darknet53.conv.74
0,2,3
-gpus
Yolov3 裁剪所检测到的目标
1、image.h 中加入函数声明
void save_cut_image(int px, int py, int ph, int pw, int no, image m_img, char
**names, float cut_pro, int the_class);
2. image.c 中加入如下函数定义
void save_cut_image(int px, int py, int ph, int pw, int no, image m_img, char **names,
float cut_pro, int the_class)
{
image copy = copy_image(m_img);
if (m_img.c == 3) rgbgr_image(copy);
int x, y, k;
char buff[256];
sprintf(buff, "results//%s%.0f%%%d.jpg", names[the_class], cut_pro, no);
printf(" cut_class
:%s
...........cut_class:%.0f ", names[the_class], cut_pro);
printf(names[the_class]);
printf("%f",cut_pro);
IplImage *disp = cvCreateImage(cvSize(m_img.w, m_img.h), IPL_DEPTH_8U,
m_img.c);
int step = disp->widthStep;
for (y = 0; y < m_img.h; ++y) {
for (x = 0; x < m_img.w; ++x) {
for (k = 0; k < m_img.c; ++k) {
disp->imageData[y*step
+
x*m_img.c
+
k]
=
(unsigned
char)(get_pixel(copy, x, y, k) * 255);
}
}
}
CvMat *pMat = cvCreateMatHeader(m_img.w, m_img.h, IPL_DEPTH_8U);
CvRect rect = cvRect(px, py, pw, ph);
cvGetSubRect(disp, pMat, rect);
IplImage *pSubImg = cvCreateImage(cvSize(pw, ph),
IPL_DEPTH_8U,
m_img.c);
cvGetImage(pMat, pSubImg);
cvSaveImage(buff, pSubImg, 0);
free_image(copy);
}
3. 在 image.c 的 void draw_detections(image im, detection *dets, int num, float
thresh, char **names, image **alphabet, int classes)函数中:
draw_box_width(im, left, top, right, bot, width, red, green, blue);前一行插入如下代
码:
int the_class = class;
float cut_pro = dets[i].prob[class];
printf("cut_class
:%s
...........class_pro:%.0f \n", names[the_class],
cut_pro);
int pre_x = left;
int pre_y = top;
int pre_h = bot - top;
int pre_w = right - left;
save_cut_image(pre_x, pre_y, pre_h, pre_w, i, im, names, cut_pro,
the_class);*/
printf("/************
cut and save over *****************/ \n");
输入图片进行测试就可以看到 results 文件夹下裁剪出来目标。
注意事项
1、 修改了.c 文件之后都需要 yolov3/darknet 下重新 make 编译
2、 如果要用到 opencv 或者 GPU 需要将 Makefile 文件的参数进行修改,具体修
改结果如下图 a 所示:
图 a Makefile 文件修改示意图
3.yolo 官网:http://pjreddie.com/yolo/可以下载代码,官网也有相关说明。