目录

1 Python环境下调用

2 C++环境下调用(编写CMakeLists.txt文件)

2.1 OpenCV安装

2.2 程序编写

2.2.1 main.cpp

2.2.2 Detection.h

2.2.3 Detection.cpp

2.2.4 CMakeLists.txt

2.3 编译和测试


1 Python环境下调用

这个较为简单,唯一注意要点是安装的opencv-python版本要对,以下代码仅支持4.4.0.XX系列OpenCV版本,4.5.0版本OpenCV没有getUnconnectedOutLayersNames()这个属性。

完整代码如下:

import numpy as np
import time
import cv2if cv2.__version__ != '4.4.0':print("opencv版本不支持! 本程序语法仅支持4.4.0系列OpenCV")LABELS = open("coco.names").read().strip().split("\n")
np.random.seed(666)
COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")
# 导入 YOLO 配置和权重文件并加载网络:
net = cv2.dnn_DetectionModel('/home/ym/ym2021/yolov4.cfg', '/home/ym/ym2021/yolov4.weights')
# 获取 YOLO 未连接的输出图层
layer = net.getUnconnectedOutLayersNames()
image = cv2.imread('1.jpg')
# 获取图片尺寸
(H, W) = image.shape[:2]
# 从输入图像构造一个 blob,然后执行 YOLO 对象检测器的前向传递,给我们边界盒和相关概率
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416),swapRB=True, crop=False)
net.setInput(blob)
start = time.time()
# 前向传递,获得信息
layerOutputs = net.forward(layer)
# 用于得出检测时间
end = time.time()
print("YOLO took {:.6f} seconds".format(end - start))boxes = []
confidences = []
classIDs = []# 循环提取每个输出层
for output in layerOutputs:# 循环提取每个框for detection in output:# 提取当前目标的类 ID 和置信度scores = detection[5:]classID = np.argmax(scores)confidence = scores[classID]# 通过确保检测概率大于最小概率来过滤弱预测if confidence > 0.5:# 将边界框坐标相对于图像的大小进行缩放,YOLO 返回的是边界框的中心(x, y)坐标,# 后面是边界框的宽度和高度box = detection[0:4] * np.array([W, H, W, H])(centerX, centerY, width, height) = box.astype("int")# 转换出边框左上角坐标x = int(centerX - (width / 2))y = int(centerY - (height / 2))# 更新边界框坐标、置信度和类 id 的列表boxes.append([x, y, int(width), int(height)])confidences.append(float(confidence))classIDs.append(classID)
# 非最大值抑制,确定唯一边框
idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
# 确定每个对象至少有一个框存在
if len(idxs) > 0:# 循环画出保存的边框for i in idxs.flatten():# 提取坐标和宽度(x, y) = (boxes[i][0], boxes[i][1])(w, h) = (boxes[i][2], boxes[i][3])# 画出边框和标签color = [int(c) for c in COLORS[classIDs[i]]]cv2.rectangle(image, (x, y), (x + w, y + h), color, 1, lineType=cv2.LINE_AA)text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,0.5, color, 1, lineType=cv2.LINE_AA)
cv2.imshow("Tag", image)
cv2.waitKey(0)

2 C++环境下调用(编写CMakeLists.txt文件)

2.1 OpenCV安装

C++环境下编译安装OpenCV 4.5.1和OpenCV_Contrib库,参考我《ubuntu + oepncv + PCL + realsenseSDK + ROS + OpenVino开发环境搭建》https://blog.csdn.net/weixin_42118657/article/details/114527831

2.2 程序编写

程序结构如下:

  • main.cpp
  • Detection.cpp
  • Detection.h
  • CMakeLists.txt
  • build文件夹

2.2.1 main.cpp

#include "Detection.h"#include <iostream>using namespace std;
using namespace cv;
using namespace dnn;void TestDetection()
{string image_path = "/data/1.jpg";string save_path = "result.jpg";Mat img = imread(image_path);cout << "width: " << img.cols << endl;cout << "height: " << img.rows << endl;Detection detection = Detection();detection.Initialize(img.cols, img.rows);detection.Detecting(img);imwrite(save_path, detection.GetFrame());return;
}int main()
{TestDetection();return 0;
}

