c++ 调用训练好的onnx文件
【代码】c++ 调用训练好的onnx文件。
·
文章目录
blobFromImage 将图像转换为神经网络可以接受的输入格式(blob)
cv::Mat blobFromImage(
cv::InputArray image,
double scalefactor = 1.0, - 缩放因子 1.0/255.0:将像素值从 [0, 255] 归一化到 [0, 1]1.0:不进行缩放
const cv::Size& size = cv::Size(), - 目标尺寸
const cv::Scalar& mean = cv::Scalar(), - 均值减除
bool swapRB = false, - 交换红蓝通道
bool crop = false, - 是否裁剪
int ddepth = CV_32F - 输出深度
);
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
int main()
{
Mat image = imread("../76_jpg.rf.04aea58b8e629bb15b1c3b52d538d3a9.jpg");
if (image.empty()) {
cerr << "Error: Could not load image!" << endl;
return -1;
}
cout << "原始图像信息:" << endl;
cout << "尺寸: " << image.cols << "x" << image.rows << endl;
cout << "通道数: " << image.channels() << endl;
cout << "类型: " << image.type() << endl;
const int INPUT_WIDTH = 640;
const int INPUT_HEIGHT = 640;
Mat blob = blobFromImage(image, 1.0, Size(INPUT_WIDTH, INPUT_HEIGHT), Scalar(), true, false);
cout << "\nBlob信息:" << endl;
cout << "维度数: " << blob.dims << endl;
cout << "形状: [" << blob.size[0];
for (int i = 1; i < blob.dims; i++) {
cout << ", " << blob.size[i];
}
cout << "]" << endl;
cout << "blob维度: " << blob.size[0] << "-" << blob.size[1]
<< "-" << blob.size[2] << "-" << blob.size[3] << endl;
cout << "总元素数: " << blob.total() << endl;
cout << "数据类型: " << blob.type() << endl;
return 0;
}

