欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c++調(diào)用實(shí)現(xiàn)yolov5轉(zhuǎn)onnx介紹

 更新時(shí)間:2021年12月22日 09:05:48   作者:小軍軍軍軍軍軍  
大家好,本篇文章主要講的是c++調(diào)用實(shí)現(xiàn)yolov5轉(zhuǎn)onnx介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽

介紹

現(xiàn)在很多開發(fā)都是需要用c++做最后一步的移植部署,手寫吧,先不說你會(huì)不會(huì)浪費(fèi)時(shí)間,網(wǎng)上找吧,問題千奇百怪,所以給大家出這篇文章,做雷鋒教學(xué),話不多說,開始

訓(xùn)練模型.pt轉(zhuǎn)onnx

訓(xùn)練部分根據(jù)呼聲再?zèng)Q定要不要寫一份博客吧??!
注意事項(xiàng):
1.訓(xùn)練代碼一定要選擇yolov5 5.0版本
2. 進(jìn)入models/exprort.py;

請(qǐng)?zhí)砑訄D片描述

3.將紅框區(qū)域換成你自己的訓(xùn)練完的模型

請(qǐng)?zhí)砑訄D片描述

4.將版本換成12;

請(qǐng)?zhí)砑訄D片描述

5.直接運(yùn)行即可,會(huì)生成出onnx的模型出來。

c++代碼解析

博主使用的是opencv4.5.3版本,已經(jīng)編譯好的,需要直接掃碼加我發(fā)你

main函數(shù)部分

請(qǐng)?zhí)砑訄D片描述

讀取模型利用的是dnn::readNet,opencv其實(shí)挺強(qiáng)大的博主已經(jīng)讀過tf模型,torch模型后續(xù)都會(huì)出對(duì)應(yīng)博客,這里總共有三點(diǎn)改,輸入圖片path,輸入類別名class_names,net部分改成自己的模型

net.set這些參數(shù)都固定就好,有興趣的同學(xué)可以研究研究DNN_TARGET_CPU這個(gè)地方,是可以使用gpu和cuda的,但是博主還沒復(fù)現(xiàn)過

推理部分講解

void postprocess(cv::Mat& cv_src, std::vector<cv::Mat>& outs, const std::vector<std::string>& classes, int net_size)
{
	float confThreshold = 0.1f;
	float nmsThreshold = 0.1f;
	std::vector<int> classIds;
	std::vector<float> confidences;
	std::vector<cv::Rect> boxes;
	int strides[] = { 8, 16, 32 };
	std::vector<std::vector<int> > anchors =
	{
		{ 10,13, 16,30, 33,23 },
		{ 30,61, 62,45, 59,119 },
		{ 116,90, 156,198, 373,326 }
	};
	for (size_t k = 0; k < outs.size(); k++)
	{
		float* data = outs[k].ptr<float>();
		int stride = strides[k];
		int num_classes = outs[k].size[4] - 5;
		for (int i = 0; i < outs[k].size[2]; i++)
		{
			for (int j = 0; j < outs[k].size[3]; j++)
			{
				for (int a = 0; a < outs[k].size[1]; ++a)
				{
					float* record = data + a * outs[k].size[2] * outs[k].size[3] * outs[k].size[4] +
						i * outs[k].size[3] * outs[k].size[4] + j * outs[k].size[4];
					float* cls_ptr = record + 5;
					for (int cls = 0; cls < num_classes; cls++)
					{
						float score = sigmoid(cls_ptr[cls]) * sigmoid(record[4]);
						if (score > confThreshold)
						{
							float cx = (sigmoid(record[0]) * 2.f - 0.5f + (float)j) * (float)stride;
							float cy = (sigmoid(record[1]) * 2.f - 0.5f + (float)i) * (float)stride;
							float w = pow(sigmoid(record[2]) * 2.f, 2) * anchors[k][2 * a];
							float h = pow(sigmoid(record[3]) * 2.f, 2) * anchors[k][2 * a + 1];
							float x1 = std::max(0, std::min(cv_src.cols, int((cx - w / 2.f) * (float)cv_src.cols / (float)net_size)));
							float y1 = std::max(0, std::min(cv_src.rows, int((cy - h / 2.f) * (float)cv_src.rows / (float)net_size)));
							float x2 = std::max(0, std::min(cv_src.cols, int((cx + w / 2.f) * (float)cv_src.cols / (float)net_size)));
							float y2 = std::max(0, std::min(cv_src.rows, int((cy + h / 2.f) * (float)cv_src.rows / (float)net_size)));
							classIds.push_back(cls);
							confidences.push_back(score);
							boxes.push_back(cv::Rect(cv::Point(x1, y1), cv::Point(x2, y2)));
						}
					}
				}
			}
		}
	}
	std::vector<int> indices;
	cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
	for (size_t i = 0; i < indices.size(); i++)
	{
		int idx = indices[i];
		cv::Rect box = boxes[idx];
		drawPred(classIds[idx], confidences[idx], box.x, box.y,
			box.x + box.width, box.y + box.height, cv_src, classes);
	}
}

抬頭部分是兩大目標(biāo)檢測(cè)的閾值設(shè)置,然后anchors這些都不建議動(dòng),除非你在訓(xùn)練的時(shí)候用了你自己生成的anchors的話,就改成你自己的,然后根據(jù)訓(xùn)練推理后,會(huì)生成我們所對(duì)應(yīng)的坐標(biāo)框以及分?jǐn)?shù),將分?jǐn)?shù)和狂送到容器中,dnn中有nms等底層函數(shù)哦
cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
對(duì)應(yīng)輸入就可以了,然后得到我們的Box,index,和置信度,接下來就到了我們的畫圖環(huán)節(jié)。

darpred部分

void drawPred(int classId, float conf, int left, int top, int right, int bottom, cv::Mat& frame,
	const std::vector<std::string>& classes)
{
	cv::rectangle(frame, cv::Point(left, top), cv::Point(right, bottom), cv::Scalar(0, 255, 0), 3);
	std::string label = cv::format("%.2f", conf);
	if (!classes.empty()) {
		CV_Assert(classId < (int)classes.size());
		label = classes[classId] + ": " + label;
	}
	int baseLine;
	cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
	top = std::max(top, labelSize.height);
	cv::rectangle(frame, cv::Point(left, top - round(1.5 * labelSize.height)), cv::Point(left + round(1.5 * labelSize.width), top + baseLine), cv::Scalar(0, 255, 0), cv::FILLED);
	cv::putText(frame, label, cv::Point(left, top), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(), 2);
}

sigmod部分

inline float sigmoid(float x)
{
	return 1.f / (1.f + exp(-x));
}

結(jié)尾

到此這篇關(guān)于c++調(diào)用實(shí)現(xiàn)yolov5轉(zhuǎn)onnx介紹的文章就介紹到這了,更多相關(guān)c++ yolov5轉(zhuǎn)onnx內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論