2.2.2 Detection.h

#pragma once
#ifndef __DETECTION_H__
#define __DETECTION_H__#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <string.h>
#include <vector>
#include <fstream>using namespace std;
using namespace cv;
using namespace dnn;class Detection
{
public://构造、析构函数Detection();~Detection();//初始化函数void Initialize(int width, int height);//读取网络模型void ReadModel();//行人与车辆检测bool Detecting(Mat frame);//获取网络输出层名称vector<String> GetOutputsNames();//对输出进行处理,使用NMS选出最合适的框void PostProcess();//画检测结果void Drawer();//画出检测框和相关信息void DrawBoxes(int classId, float conf, int left, int top, int right, int bottom);//获取Mat对象Mat GetFrame();//获取图像宽度int GetResWidth();//获取图像高度int GetResHeight();private://图像属性int m_width;  //图像宽度int m_height; //图像高度//网络处理相关Net m_model;            //网络模型Mat m_frame;            //每一帧Mat m_blob;             //从每一帧创建一个4D的blob用于网络输入vector<Mat> m_outs;     //网络输出vector<float> m_confs;  //置信度vector<Rect> m_boxes;   //检测框左上角坐标、宽、高vector<int> m_classIds; //类别idvector<int> m_perfIndx; //非极大阈值处理后边界框的下标//检测超参数int m_inpWidth;           //网络输入图像宽度int m_inpHeight;          //网络输入图像高度float m_confThro;         //置信度阈值float m_NMSThro;          //NMS非极大抑制阈值vector<string> m_classes; //类别名称private://内存释放void Dump();
};#endif

2.2.3 Detection.cpp

