项目需求+锻炼自己,尝试用yolov2跑自己的数据集,中间遇到了很多问题,记下来防止忘记
一、数据集
首先发现由于物体特殊没有合适的现成的数据集使用,所以只好自己标注,为了减少工作量,先用opencv标记连通域
(环境 ubuntu qt opencv)
在qt中创建console类型工程,需要对test.pro进行如下配置
QT -= gui QT += core CONFIG += c++11 CONFIG += console CONFIG -= app_bundle TARGET = test TEMPLATE = app DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp INCLUDEPATH+=/home/opencv-3.4.4/include /home/opencv-3.4.4/include\opencv /home/opencv-3.4.4/include\opencv2 LIBS+=-L/home/opencv-3.4.4/build/lib -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc
路径按照自己电脑中的路径
头文件也需要注意
1 #include <opencv2/core/core.hpp> 2 #include <opencv2/highgui/highgui.hpp> 3 #include <opencv2/opencv.hpp> 4 #include <iostream> 5 #include <string> 6 #include <stdio.h> 7 using namespace std; 8 using namespace cv;
头文件包含不足够会出现 returned 1 status问题
###接下来对图片处理
首先转为灰度图,接着用floodfill函数,OTSU算法,利用OTSU算法得到的阈值进行二值化处理(具体不再展开)
【用函数threshold,其中type选择THRESH_OTSU】
之后像素反转,因为一般习惯物体(前景)黑色,背景白色
标记连通域可以用函数findcontours 和 drawcontours,并且可以输出代码数量作为参考
1 vector <vector<Point>> contours; 2 findContours(reverseImage, 3 contours, 4 CV_RETR_CCOMP,//外轮廓 5 CV_CHAIN_APPROX_NONE);//存储所有轮廓点 6 7 Mat result(reverseImage.size(),CV_8U,Scalar(255)); 8 drawContours(result, 9 contours, 10 -1,//画所有轮廓 11 Scalar(0),//黑色 12 2); 13 namedWindow("contours"); 14 imshow("contours",result); 15 cout<<"contours:"<<contours.size()<<endl;
为了避免没用的连通域,需要对其进行筛选,其过滤过大过小连通域
1 unsigned int cmin=100; 2 unsigned int cmax=5000; 3 vector<vector<Point>>::const_iterator itc=contours.begin(); 4 while(itc!=contours.end()) 5 { 6 cout<<itc->size()<<endl; 7 if (itc->size() < cmin || itc->size() > cmax) 8 itc=contours.erase(itc); 9 else 10 ++itc; 11 } 12 Mat result_erase(result.size(),CV_8U,Scalar(255)); 13 drawContours(result_erase, 14 contours, 15 -1, 16 Scalar(0), 17 2); 18 19 namedWindow("contours_erase"); 20 imshow("contours_erase",result_erase); 21 cout<<"contours:"<<contours.size()<<endl;
结果如下:
二、数据集准备
复杂的环境下识别连通域并不准确,所以最后还是决定手动标注,用的labelimg,方法非常简单
唯一的技巧可能就是选择自动保存,以及单一标注,标注前后的格式分别是jpg和xml
这是为了和VOC数据集格式相同,便于yolov2识别
需要注意的是如果没有bounding box,那么也没有相应图片的xml,一定要删除照片,否则之后训练时会出现问题
命名格式也可以按照VOC数据集的命名格式
VOC数据集包括三个文件夹,Annotations,ImageSets,JPEGImages,分别放xml,(layout,main,segmentation),jpg
其中main包括train.txt 用来存放照片的名称(无路径,无后缀)
【照片名称写入txt的步骤建议Python】
1 import sys 2 import os 3 import random 4 file_path="/home/yjq/test_image" 5 path_list=os.listdir(file_path) 6 path_name=[] 7 for i in path_list: 8 path_name.append(i.split(".")[0]) 9 10 path_name.sort() 11 12 for file_name in path_name: 13 with open("/home/yjq/image_name.txt","a") as f: 14 f.write(file_name+"\n") 15 f.close()
三、配置yolov2
在darknet/scripts下建立文件夹,名字自取(如:VOCdevkit)
里面放入准备好的数据集
对voc_label.py进行修改
【进入pycharm的bin中,用终端打开,输入 sh ./pycharm.sh 打开py文件】
修改sets 和 classes 其他几乎不用修改,报错再相应修改
(事实上这里错了很多次,比如
修改时如果把sets中的year去掉,下面也要相应修改
路径不要出错)
修改后 cd ./darknet/scripts 进入文件夹后再 python voc_label.py
这时会生成labels文件夹,里面存有xml内容的txt文件,同时还有train.txt,存有图片的绝对路径
四、准备训练
这时距离训练只有几步之遥,仍需要修改几个文件
classes= 2 train = /home/yjq/darknet/scripts/VOCdevkit/train.txt //valid = /home/pjreddie/data/voc/2007_test.txt names = data/voc.names backup = /home/yjq/darknet/results/
五、开始训练
在terminal输入
cd darknet
./darknet detector train cfg/voc.data cfg/yolov2-voc.cfg
就可以开始了
如果出现 cannot load image 问题可能出在train.txt,用notepad打开,确保最后一行只有换行符即可
或者一不小心路径输错也不是没有可能
默认每100 images 会存入results中,可以查看
【在此之前先从github上下载darknet,训练weights,再测试examples】
【希望一切顺利】
【参考:https://blog.csdn.net/hysteric314/article/details/54097845】
原文:https://www.cnblogs.com/yjqjy/p/10446553.html