读取文件onnx
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
int main()
{
Net net = readNetFromONNX("../best.onnx");
if (net.empty())
{
cout << "模型加载失败" << endl;
return -1;
}
cout << "CNN模型模型加载成功" << endl;
vector<string> layerNames = net.getLayerNames();
cout << "模型的总层数:" << layerNames.size() << endl;
for (int i = 0; i < layerNames.size(); i++)
{
string layerName = layerNames[i]; //层的名字
int layerId = net.getLayerId(layerName);
Ptr<Layer> layer = net.getLayer(layerId);
cout << "第" << i + 1 << "层\t名称:" << layerName << "\t类型:" << layer->type << endl;
}
return 0;
}
读取Caffe 文件
Net net1 = readNetFromCaffe("1.prototxt", "1.caffemodel");
读取Tensorflow文件
Net net2 = readNetFromTensorflow("1.pb");
通用读取文件
//一个参数:单文件模型
Net net3 = readNet("resnet18-v1-7.onnx");
//二个参数:双文件模型
Net net4 = readNet("deploy.prototxt", "res10_300x300_ssd_iter_140000_fp16.caffemodel");
调用YOLOv11 目标检测
#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <fstream>
#include <algorithm>
using namespace std;
using namespace cv;
using namespace dnn;
vector<string> classes = { "cat", "chicken", "cow", "dog", "fox",
"goat", "horse", "person", "racoon", "skunk" };
struct Detection
{
Rect bbox;
float confidence;
int class_id;
};
void processYOLODecectionOutput(const Mat&output,
vector<Detection>&detections,
float conf_threshold=0.25f,
float iou_threshold=0.45f)
{
//[1, 14, 8400]
int mun_classess = 10;//类别
int num_boxes = output.size[2];
int data_length = output.size[1];
//重新排列维度
Mat output_mat = output.reshape(1, data_length);
output_mat = output_mat.t();
vector<Rect> boxs;
vector<float> confidences;
vector<int> class_ids;
for (int i = 0; i < num_boxes; i++)
{
Mat row = output_mat.row(i);
//提取边界
float* data = row.ptr<float>();
float cx = data[0];
float cy = data[1];
float w = data[2];
float h = data[3];
//找到最大类别概率
Mat scores = row.colRange(4,4+ mun_classess);
Point class_id_point;
double max_class_score;
minMaxLoc(scores,nullptr, &max_class_score, nullptr, &class_id_point);
if (max_class_score > conf_threshold)
{
//转换为左上角坐标的宽和高
float x = cx - w / 2.0f;
float y = cy - h / 2.0f;
boxs.emplace_back(x, y, w, h);
confidences.push_back(max_class_score);
class_ids.push_back(class_id_point.x);
}
}
//非极大值抑制
vector<int> indices;
NMSBoxes(boxs, confidences, conf_threshold, iou_threshold, indices);
for (int idx : indices)
{
Detection det;
det.bbox = boxs[idx];
det.confidence = confidences[idx];
det.class_id = class_ids[idx];
detections.push_back(det);
}
}
class YOlODetection
{
private:
Net net;
float conf_threshold;
float iou_threshold;
int input_width;
int input_height;
public:
YOlODetection(const string& model_path, float con_thresh = 0.25f, float iou_thresh = 0.45,
int width = 640, int height = 640)
{
net = readNet(model_path);
conf_threshold = con_thresh;
iou_threshold = iou_thresh;
input_width = width;
input_height = height;
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
}
void detect(const Mat& image,vector<Detection>& detection)
{
Mat blob;
blobFromImage(image, blob, 1.0 / 255.0, Size(input_width, input_height), Scalar(), true,false);
// 设置模型输入
net.setInput(blob);
//前向传播,推理
vector<Mat> outputs;
net.forward(outputs,net.getUnconnectedOutLayersNames());//getUnconnectedOutLayersNames获取最后一层的名字
cout << "outputs" << outputs.size() << endl;
Mat output = outputs[0]; // YOLOv8 ONNX 通常只有一个输出
cout << "Output shape: [";
for (int i = 0; i < output.dims; ++i) {
cout << output.size[i];
if (i < output.dims - 1) cout << ", ";
}
cout << "]" << endl;
if (!output.empty())
{
processYOLODecectionOutput(output, detection, conf_threshold, iou_threshold);
}
//坐标转换为原图尺寸
float x_factor = static_cast<float>(image.cols) / input_width;
float y_factor = static_cast<float>(image.rows) / input_height;
for (auto& det : detection)
{
det.bbox.x = static_cast<int>(det.bbox.x * x_factor);
det.bbox.y = static_cast<int>(det.bbox.y * y_factor);
det.bbox.width = static_cast<int>(det.bbox.width * x_factor);
det.bbox.height = static_cast<int>(det.bbox.height * y_factor);
}
}
};
int main()
{
YOlODetection detector("../best.onnx");
Mat img = imread("../73_jpg.rf.4a2e03f9868a026dc1e1e7d166b59340.jpg");
vector<Detection> detection;
detector.detect(img, detection);
//绘制
for (const auto& det : detection)
{
rectangle(img,det.bbox,cv::Scalar(0,255,0),2);
// 2. 构造标签文本:例如 "fox: 0.85"
string label = format("%s: %.2f", classes[det.class_id].c_str(), det.confidence);
// 3. 设置文字位置(在框的左上角)
int x = det.bbox.x;
int y = det.bbox.y - 10; // 文字在框上方,避免遮挡
// 防止文字画到图像外面
if (y < 15) y = det.bbox.y + 15; // 如果太靠上,就画在框内顶部
// 4. 绘制文字
putText(img, label, Point(x, y),FONT_HERSHEY_SIMPLEX,0.5,Scalar(0, 255, 0), 2);
}
imshow("Detection", img);
waitKey(0);
return 0;
}

更多推荐
所有评论(0)