#include "Detection.h"using namespace cv;
using namespace dnn;//构造函数,成员变量初始化
Detection::Detection()
{//图像属性m_width = 0;m_height = 0;m_inpWidth = 416;m_inpHeight = 416;//其他成员变量m_confThro = 0.25;m_NMSThro = 0.4;//网络模型加载ReadModel();
}//析构函数
Detection::~Detection()
{Dump();
}//内存释放
void Detection::Dump()
{//网络输出相关清零m_outs.clear();m_boxes.clear();m_confs.clear();m_classIds.clear();m_perfIndx.clear();
}//初始化函数
void Detection::Initialize(int width, int height)
{//图像属性m_width = width;m_height = height;
}//读取网络模型和类别
void Detection::ReadModel()
{string classesFile = "/data/coco.names";String modelConfig = "/data/yolov4.cfg";String modelWeights = "/data/yolov4.weights";//加载类别名ifstream ifs(classesFile.c_str());string line;while (getline(ifs, line))m_classes.push_back(line);//加载网络模型m_model = readNetFromDarknet(modelConfig, modelWeights);m_model.setPreferableBackend(DNN_BACKEND_OPENCV);m_model.setPreferableTarget(DNN_TARGET_OPENCL);
}//行人与车辆检测
bool Detection::Detecting(Mat frame)
{m_frame = frame.clone();//创建4D的blob用于网络输入blobFromImage(m_frame, m_blob, 1 / 255.0, Size(m_inpWidth, m_inpHeight), Scalar(0, 0, 0), true, false);//设置网络输入m_model.setInput(m_blob);//前向预测得到网络输出,forward需要知道输出层,这里用了一个函数找到输出层m_model.forward(m_outs, GetOutputsNames());//使用非极大抑制NMS删除置信度较低的边界框PostProcess();//画检测框Drawer();return true;
}//获取网络输出层名称
vector<String> Detection::GetOutputsNames()
{static vector<String> names;if (names.empty()){//得到输出层索引号vector<int> outLayers = m_model.getUnconnectedOutLayers();//得到网络中所有层名称vector<String> layersNames = m_model.getLayerNames();//获取输出层名称names.resize(outLayers.size());for (int i = 0; i < outLayers.size(); ++i)names[i] = layersNames[outLayers[i] - 1];}return names;
}//使用非极大抑制NMS去除置信度较低的边界框
void Detection::PostProcess()
{for (int num = 0; num < m_outs.size(); num++){Point Position;double confidence;//得到每个输出的数据float *data = (float *)m_outs[num].data;for (int j = 0; j < m_outs[num].rows; j++, data += m_outs[num].cols){//得到该输出的所有类别的Mat scores = m_outs[num].row(j).colRange(5, m_outs[num].cols);//获取最大置信度对应的值和位置minMaxLoc(scores, 0, &confidence, 0, &Position);//对置信度大于阈值的边界框进行相关计算和保存if (confidence > m_confThro){//data[0],data[1],data[2],data[3]都是相对于原图像的比例int centerX = (int)(data[0] * m_width);int centerY = (int)(data[1] * m_height);int width = (int)(data[2] * m_width);int height = (int)(data[3] * m_height);int left = centerX - width / 2;int top = centerY - height / 2;//保存信息m_classIds.push_back(Position.x);m_confs.push_back((float)confidence);m_boxes.push_back(Rect(left, top, width, height));}}}//非极大值抑制,以消除具有较低置信度的冗余重叠框NMSBoxes(m_boxes, m_confs, m_confThro, m_NMSThro, m_perfIndx);
}//画出检测结果
void Detection::Drawer()
{//获取所有最佳检测框信息for (int i = 0; i < m_perfIndx.size(); i++){int idx = m_perfIndx[i];Rect box = m_boxes[idx];DrawBoxes(m_classIds[idx], m_confs[idx], box.x, box.y,box.x + box.width, box.y + box.height);}
}//画出检测框和相关信息
void Detection::DrawBoxes(int classId, float conf, int left, int top, int right, int bottom)
{//画检测框rectangle(m_frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);//该检测框对应的类别和置信度string label = format("%.2f", conf);if (!m_classes.empty()){CV_Assert(classId < (int)m_classes.size());label = m_classes[classId] + ":" + label;}//将标签显示在检测框顶部int baseLine;Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);top = max(top, labelSize.height);rectangle(m_frame, Point(left, top - round(1.5 * labelSize.height)), Point(left + round(1.5 * labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);putText(m_frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}//获取Mat对象
Mat Detection::GetFrame()
{return m_frame;
}//获取结果图像宽度
int Detection::GetResWidth()
{return m_width;
}//获取结果图像高度
int Detection::GetResHeight()
{return m_height;
}

2.2.4 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)project(yolo4_test)set(CMAKE_CXX_STANDARD 11)# Add block directories
set(DETECTION Detection.cpp)
add_executable(yolo4_test main.cpp ${DETECTION})#寻找opencv库
find_package(OpenCV REQUIRED)#添加头文件
include_directories(${OpenCV_INCLUDE_DIRS})
#链接Opencv库
target_link_libraries(yolo4_test ${OpenCV_LIBS} )

2.3 编译和测试

  1. cd 到源码目录
  2. mkdir build
  3. cd build
  4. cmake ..
  5. make
  6. ./yolo4_test(运行在build文件夹生成的可执行文件yolo4_test)

结果如下:

python、C++ 中通过OpenCV的DNN模块使用YoloV4相关推荐

  1. 用opencv的dnn模块做yolov5目标检测

    最近在微信公众号里看到多篇讲解yolov5在openvino部署做目标检测文章,但是没看到过用opencv的dnn模块做yolov5目标检测的.于是,我就想着编写一套用opencv的dnn模块做yol ...

  2. OpenCV之DNN模块,实现深度学习网络的推理加速

    OpenCV是计算机视觉领域使用最为广泛的开源库,以功能全面使用方便著称.自3.3版本开始,OpenCV加入了对深度神经网络(DNN)推理运算的支持.在LiveVideoStack线上交流分享中英特尔 ...

  3. AI入门之神经网络(9)基于c++、opencv的dnn模块的视频手势识别

    基于c++.opencv的dnn模块的手势识别 先看效果: 老规矩话不多,实现的方法步骤,细节全在我的代码注释里面,只你跟着注释写,相信你也写得出来的! #include <opencv2/dn ...

  4. OpenCV的dnn模块调用TesorFlow训练的MoblieNet模型

    七月 上海| 高性能计算之GPU CUDA培训 7月27-29日三天密集式学习  快速带你入门阅读全文> 正文共2073个字,2张图,预计阅读时间10分钟. 一.初得模型 那是一个月之前的事情了 ...

  5. python安装wheel,opencv与其它模块

    1.安装wheel,得先安装pip.pip安装好,按cmd进入后台,再按cd加python路径,进入python,输入pip instal wheel 会自动安装wheel! 2.安装opencv,到 ...

  6. OpenCV的DNN模块

    文章目录 Mat的构造函数 blobFromImage函数 dnn::Net 的 forward() Mat的构造函数 Mat::Mat()//无参数构造方法: Mat::Mat(int rows, ...

  7. ubuntu使用python opencv_Ubuntu中“利用Opencv + python进行特征匹配”的环境搭建

    2.安装Python插件:点击Vscode左侧第五个方框对应的功能,搜索Python并安装 3.安装pip (以下步骤均在终端Terminal中执行) sudo apt install pytho-p ...

  8. Python库中,如何使用jieba模块来实现古典名著《西游记》的分词

    接下来,我们将学习如何使用jieba模块来实现古典名著<西游记>的分词,并且会将书中重点人物出场次数以图形化的方式显示出来,并进一步创建一个词云图. 17.4.1 读取文件 因为小说< ...

  9. 深度学习与OpenCV DNN模块:权威指南

    计算机视觉领域自20世纪60年代末就已经存在.图像分类和目标检测是计算机视觉领域的一些最古老的问题,研究人员已经努力解决了几十年.使用神经网络和深度学习,我们已经达到了一个阶段,计算机可以开始真正地理 ...

最新文章

  1. HTML DOM Console对象
  2. CV领域论文常用单词汇总
  3. extjs4:代码实现comboBox选中事件
  4. asp获取手机mac_asp.net 获取客户端IP与mac
  5. 微软文本检索_如何在Microsoft Word中引用其他文档中的文本
  6. .NET 6 Preview 3 发布
  7. gsoap使用心得! (win32)
  8. 打印1-400以内 能同时被5和9 整数的数将这些数放入一个列表中,再输出这个列表
  9. Mac下matplotlib中文显示
  10. python开发环境
  11. 帆软决策报表JS实现点击超链切换TAB页
  12. Mysql 日期函数 增加周天年月时分秒
  13. 运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
  14. ubuntu16使用labelImg
  15. 【无线芯片解读】2.4G专题:(SI24R1简版)Ci24R1
  16. .com域名好抢注吗?抢注.com域名有哪些技巧?
  17. python中while循环只能用来实现无限循环的编程_while循环只能实现无限循环的编程...
  18. M1芯片电脑安装cerebro
  19. 南京中北学院荣跃计算机,南京师范大学中北学院来我院交流调研
  20. 【渝粤教育】国家开放大学2018年秋季 2408T中国当代文学 参考试题

热门文章

  1. [JAVA EE]Spring Boot 控制层:参数传递方法
  2. python中什么是字符举例说明_第20p,什么是字符串?Python中的str
  3. Failed to open zip file. Gradle‘s dependency cache may be corrupt (xx)
  4. java.lang.UnsupportedOperationException: Required method destroyItem was not overridden
  5. SCOI2009 最长距离
  6. oracleHelper 操作帮助类
  7. 2022-2028年中国UTM市场投资分析及前景预测报告
  8. 2022-2028年中国半导体硅片行业深度调研及投资前景预测报告
  9. SharePreference工具类
  10. 题目1000:计算a+b