目录
下图中,可以看到存在darknet、libdarknet.so两个文件(网上有很多darknet资源)2.2 在终端创建一个新文件夹yolov3_test
0. 前言
在正文之前,交代背景。不同与PC端的是,这里采用的是Jetson nano上位机(我感觉与树霉派差不多)。Jeston nano上搭载的是ubuntuu18.04,至于系统问题请自行搜索。
系统:Ubuntu 18.04
软件:opencv 3.4.0、CMake
外设(必须):5V2A直流电源线、摄像头、屏幕、键盘、鼠标
1. 下载安装opencv 3.4.0
先附上两篇参考博客,我按照这两篇博客操作下来是没问题的:第一篇,第二篇。
以下内容几乎是复制粘贴:
1.1 配置相应的以来库
sudo apt-get install build-essential
# 必须的,gcc编译环境
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
# 必须的,包括cmake等工具
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
# 可选的,看个人需要,总共5M左右
1.2 下载opencv 3.4.0(源码)
1.3 编译(时间较长)
cd opencv-3.4.0
mkdir build
# 创建编译文件
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
# 生成后的Makefile在build文件夹中,而需要的CMakeLists.txt在 ".."中,即上一级文件夹中(opencv-3.4.0)
1.4 安装
# 4个线程编译,查看cpu核数量
# grep "model name" /proc/cpuinfo | wc -l
make -j4
# 安装
sudo make install
1.5 配置opencv路径
#终端中输入
sudo vim /etc/ld.so.conf.d/opencv.conf
在打开的文件内添加:
/usr/local/lib
#终端中输入
sudo ldconfig
sudo vim /etc/bash.bashrc
在打开的文件夹末尾添加:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
#终端中输入
source /etc/bash.bashrc
1.6 测试opencv3.4.0
#上一个终端不用关闭,继续输入
cd ../samples/cpp/example_cmake
cmake .
make
./opencv_example
2. c++使用darknet链接库调用yolov3
2.1 准备工作
下图中,可以看到存在darknet、libdarknet.so两个文件(网上有很多darknet资源)
2.2 在终端创建一个新文件夹yolov3_test
创建完成后,在文件夹内创建CMakeLists.txt文件,并将以下内容粘贴到文件里。
cmake_minimum_required(VERSION 2.8) # 最低版本需求
project(yolov3) #项目名
#opencv
add_definitions(-std=c++11)
ADD_DEFINITIONS(-DOPENCV)
ADD_DEFINITIONS(-DGPU)
######### opencv #########
set(OpenCV_DIR "/home/zzp/opencv-3.4.0")
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
######### darknet #########
include_directories(/home/zzp/darknet-master/include)
find_library(darknet libdarknet.so /home/zzp/darknet-master)
add_executable(${PROJECT_NAME} "/home/zzp/yolov3/yolov3_test.cpp" )
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${darknet})
接下来,在yolov3_test文件夹内新建cfg、img、data、include、weights文件夹,结果如下图所示。
2.3 丰富yolov3_test
回到darknet-master文件夹,将coco.names、yolov-tiny.cfg放入cfg文件,将dog.jpg放入img,将yolo_v2_class.hpp放入Include,将yolov3-tiny.weights放入weights。
2.4 编写源码
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>
#include <fstream>
#include "/home/zzp/yolov3/include/yolo_v2_class.hpp"//引用yolo动态链接库中的头文件
using namespace std;
using namespace cv;
#pragma comment(lib, "yolo_cpp_dll.lib")//引用yolo动态链接库
//画出检测框和相关信息
void DrawBoxes(Mat &frame, vector<string> classes, int classId, float conf, int left, int top, int right, int bottom)
{
//画检测框
rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
//该检测框对应的类别和置信度
string label = format("%.2f", conf);
if (!classes.empty())
{
CV_Assert(classId < (int)classes.size());
label = classes[classId] + ":" + label;
}
//将标签显示在检测框顶部
int baseLine;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
top = max(top, labelSize.height);
rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}
//画出检测结果
void Drawer(Mat &frame, vector<bbox_t> outs, vector<string> classes)
{
//获取所有最佳检测框信息
for (int i = 0; i < outs.size(); i++)
{
DrawBoxes(frame, classes, outs[i].obj_id, outs[i].prob, outs[i].x, outs[i].y,
outs[i].x + outs[i].w, outs[i].y + outs[i].h);
}
}
int main(void)
{
string classesFile = "/home/zzp/yolov3/cfg/coco.names";
string modelConfig = "/home/zzp/yolov3/cfg/yolov3-tiny.cfg";
string modelWeights = "/home/zzp/yolov3/weights/yolov3-tiny.weights";
//加载类别名
vector<string> classes;
ifstream ifs(classesFile.c_str());
string line;
while (getline(ifs, line)) classes.push_back(line);
//加载网络模型,0是指定第一块GPU
Detector detector(modelConfig, modelWeights, 0);
string mode = "video";
//图像
if (mode == "image")
{
Mat frame = imread("/home/zzp/yolov3/img/test.jpeg");
std::vector<bbox_t> result_vec = detector.detect(frame);
Drawer(frame, result_vec, classes);
cv::namedWindow("CV_WINDOW", CV_WINDOW_NORMAL);
cv::imshow("CV_IMAGE", frame);
cv::imwrite("/home/zzp/yolov3/img/result.jpg",frame);
cv::waitKey(0);
}
//视频
else if (mode == "video")
{
VideoCapture cap(0);
Size size(640, 480);
VideoWriter writer("/home/zzp/yolov3/data/result.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 25, size);
while (1)
{
Mat frame;
cap >> frame;
if (frame.empty())
break;
std::vector<bbox_t> result_vec = detector.detect(frame);
//画图
Drawer(frame, result_vec, classes);
cv::imshow("YOLO V3 Camera", frame);
for(int i = 0; i < result_vec.size(); i++)
{
//检测到人就告知用户此人所在区域
if(result_vec[i].obj_id == 0)
{
cout << "-----------------------------------------------------------------------" << endl;
cout << "检测到一个人,他(她)位于视频中这个位置: " << endl;
cout << "起始点(左上):(" << result_vec[i].x << "," << result_vec[i].y << ")"
<< "\t宽与高:(" << result_vec[i].w << "," << result_vec[i].h << ")." << endl;
cout << "-----------------------------------------------------------------------" << endl;
}
}
//ESC退出程序
if(waitKey(3) == 27) break;
writer << frame;
}
cv::destroyAllWindows();
cap.release();
}
return 0;
}
2.5 编译
此时yolov3_test文件夹有如下文件:
#在终端中输入
cd yolov3_test
cmake .
make
结果如下图所示:
2.6 测试效果
#测试图片(将源码string mode修改为 image)
cd yolov3_test
./yolov3
#测试视频(自己测试吧,我这里是没毛病的!)
3. 后续目标
探索Jetson nano串口功能,实现检测到目标后实时反馈数据。