2021-02-25

基于windows10系统的c++与darknet联合推理部署

基于windows的c++与darknet部署推理提供两种方式:基于opencv dnn模块推理方式和基于darknet模块推理方式。本文章介绍基于opencv dnn模块推理。

1)基于opencv dnn模块推理

  系统要求:Windows10系统
  软件及库文件下载: vs2015(社区个人免费版本镜像:[http://download.microsoft.com/download/B/4/8/B4870509-05CB-447C-878F-2F80E4CB464C/vs2015.com_chs.iso])
                 opencv4.4.0(地址:[https://opencv.org/])
  权重文件下载:coco.name、yolov4.cfg、yolov4.weights (文件在案例工程\x64\Debug\data\data80\yolo目录下)
案例:
新建项目:文件->新建->项目->VisualC++->Win32控制台应用程序
opencv配置:Debug与X64环境。参考链接https://blog.csdn.net/h321880947/article/details/90581647

完整工程:百度链接:https://pan.baidu.com/s/1q7jPY-RVhgPHeNy3qrCCNQ
提取码:9csi
源码:
#include “stdafx.h”
#include
#include <opencv.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <string.h>
#include
#include
#include <time.h>
#include<Windows.h>
#include <direct.h>
#include <stdio.h>
using namespace std;
using namespace cv;
using namespace dnn;
int m_width=0; //图像宽度
int m_height=0; //图像高度
Net m_model; //网络模型
Mat m_frame; //每一帧
Mat m_blob;
vectorm_outs; //网络输出
vectorm_confs; //置信度
vector m_boxes; // 检测窗口
vector m_classIds; //类别
vectorm_perfIndx; //非极大阈值处理后边界框的下标
int m_inpWidth=416; // 网络输入图像宽度
int m_inpHeight=416; // 网络输入图像高度
float m_confThro=0.25; // 置信度阈值
float m_NMSThro=0.4; //NMS非极大抑制阈值
vector m_classes; //类别名称
string m_loadConfigPath = “C:\Users\pb079088\Desktop\opencvdnn\x64\Debug\data\data80\”;
//加载模型
void ReadModel()
{
string classesFile = m_loadConfigPath +“yolo\coco.names”;
String modelConfig = m_loadConfigPath +“yolo\yolov4.cfg”;
String modelWeights= m_loadConfigPath +“yolo\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);
}
//使用非极大抑制NMS去除置信度较低的边界框
void 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 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);
}

//画出检测结果
void 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);
}
}
//获取Mat对象
Mat GetFrame()
{
return m_frame;
}
//获取结果图像宽度
int GetResWidth()
{
return m_width;
}
//获取结果图像高度
int GetResHeight()
{
return m_height;
}
vector GetOutputsNames()
{
static vector names;
if (names.empty())
{
//得到输出层索引号
vector 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;

}
bool Detecting(Mat frame)
{
m_frame = frame.clone();
blobFromImage(m_frame, m_blob, 1 / 255.0, Size(m_inpWidth, m_inpHeight), Scalar(0, 0, 0), true, false);
m_model.setInput(m_blob);
m_model.forward(m_outs, GetOutputsNames());
PostProcess();
Drawer();
return true;
}
void Initialize(int width, int height)
{
m_width = width;
m_height = height;
}
//图像检测
vector read_images_in_folder(cv::String pattern)
{
vectorcv::String fn;
glob(pattern, fn, false);

vector<Mat> images;
size_t count = fn.size(); //number of png files in images folder
for (size_t i = 0; i < count; i++)
{
	images.push_back(imread(fn[i]));
	imshow("img", imread(fn[i]));
	waitKey(1000);
}
return images;

}
void TestDetection()
{
string path =m_loadConfigPath+ “test_image/”;
string savePath = m_loadConfigPath + “test_result/”;
cv::String pattern = path+"*.jpg";
vectorcv::String fn;
glob(pattern, fn, false);
vector images;
size_t count = fn.size(); //number of png files in images folder
for (size_t i = 0; i < count; i++)
{
m_outs.clear();
m_confs.clear();
m_boxes.clear();
m_classIds.clear();
m_perfIndx.clear();
Mat img = imread(fn[i]);
Initialize(img.cols, img.rows);
Detecting(img);
string save_path =savePath+ fn[i].substr(fn[i].find_last_of("\") + 1);
imwrite(save_path, GetFrame());
}
return;
}
int main()
{
ReadModel(); //加载模型配置
TestDetection();//检测
return 0;
}

下次文章介绍c++与darknet联合部署推理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值