1.环境配置
在进行onnx预测前,需要搭建的环境如下:
1.opencv环境的配置,可参考博客:9.2 c++搭建opencv环境-CSDN博客
2.libtorch环境的配置,可参考博客:9.4 visualStudio 2022 配置 cuda 和 torch (c++)-CSDN博客
3.cuda环境的配置,可参考博客:9.4 visualStudio 2022 配置 cuda 和 torch (c++)-CSDN博客
4.onnx环境的配置,可参考博客:VS2019配置ONNXRuntime c++环境_microsoft.ml.onnxruntime-CSDN博客
2.yolov10的c++代码
该代码做了部分的修改,最后调试成功。具体的代码如下:
main.cpp
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include "inference.h"
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
bool runOnGPU = false;
// 1. 设置你的onnx模型
// Note that in this example the classes are hard-coded and 'classes.txt' is a place holder.
Inference inf("E:/best.onnx", cv::Size(640, 640), "classes.txt", runOnGPU); // classes.txt 可以缺失
// 2. 设置你的输入图片
std::vector<std::string> imageNames;
imageNames.push_back("E:\\vs\\daima\\1_16\\Project1\\x64\\Release\\street.jpg");
//imageNames.push_back("zidane.jpg");
for (int i = 0; i < imageNames.size(); ++i)
{
cv::Mat frame = cv::imread(imageNames[i]);
// Inference starts here...
std::vector<Detection> output = inf.runInference(frame);
int detections = output.size();
std::cout << "Number of detections:" << detections << std::endl;
// feiyull
// 这里需要resize下,否则结果不对
//cv::resize(frame, frame, cv::Size(480, 640));
for (int i = 0; i < detections; ++i)
{
Detection detection = output[i];
cv::Rect box = detection.box;
cv::Scalar color = detection.color;
// Detection box
cv::rectangle(frame, box, color, 2);
// Detection box text
std::string classString = detection.className + ' ' + std::to_string(detection.confidence).substr(0, 4);
cv::Size textSize = cv::getTextSize(classString, cv::FONT_HERSHEY_DUPLEX, 1, 2, 0);
cv::Rect textBox(box.x, box.y - 40, textSize.width + 10, textSize.height + 20);
cv::rectangle(frame, textBox, color, cv::FILLED);
cv::putText(frame, classString, cv::Point(box.x + 5, box.y - 10), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 0), 2, 0);
}
cv::imshow("Inference", frame);
cv::waitKey(0);
cv::destroyAllWindows();
}
}
inference.cpp
#include "inference.h"
Inference::Inference(const std::string &onnxModelPath, const cv::Size &modelInputShape, const std::string &classesTxtFile, const bool &runWithCuda)
{
modelPath = onnxModelPath;
modelShape = modelInputShape;
classesPath = classesTxtFile;
cudaEnabled = runWithCuda;
loadOnnxNetwork();
// loadClassesFromFile(); The classes are hard-coded for this example
}
std::vector<Detection> Inference::runInference(const cv::Mat &input)
{
cv::Mat modelInput = input;
if (letterBoxForSquare && modelShape.width == modelShape.height)
modelInput = formatToSquare(modelInput);
cv::Mat blob;
cv::dnn::blobFromImage(modelInput, blob, 1.0/255.0, modelShape, cv::Scalar(), true, false);
net.setInput(blob);
std::vector<cv::Mat> outputs;
net.forward(outputs, net.getUnconnectedOutLayersNames());
int rows = outputs[0].size[1];
int dimensions = outputs[0].size[2];
bool yolov8 = false;
// yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])
// yolov8 has an output of shape (batchSize, 84, 8400) (Num classes + box[x,y,w,h])
if (dimensions > rows) // Check if the shape[2] is more than shape[1] (yolov8)
{
yolov8 = true;
rows = outputs[0].size[2];
dimensions = outputs[0].size[1];
outputs[0] = outputs[0].reshape(1, dimensions);
cv::transpose(outputs[0], outputs[0]);
}
float *data = (float *)outputs[0].data;
float x_factor = modelInput.cols / modelShape.width;
float y_factor = modelInput.rows / modelShape.height;
std::vector<int> class_ids;
std::vector<float> confidences;
std::vector<cv::Rect> boxes;
for (int i = 0; i < rows; ++i)
{
if (yolov8)
{
float *classes_scores = data+4;
cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);
cv::Point class_id;
double maxClassScore;
minMaxLoc(scores, 0, &maxClassScore, 0, &class_id);
if (maxClassScore > modelScoreThreshold)
{
confidences.push_back(maxClassScore);
class_ids.push_back(class_id.x);
float x = data[0];
float y = data[1];
float w = data[2];
float h = data[3];
int left = int((x - 0.5 * w) * x_factor);
int top = int((y - 0.5 * h) * y_factor);
int width = int(w * x_factor);
int height = int(h * y_factor);
boxes.push_back(cv::Rect(left, top, width, height));
}
}
else // yolov5
{
float confidence = data[4];
if (confidence >= modelConfidenceThreshold)
{
float *classes_scores = data+5;
cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);
cv::Point class_id;
double max_class_score;
minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
if (max_class_score > modelScoreThreshold)
{
confidences.push_back(confidence);
class_ids.push_back(class_id.x);
float x = data[0];
float y = data[1];
float w = data[2];
float h = data[3];
int left = int((x - 0.5 * w) * x_factor);
int top = int((y - 0.5 * h) * y_factor);
int width = int(w * x_factor);
int height = int(h * y_factor);
boxes.push_back(cv::Rect(left, top, width, height));
}
}
}
data += dimensions;
}
std::vector<int> nms_result;
cv::dnn::NMSBoxes(boxes, confidences, modelScoreThreshold, modelNMSThreshold, nms_result);
std::vector<Detection> detections{};
for (unsigned long i = 0; i < nms_result.size(); ++i)
{
int idx = nms_result[i];
Detection result;
result.class_id = class_ids[idx];
result.confidence = confidences[idx];
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(100, 255);
result.color = cv::Scalar(dis(gen),
dis(gen),
dis(gen));
result.className = classes[result.class_id];
result.box = boxes[idx];
detections.push_back(result);
}
return detections;
}
void Inference::loadClassesFromFile()
{
std::ifstream inputFile(classesPath);
if (inputFile.is_open())
{
std::string classLine;
while (std::getline(inputFile, classLine))
classes.push_back(classLine);
inputFile.close();
}
}
void Inference::loadOnnxNetwork()
{
net = cv::dnn::readNetFromONNX(modelPath);
if (cudaEnabled)
{
std::cout << "\nRunning on CUDA" << std::endl;
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
}
else
{
std::cout << "\nRunning on CPU" << std::endl;
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
}
}
cv::Mat Inference::formatToSquare(const cv::Mat &source)
{
int col = source.cols;
int row = source.rows;
int _max = MAX(col, row);
cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);
source.copyTo(result(cv::Rect(0, 0, col, row)));
return result;
}
inference.h:
#ifndef INFERENCE_H
#define INFERENCE_H
// Cpp native
#include <fstream>
#include <vector>
#include <string>
#include <random>
// OpenCV / DNN / Inference
#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
struct Detection
{
int class_id{0};
std::string className{};
float confidence{0.0};
cv::Scalar color{};
cv::Rect box{};
};
class Inference
{
public:
Inference(const std::string &onnxModelPath, const cv::Size &modelInputShape = {640, 640}, const std::string &classesTxtFile = "", const bool &runWithCuda = true);
std::vector<Detection> runInference(const cv::Mat &input);
private:
void loadClassesFromFile();
void loadOnnxNetwork();
cv::Mat formatToSquare(const cv::Mat &source);
std::string modelPath{};
std::string classesPath{};
bool cudaEnabled{};
std::vector<std::string> classes{"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"};
cv::Size2f modelShape{};
float modelConfidenceThreshold {0.25};
float modelScoreThreshold {0.45};
float modelNMSThreshold {0.50};
bool letterBoxForSquare = true;
cv::dnn::Net net;
};
#endif // INFERENCE_H
3.geotpt文件的配置
geotpt文件的配置比较简单,我们只需要写两个文件放入我们的工程就行,代码如下:
getopt.h
# ifndef __GETOPT_H_
# define __GETOPT_H_
# ifdef _GETOPT_API
# undef _GETOPT_API
# endif
//------------------------------------------------------------------------------
# if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
# error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT \
can only be used individually"
# elif defined(STATIC_GETOPT)
# pragma message("Warning static builds of getopt violate the Lesser GNU \
Public License")
# define _GETOPT_API
# elif defined(EXPORTS_GETOPT)
# pragma message("Exporting getopt library")
# define _GETOPT_API __declspec(dllexport)
# else
# pragma message("Importing getopt library")
# define _GETOPT_API __declspec(dllimport)
# endif
# include <tchar.h>
// Standard GNU options
# define null_argument 0 /*Argument Null*/
# define no_argument 0 /*Argument Switch Only*/
# define required_argument 1 /*Argument Required*/
# define optional_argument 2 /*Argument Optional*/
// Shorter Versions of options
# define ARG_NULL 0 /*Argument Null*/
# define ARG_NONE 0 /*Argument Switch Only*/
# define ARG_REQ 1 /*Argument Required*/
# define ARG_OPT 2 /*Argument Optional*/
// Change behavior for C\C++
# ifdef __cplusplus
# define _BEGIN_EXTERN_C extern "C" {
# define _END_EXTERN_C }
# define _GETOPT_THROW throw()
# else
# define _BEGIN_EXTERN_C
# define _END_EXTERN_C
# define _GETOPT_THROW
# endif
_BEGIN_EXTERN_C
extern _GETOPT_API TCHAR* optarg;
extern _GETOPT_API int optind;
extern _GETOPT_API int opterr;
extern _GETOPT_API int optopt;
struct option
{
/* The predefined macro variable __STDC__ is defined for C++, and it has the in-
teger value 0 when it is used in an #if statement, indicating that the C++ l-
anguage is not a proper superset of C, and that the compiler does not confor-
m to C. In C, __STDC__ has the integer value 1. */
# if defined (__STDC__) && __STDC__
const TCHAR* name;
# else
TCHAR* name;
# endif
int has_arg;
int* flag;
TCHAR val;
};
extern _GETOPT_API int getopt(int argc, TCHAR* const* argv
, const TCHAR* optstring) _GETOPT_THROW;
extern _GETOPT_API int getopt_long
(int ___argc, TCHAR* const* ___argv
, const TCHAR* __shortopts
, const struct option* __longopts
, int* __longind) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only
(int ___argc, TCHAR* const* ___argv
, const TCHAR* __shortopts
, const struct option* __longopts
, int* __longind) _GETOPT_THROW;
// harly.he add for reentrant 12.09/2013
extern _GETOPT_API void getopt_reset() _GETOPT_THROW;
_END_EXTERN_C
// Undefine so the macros are not included
# undef _BEGIN_EXTERN_C
# undef _END_EXTERN_C
# undef _GETOPT_THROW
# undef _GETOPT_API
# endif // __GETOPT_H_
getopt.c
# ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
# endif
# include <stdlib.h>
# include <stdio.h>
# include <tchar.h>
# include "getopt.h"
# ifdef __cplusplus
# define _GETOPT_THROW throw()
# else
# define _GETOPT_THROW
# endif
enum ENUM_ORDERING
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
struct _getopt_data
{
int optind;
int opterr;
int optopt;
TCHAR* optarg;
int __initialized;
TCHAR* __nextchar;
int __ordering;
int __posixly_correct;
int __first_nonopt;
int __last_nonopt;
};
static struct _getopt_data getopt_data = { 0, 0, 0, NULL, 0, NULL, 0, 0, 0, 0 };
TCHAR* optarg = NULL;
int optind = 1;
int opterr = 1;
int optopt = _T('?');
static void exchange(TCHAR** argv, struct _getopt_data* d)
{
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
TCHAR* tem;
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
int len = middle - bottom;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
top -= len;
}
else
{
int len = top - middle;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
bottom += len;
}
}
d->__first_nonopt += (d->optind - d->__last_nonopt);
d->__last_nonopt = d->optind;
}
static const TCHAR* _getopt_initialize(const TCHAR* optstring
, struct _getopt_data* d
, int posixly_correct)
{
d->__first_nonopt = d->__last_nonopt = d->optind;
d->__nextchar = NULL;
d->__posixly_correct = posixly_correct
| !!_tgetenv(_T("POSIXLY_CORRECT"));
if (optstring[0] == _T('-'))
{
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == _T('+'))
{
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if (d->__posixly_correct)
{
d->__ordering = REQUIRE_ORDER;
}
else
{
d->__ordering = PERMUTE;
}
return optstring;
}
int _getopt_internal_r(int argc
, TCHAR* const* argv
, const TCHAR* optstring
, const struct option* longopts
, int* longind
, int long_only
, struct _getopt_data* d
, int posixly_correct)
{
int print_errors = d->opterr;
if (argc < 1)
{
return -1;
}
d->optarg = NULL;
if (d->optind == 0 || !d->__initialized)
{
if (d->optind == 0)
{
d->optind = 1;
}
optstring = _getopt_initialize(optstring, d, posixly_correct);
d->__initialized = 1;
}
else if (optstring[0] == _T('-') || optstring[0] == _T('+'))
{
optstring++;
}
if (optstring[0] == _T(':'))
{
print_errors = 0;
}
if (d->__nextchar == NULL || *d->__nextchar == _T('\0'))
{
if (d->__last_nonopt > d->optind)
{
d->__last_nonopt = d->optind;
}
if (d->__first_nonopt > d->optind)
{
d->__first_nonopt = d->optind;
}
if (d->__ordering == PERMUTE)
{
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
{
exchange((TCHAR**)argv, d);
}
else if (d->__last_nonopt != d->optind)
{
d->__first_nonopt = d->optind;
}
while (d->optind
< argc
&& (argv[d->optind][0] != _T('-')
|| argv[d->optind][1] == _T('\0')))
{
d->optind++;
}
d->__last_nonopt = d->optind;
}
if (d->optind != argc && !_tcscmp(argv[d->optind], _T("--")))
{
d->optind++;
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
{
exchange((TCHAR**)argv, d);
}
else if (d->__first_nonopt == d->__last_nonopt)
{
d->__first_nonopt = d->optind;
}
d->__last_nonopt = argc;
d->optind = argc;
}
if (d->optind == argc)
{
if (d->__first_nonopt != d->__last_nonopt)
{
d->optind = d->__first_nonopt;
}
return -1;
}
if ((argv[d->optind][0] != _T('-')
|| argv[d->optind][1] == _T('\0')))
{
if (d->__ordering == REQUIRE_ORDER)
{
return -1;
}
d->optarg = argv[d->optind++];
return 1;
}
d->__nextchar = (argv[d->optind]
+ 1 + (longopts != NULL
&& argv[d->optind][1] == _T('-')));
}
if (longopts != NULL
&& (argv[d->optind][1] == _T('-')
|| (long_only && (argv[d->optind][2]
|| !_tcschr(optstring, argv[d->optind][1]))
)
)
)
{
TCHAR* nameend;
const struct option* p;
const struct option* pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = -1;
int option_index;
for (nameend = d->__nextchar;
*nameend && *nameend != _T('=');
nameend++)
;
for (p = longopts, option_index = 0; p->name; p++, option_index++)
{
if (!_tcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int)(nameend - d->__nextchar)
== (unsigned int)_tcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only
|| pfound->has_arg != p->has_arg
|| pfound->flag != p->flag
|| pfound->val != p->val)
{
ambig = 1;
}
}
}
if (ambig && !exact)
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option '%s' is ambiguous\n")
, argv[0]
, argv[d->optind]);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optind++;
d->optopt = 0;
return _T('?');
}
if (pfound != NULL)
{
option_index = indfound;
d->optind++;
if (*nameend)
{
if (pfound->has_arg)
{
d->optarg = nameend + 1;
}
else
{
if (print_errors)
{
if (argv[d->optind - 1][1] == _T('-'))
{
_ftprintf(stderr
, _T("%s: option '--%s' doesn't allow ")
_T("an argument\n")
, argv[0]
, pfound->name);
}
else
{
_ftprintf(stderr
, _T("%s: option '%c%s' doesn't allow ")
_T("an argument\n")
, argv[0]
, argv[d->optind - 1][0]
, pfound->name);
}
}
d->__nextchar += _tcslen(d->__nextchar);
d->optopt = pfound->val;
return _T('?');
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
{
d->optarg = argv[d->optind++];
}
else
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option '--%s' requires an ")
_T("argument\n")
, argv[0]
, pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optopt = pfound->val;
return optstring[0] == _T(':') ? _T(':') : _T('?');
}
}
d->__nextchar += _tcslen(d->__nextchar);
if (longind != NULL)
{
*longind = option_index;
}
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
if (!long_only
|| argv[d->optind][1]
== _T('-')
|| _tcschr(optstring
, *d->__nextchar)
== NULL)
{
if (print_errors)
{
if (argv[d->optind][1] == _T('-'))
{
/* --option */
_ftprintf(stderr
, _T("%s: unrecognized option '--%s'\n")
, argv[0]
, d->__nextchar);
}
else
{
/* +option or -option */
_ftprintf(stderr
, _T("%s: unrecognized option '%c%s'\n")
, argv[0]
, argv[d->optind][0]
, d->__nextchar);
}
}
d->__nextchar = (TCHAR*)_T("");
d->optind++;
d->optopt = 0;
return _T('?');
}
}
{
TCHAR c = *d->__nextchar++;
TCHAR* temp = (TCHAR*)_tcschr(optstring, c);
if (*d->__nextchar == _T('\0'))
{
++d->optind;
}
if (temp == NULL || c == _T(':') || c == _T(';'))
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: invalid option -- '%c'\n")
, argv[0]
, c);
}
d->optopt = c;
return _T('?');
}
if (temp[0] == _T('W') && temp[1] == _T(';'))
{
TCHAR* nameend;
const struct option* p;
const struct option* pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option requires an argument -- '%c'\n")
, argv[0]
, c);
}
d->optopt = c;
if (optstring[0] == _T(':'))
{
c = _T(':');
}
else
{
c = _T('?');
}
return c;
}
else
{
d->optarg = argv[d->optind++];
}
for (d->__nextchar = nameend = d->optarg;
*nameend && *nameend != _T('=');
nameend++)
;
for (p = longopts, option_index = 0;
p->name;
p++, option_index++)
{
if (!_tcsncmp(p->name
, d->__nextchar
, nameend - d->__nextchar))
{
if ((unsigned int)(nameend - d->__nextchar)
== _tcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only
|| pfound->has_arg != p->has_arg
|| pfound->flag != p->flag
|| pfound->val != p->val)
{
ambig = 1;
}
}
}
if (ambig && !exact)
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option '-W %s' is ambiguous\n")
, argv[0]
, d->optarg);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optind++;
return _T('?');
}
if (pfound != NULL)
{
option_index = indfound;
if (*nameend)
{
if (pfound->has_arg)
{
d->optarg = nameend + 1;
}
else
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option '-W %s' doesn't allow ")
_T("an argument\n")
, argv[0]
, pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
return _T('?');
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
{
d->optarg = argv[d->optind++];
}
else
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option '-W %s' requires an ")
_T("argument\n")
, argv[0]
, pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
return optstring[0] == _T(':') ? _T(':') : _T('?');
}
}
else
{
d->optarg = NULL;
}
d->__nextchar += _tcslen(d->__nextchar);
if (longind != NULL)
{
*longind = option_index;
}
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
d->__nextchar = NULL;
return _T('W');
}
if (temp[1] == _T(':'))
{
if (temp[2] == _T(':'))
{
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else
{
d->optarg = NULL;
}
d->__nextchar = NULL;
}
else
{
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
_ftprintf(stderr
, _T("%s: option requires an ")
_T("argument -- '%c'\n")
, argv[0]
, c);
}
d->optopt = c;
if (optstring[0] == _T(':'))
{
c = _T(':');
}
else
{
c = _T('?');
}
}
else
{
d->optarg = argv[d->optind++];
}
d->__nextchar = NULL;
}
}
return c;
}
}
int _getopt_internal(int argc
, TCHAR* const* argv
, const TCHAR* optstring
, const struct option* longopts
, int* longind
, int long_only
, int posixly_correct)
{
int result;
getopt_data.optind = optind;
getopt_data.opterr = opterr;
result = _getopt_internal_r(argc
, argv
, optstring
, longopts
, longind
, long_only
, &getopt_data
, posixly_correct);
optind = getopt_data.optind;
optarg = getopt_data.optarg;
optopt = getopt_data.optopt;
return result;
}
int getopt(int argc, TCHAR* const* argv, const TCHAR* optstring) _GETOPT_THROW
{
return _getopt_internal(argc
, argv
, optstring
, (const struct option*)0
, (int*)0
, 0
, 0);
}
int getopt_long(int argc
, TCHAR* const* argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index) _GETOPT_THROW
{
return _getopt_internal(argc
, argv
, options
, long_options
, opt_index
, 0
, 0);
}
int _getopt_long_r(int argc
, TCHAR* const* argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index
, struct _getopt_data* d)
{
return _getopt_internal_r(argc
, argv
, options
, long_options
, opt_index
, 0
, d
, 0);
}
int getopt_long_only(int argc
, TCHAR* const* argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index) _GETOPT_THROW
{
return _getopt_internal(argc
, argv
, options
, long_options
, opt_index
, 1
, 0);
}
int _getopt_long_only_r(int argc
, TCHAR* const* argv
, const TCHAR* options
, const struct option* long_options
, int* opt_index
, struct _getopt_data* d)
{
return _getopt_internal_r(argc
, argv
, options
, long_options
, opt_index
, 1
, d
, 0);
}
void getopt_reset()
{
optarg = NULL;
optind = 1;
opterr = 1;
optopt = _T('?');
//
getopt_data.optind = 0;
getopt_data.opterr = 0;
getopt_data.optopt = 0;
getopt_data.optarg = NULL;
getopt_data.__initialized = 0;
getopt_data.__nextchar = NULL;
getopt_data.__ordering = 0;
getopt_data.__posixly_correct = 0;
getopt_data.__first_nonopt = 0;
getopt_data.__last_nonopt = 0;
}
做完以上步骤后,就可以进行预测了。
注意:最好配置opencv4.8.1,其他版本的opencv可能会报如下错误:
4.yolov8的pt文件转为onnx文件
首先我们将终端运行的文件夹转换到yolov8文件的test文件夹下,这个文件夹是官方自带的文件夹,如下图所示
然后我们在该终端下运行代码
yolo mode=export model=runs/detect/train/weights/best.pt imgsz=[640,640] format=onnx opset=11
注意,代码后的opset=11不能改变,否则在c++调用时会报错。然后转好的best.onnx文件就在.ultralytics-main\tests\runs\detect\train\weights文件夹下了。
然后,我们将该onnx文件用c++调用如下:
#include <iostream>
#include <string>
#include <onnxruntime_cxx_api.h>
#include<opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
int main()
{
cv::dnn::Net net = cv::dnn::readNetFromONNX("E:\\best.onnx"); // 加载模型
return 0;
}
打印结果如下:
显然,没有报错.
运行以上的yolov8的模型结果如下: