前言
目前基于深度学习的目标检测越来越火,其准确度很高。笔者采用Yolo-v3实现目标检测。Yolo-v3基于darknet框架,该框架采用纯c语言,不依赖来其他第三方库,相对于caffe框架在易用性对开发者友好(笔者编译过数次caffe才成功)。本文基于windows平台将yolo-v3编译为动态链接库dll,测试其检测性能。
New, python接口的YOLO-v3, !!!, 走过不要错过
为了方便测试,本人将测试通过的Visual Studio工程贴出来
Yolov3-windows测试工程
链接:https://pan.baidu.com/s/1i6ZK2ZCGzWbfWT1-_fUTzg
提取码:rj9o
复制这段内容后打开百度网盘手机App,操作更方便哦
image.png
开发环境
windows 10 x64
Visual Studio 2017
opencv3.4.0
动态链接库.dll的编译过程就不再赘述,相信熟悉C++,编译过opencv的小伙伴都很容易,本文测试使用的的cpu-only版本,笔者编译过cpu-only, gpu两个版本的yolo-v3 dll,需要dll的请点赞支持哦。
Yolo-v3
代码 C++,opencv
需要的文件可以在darknet链接下载打到:
yolov3.cfg,yolov3的网络结构描述文件
yolov3.weights,yolov3训练好的权重文件,在coco数据集上训练的
coco.names, coco数据集的目标类别文件
#include
#include
#include
using namespace std;
using namespace cv;
const string CFG_FILE = "darknet-master\\cfg\\yolov3.cfg";
const string WEIGHT_FILE = "yolov3.weights";
const string COCO_NAMES = "darknet-master\\cfg\\coco.names";
class Object
{
public:
Object();
Object::Object(int id, float confidence, Rect rect, String name);
~Object();
public:
int id;
float confidence;
Rect rect;
String name;
private:
};
Object::Object() {
}
Object::Object(int id,float confidence,Rect rect,String name) {
this->id = id;
this->confidence = confidence;
this->rect = rect;
this->name = name;
}
Object::~Object() {
}
int main() {
//--------------------------实例化一个Yolo检测器---------------------------
Detector yolo_detector(CFG_FILE, WEIGHT_FILE);
//读取目标类别文件,80类
vector classNames;
ifstream fileIn(COCO_NAMES, ios::in);
if (!fileIn.is_open()) {
cerr << "failed to load COCO.names!" << endl;
return -1;
}
for (int i = 0; i < 80; i++) {
char temp1[100];
fileIn.getline(temp1, 100);
string temp2(temp1);
classNames.push_back(String(temp2));
}
//---------------------------加载输入图像-----------------------------------
auto image = Detector::load_image("7.jpg");
cout << "图像宽度=" << image.w << endl
<< "图像高度=" << image.h << endl
<< "图像通道=" << image.c << endl;
//-----------------------------目标检测---------------------------------------
TickMeter t;
t.start();
auto res = yolo_detector.detect(image);
t.stop();
cout << "YOLO-v3检测时间=" << t.getTimeSec() << "sec" << endl;
//----------------------------解析检测结果---------------------------------------
vector detectObjects;
for (auto& i:res) {
int id = i.obj_id;
float confidence = i.prob;
String name = classNames[id];
Rect rect = Rect{ static_cast(i.x),static_cast(i.y),static_cast(i.w),static_cast(i.h) };
detectObjects.push_back(Object{ id,confidence,rect,name });
}
//----------------------------绘制结果---------------------------------------------
Mat im_src = imread("7.jpg");
for (auto& i:detectObjects) {
rectangle(im_src, i.rect, Scalar(0, 255, 255), 2);
putText(im_src, i.name, i.rect.tl(), 1, 1.8, Scalar(255, 0, 0),2);
}
imshow("yolo-v3", im_src);
waitKey(0);
}
API介绍
yolo_v2_class.hpp 中定义了Detector,将yolo封装到C++类中,方便使用。下面是Detector类的源码。
class Detector {
std::shared_ptr detector_gpu_ptr;
std::deque<:vector>> prev_bbox_vec_deque;
const int cur_gpu_id;
public:
float nms = .4;
bool wait_stream;
YOLODLL_API Detector(std::string cfg_filename, std::string weight_filename, int gpu_id = 0);
YOLODLL_API ~Detector();
YOLODLL_API std::vector detect(std::string image_filename, float thresh = 0.2, bool use_mean = false);
YOLODLL_API std::vector detect(image_t img, float thresh = 0.2, bool use_mean = false);
static YOLODLL_API image_t load_image(std::string image_filename);
static YOLODLL_API void free_image(image_t m);
YOLODLL_API int get_net_width() const;
YOLODLL_API int get_net_height() const;
YOLODLL_API std::vector tracking_id(std::vector cur_bbox_vec, bool const change_history = true,
int const frames_story = 10, int const max_dist = 150);
std::vector detect_resized(image_t img, int init_w, int init_h, float thresh = 0.2, bool use_mean = false)
{
if (img.data == NULL)
throw std::runtime_error("Image is empty");
auto detection_boxes = detect(img, thresh, use_mean);
float wk = (float)init_w / img.w, hk = (float)init_h / img.h;
for (auto &i : detection_boxes) i.x *=