yolov3自带了一个视频测试的demo,是c语言写的,本文根据yolov3的makefile结合自身需要,编写一个GPU版本的darknet.so库调用程序。将库的调用和应用程序分开来编译,具体的程序如下所示:
main.cpp
#include
#include
#include
#include
#include "opencv2/opencv.hpp"
#include "highgui.h"
#include "detect_obj.h"
void video_test(char * _video) ;
int main(int argc,char **argv)
{
video_test(argv[1]);
return 0 ;
}
//use this function to process video for detecting object
void video_test(char * _video)
{
detect_obj * detect_yolo = new detect_obj();
if(!detect_yolo->load_net("/home/wq/darknet/cfg/coco.data", \
"/home/wq/darknet/cfg/yolov3.cfg", "/home/wq/darknet/yolov3.weights",\
"/home/wq/darknet/data/names.list") )
return ;
CvCapture * capture = cvCreateFileCapture(_video);
IplImage * frame ;
unsigned short count = 0 ;
while (1){
count ++ ;
frame = cvQueryFrame(capture);
if (count%3==0)
{
detect_result result = detect_yolo->to_detection(frame,0.45,0.5,0.5) ;
free_detections(result.dets, result.nboxes);
}
// char c = cvWaitKey(33);
//if(c==27) break ;
}
cvReleaseCapture(&capture);
}
detect_obj.h
#pragma once
#include
#include
#include
#include
#include "opencv2/opencv.hpp"
#include "highgui.h"
typedef struct {
detection * dets;
int nboxes ;
} detect_result ;
/*
use this class to detect the object from image(iplimage)
*/
class detect_obj {
public:
explicit detect_obj();
virtual ~detect_obj();
//load the trained yolo net
bool load_net(char *datacfg, char *cfgfile, char *weightfile,char * nameslist) ;
// use the yolo net to detect the object before call this function,
// you must called the load_net function
detect_result to_detection(IplImage *_img ,float _nms , float _thresh, float _hier_thresh ) ;
/* detect_obj & operator = ( const detect_obj & _obj){
if (&_obj ==this)
{return *this;} };*/
protected:
char **names ;
image **alphabet ;
network * net ;
layer l_last ;
};
detect_obj.cpp
#include "detect_obj.h"
detect_obj::detect_obj()
{
//initilizing the member variable
names = nullptr ;
alphabet =NULL;
net = NULL ;
make_window("predictions", 512, 512, 0);
}
detect_obj::~detect_obj()
{
if(*names) delete *names;
if (names) delete names ;
if (*alphabet) delete *alphabet ;
if (alphabet) delete alphabet ;
if (net) delete net ;
}
/*****************************************************
name:bool detect_obj::load_net(char *datacfg, char *cfgfile, char *weightfile,char * nameslist)
input:
datacfg the info about data
cfgfile the architecture of model
weightfile the parameters of the model
nameslist the classes of data
output:
bool if load the net correctly return true ,otherwise return false
function:load the network of yolo
*********************************************************/
bool detect_obj::load_net(char *datacfg, char *cfgfile, char *weightfile,char * nameslist)
{
list *options = read_data_cfg(datacfg) ;
char *name_list = option_find_str(options,"names",nameslist);
names = get_labels(name_list) ;
alphabet = load_alphabet();
net = load_network(cfgfile,weightfile,0);
set_batch_network(net,1);
srand(2222222);
l_last = net->layers[net->n-1] ;
return true ;
}
/*****************************************************
name:bool detect_obj::to_detection(IplImage *_img,float _nms , float _thresh, float _hier_thresh )
input:
IplImage the image used to detect the object
_nms if not zero ,will use this value to do nms operation
_thresh the thresh of whether object or not
_hier_thresh the same meaning with thresh ,i am not comprehensize
output:
detect_result the object boxes and the classes ,the numbers of boxes
function:use the yolo model to detect object in object ,you must call net_load
before call this function
*********************************************************/
detect_result detect_obj::to_detection(IplImage *_img,float _nms , float _thresh, float _hier_thresh )
{
int h = _img->height ;
int w = _img->width ;
int c = _img->nChannels ;
image im = make_image(w,h,c) ;
unsigned char *data = (unsigned char *)_img->imageData ;
int step = _img->widthStep;
int i,j,k;
for (i = 0 ;iw,net->h) ;
double time ;
float *X = sized.data ;
time = what_time_is_it_now();
network_predict(net,X);
printf("Predicted in %f seconds.\n",what_time_is_it_now()-time) ;
int nboxes = 0 ;
detection *dets = get_network_boxes(net,im.w,im.h,_thresh,_hier_thresh,0,1,&nboxes);
if(_nms) do_nms_sort(dets,nboxes,l_last.classes,_nms);
detect_result result ;
result.dets = dets ;
result.nboxes = nboxes ;
//for test
draw_detections(im, dets, nboxes, _thresh, names, alphabet, l_last.classes);
//save_image(im, "predictions");
show_image(im, "predictions", 1);
free_image(im) ;
free_image(sized) ;
//for test end
return result ;
}
对darknet自带的makefile进行更改,只编译自己写的程序,GPU版本,代码如下:
GPU=1
CUDNN=0
OPENCV=1
OPENMP=0
DEBUG=0
VPATH=./myproj2
SLIB=libdarknet.so
ALIB=libdarknet.a
EXEC=main2
OBJDIR=./myobj2/
CC=gcc
CPP=g++ -std=c++11
OPTS=-Ofast
LDFLAGS= -lm -pthread
COMMON= -Iinclude/ -Isrc/
CFLAGS=-Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC
ifeq ($(OPENMP), 1)
CFLAGS+= -fopenmp
endif
ifeq ($(DEBUG), 1)
OPTS=-O0 -g
endif
CFLAGS+=$(OPTS)
ifeq ($(OPENCV), 1)
COMMON+= -DOPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` -lstdc++
COMMON+= `pkg-config --cflags opencv`
endif
ifeq ($(GPU), 1)
COMMON+= -DGPU -I/usr/local/neumoai/cuda8.0/include
CFLAGS+= -DGPU
LDFLAGS+= -L/usr/local/neumoai/cuda8.0/lib64 -lcuda -lcudart -lcublas -lcurand
endif
ifeq ($(CUDNN), 1)
COMMON+= -DCUDNN
CFLAGS+= -DCUDNN
LDFLAGS+= -lcudnn
endif
EXECOBJA= detect_obj.o main.o
ifeq ($(GPU), 1)
LDFLAGS+= -lstdc++
endif
EXECOBJ = $(addprefix $(OBJDIR), $(EXECOBJA))
DEPS = $(wildcard myproj2/*.h) Makefile-myproj2 include/darknet.h
all: obj backup results $(EXEC)
#all: obj results $(SLIB) $(ALIB) $(EXEC)
$(EXEC): $(EXECOBJ) $(ALIB)
$(CPP) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(ALIB)
$(OBJDIR)%.o: %.cpp $(DEPS)
$(CPP) $(COMMON) $(CFLAGS) -c $< -o $@
$(OBJDIR)%.o: %.c $(DEPS)
$(CC) $(COMMON) $(CFLAGS) -c $< -o $@
$(OBJDIR)%.o: %.cu $(DEPS)
$(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@
obj:
mkdir -p myobj2
.PHONY: clean
clean:
rm -rf $(EXEC) $(EXECOBJ)
需要对库的路径及头文件的路径进行修改,符合自己的工程的需要,推荐在darknet源文件中。
之前写了个cmakefile.txt的,cpu版本的库调用没有问题,gpu版本的库调用有问题,后来发现应该是没有指定-DGPU宏定义,大家也可以用cmakelist.txt。