Darknet-YOLOV3编译成动态链接库并进行检测

Darknet深度学习框架是一个用C和CUDA编写的开源神经网络框架。它安装速度快,易于安装,并支持CPU和GPU计算。
GitHub源码:https://github.com/pjreddie/darknet
官网:https://pjreddie.com/darknet/
YOLO算法中把物体检测问题处理成回归问题,用一个卷积神经网络结构就可以从输入图像直接预测bounding box和类别概率。其优点有:
1、速度快。在Titan X GPU上的速度是45 fps(frames per second),加速版的YOLO差不多是150fps。
2、基于图像的全局信息进行预测。这一点和基于sliding window以及region proposal等检测算法不一样。与Fast R-CNN相比,YOLO在误检测(将背景检测为物体)方面的错误率能降低一半多。
3、可以学到物体的generalizable-representations。可以理解为泛化能力强。
4、准确率高。
最近在使用Yolov3进行目标物体(行人)的检测,原本是在Pytorch上用的,检测识别的部分是用python3写的,但因为要和ROS结合起来使用,再加上要用到Kinect摄像头,一方面ROS默认python使用的版本是2.7,另一方面纯python写的代码调用起来效率确实没那么高,一旦同时好几个工作同时进行的话,效率就更低了。于是决定把目标检测那边也使用C++。Pytorch其实有C++版本,用的是libtorch,但因为教程比较少,就先不去踩坑了。
官方的github源码挺好的,但菜菜的我想实现的是加载网络之后,传一张图片返回识别的标定框信息的功能,但官方给的示例都是使用的./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg的方法进行识别的,目前我还没找到进行检测的那部分代码。
这里推荐另一份代码,给上github地址:https://github.com/AlexeyAB/darknet 这个库十分贴心,可以生成动态链接库供调用。
首先说编译方法,其实很简单。如果有CUDA,要使用GPU加速,要用OpenCV,要生成动态链接库,那么打开Makefile文件,修改下面的部分:

# GPU=0
GPU=1
# CUDNN=0
CUDNN=1
CUDNN_HALF=0
# OPENCV=0
OPENCV=1
AVX=0
OPENMP=0
# LIBSO=0
LIBSO=1
ZED_CAMERA=0

# set GPU=1 and CUDNN=1 to speedup on GPU
# set CUDNN_HALF=1 to further speedup 3 x times (Mixed-precision on Tensor Cores) GPU: Volta, Xavier, Turing and higher
# set AVX=1 and OPENMP=1 to speedup on CPU (if error occurs then set AVX=0)

也就是将对应的0改成1
然后直接make,就可以生成.so文件了
下面是调用动态链接库的使用:
参考博客:https://blog.csdn.net/haithink/article/details/88843297
cpp文件:

#include 
#include 
#include 
#include 

#include             // C++
#include    // C
#include    // C
#include "yolo_v2_class.hpp" 

using namespace std;
using namespace cv;

cv::Rect draw_boxes(cv::Mat mat_img, std::vector<bbox_t> result_vec);
std::vector<std::string> objects_names_from_file(std::string const filename);

int main(int argc, char ** argv)
{
    std::string  names_file = "/xxx/darknet/data/coco.names";
    std::string  cfg_file = "/xxx/darknet/cfg/yolov3.cfg";
    std::string  weights_file = "/xxx/darknet/yolov3.weights";
    std::string filename;

    float const thresh = 0.2;
    Detector detector(cfg_file, weights_file);		//加载模型

    //auto obj_names = objects_names_from_file(names_file);

    cv::Mat mat_img = cv::imread("xxx.jpg");		//加载图片

    std::vector<bbox_t> result_vec = detector.detect(mat_img);		//获得返回结果

    cv::Rect rect = draw_boxes(mat_img,result_vec);
    cv::imshow("window name", mat_img);
    cv::waitKey(1000);

    return 0;
}

cv::Rect draw_boxes(cv::Mat mat_img, std::vector<bbox_t> result_vec)
{
    cv::Rect rect;
    for (auto &i : result_vec) {
        if(i.obj_id==0){
            rect = cv::Rect(i.x, i.y, i.w, i.h);
            cv::rectangle(mat_img, rect, cv::Scalar(0,255,255), 2);
        }
    }
    return rect;
}

std::vector<std::string> objects_names_from_file(std::string const filename) {
    std::ifstream file(filename);
    std::vector<std::string> file_lines;
    if (!file.is_open()) return file_lines;
    for(std::string line; getline(file, line);) file_lines.push_back(line);
    std::cout << "object names loaded \n";
    return file_lines;
}

重点部分就三句:

    Detector detector(cfg_file, weights_file);		//加载模型

    cv::Mat mat_img = cv::imread("xxx.jpg");		//加载图片

    std::vector<bbox_t> result_vec = detector.detect(mat_img);		//获得返回结果

在/include/yolo_v2_class.hpp中可以看到bbox_t的结构:

struct bbox_t {
    unsigned int x, y, w, h;       // (x,y) - top-left corner, (w, h) - width & height of bounded box
    float prob;                    // confidence - probability that the object was found correctly
    unsigned int obj_id;           // class of object - from range [0, classes-1]
    unsigned int track_id;         // tracking id for video (0 - untracked, 1 - inf - tracked object)
    unsigned int frames_counter;   // counter of frames on which the object was detected
    float x_3d, y_3d, z_3d;        // center of object (in Meters) if ZED 3D Camera is used
};

可以根据自己的需求进行调取和检测物的筛选,注意id是从0开始的
最后是CMakeLists.txt文件的编写:

cmake_minimum_required(VERSION 2.8)

project(Test)

add_definitions(-std=c++11)
ADD_DEFINITIONS(-DOPENCV)

# find opencv
find_package(OpenCV REQUIRED)
message(${OpenCV_INCLUDE_DIRS})

#这个是 yolo 动态库的路径
find_library(darknet libdarknet.so /home/xxx/darknet)

include_directories(${OpenCV_INCLUDE_DIRS})
# yolo 代码路径
include_directories(/home/xxx/darknet/include) 
  
aux_source_directory(./src/ DIR_SRC)

add_executable(Test Test.cpp)

target_link_libraries(Test ${OpenCV_LIBS} ${darknet} /home/xxx/darknet/libdarknet.so)

如果是利用OpenCV进行图片的传输的话,一定要加上ADD_DEFINITIONS(-DOPENCV)
放一张检测的结果图:
Darknet-YOLOV3编译成动态链接库并进行检测_第1张图片
Darknet-YOLOV3编译成动态链接库并进行检测_第2张图片

你可能感兴趣的:(机器学习)