first commit
|
|
@ -1,57 +1,75 @@
|
|||
#include <iostream>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "../Yolo11_ONNX/Yolo_ONNX.h" // 包含DLL的头文件
|
||||
#include <vector> //
|
||||
#include "../Yolo11_ONNX/Yolo_ONNX.h" //
|
||||
|
||||
int main()
|
||||
{
|
||||
// --- 1. 准备输入和参数 ---
|
||||
const wchar_t* model_path = L"D:/dev/models/best.onnx";
|
||||
cv::Mat image = cv::imread("D:/dev/dataset/003.jpg");
|
||||
const wchar_t* model_path = L"D:/dev/models/best_fixed_dim.onnx";
|
||||
|
||||
if (image.empty()) {
|
||||
std::cerr << "Error: Could not read the image." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
//
|
||||
//
|
||||
std::vector<std::string> image_paths = {
|
||||
|
||||
// 【新增】将所有可配置参数定义在这里,方便修改
|
||||
const float conf_threshold = 0.9f;
|
||||
"D:/dev/dataset/qd/1.jpg",
|
||||
"D:/dev/dataset/qd/2.jpg",
|
||||
"D:/dev/dataset/qd/3.jpg",
|
||||
"D:/dev/dataset/qd/4.jpg",
|
||||
"D:/dev/dataset/qd/5.jpg"
|
||||
};
|
||||
|
||||
const float conf_threshold = 0.15f;
|
||||
const float iou_threshold = 0.45f;
|
||||
const int input_width = 2016;
|
||||
const int input_height = 1536;
|
||||
const int input_width = 640;
|
||||
const int input_height = 640;
|
||||
|
||||
const char* class_names[] = { /* ... 您的类别列表 ... */ "tiaojuan", "zhujiesi", "yulingwen" }; // 示例
|
||||
const char* class_names[] = { "qd", "fl", "zw" };
|
||||
int class_count = sizeof(class_names) / sizeof(class_names[0]);
|
||||
|
||||
// --- 2. 调用更新后的DLL函数 ---
|
||||
|
||||
std::cout << "Loading model... (This happens only once)" << std::endl;
|
||||
void* detector_handle = create_detector(model_path, input_width, input_height);
|
||||
|
||||
if (detector_handle == nullptr) {
|
||||
std::cerr << "Error: Failed to create detector." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
std::cout << "Model loaded successfully." << std::endl;
|
||||
|
||||
for (const auto& image_path : image_paths)
|
||||
{
|
||||
std::cout << "\n--- Processing image: " << image_path << " ---" << std::endl;
|
||||
cv::Mat image = cv::imread(image_path);
|
||||
|
||||
if (image.empty()) {
|
||||
std::cerr << "Error: Could not read image " << image_path << std::endl;
|
||||
continue; //
|
||||
}
|
||||
|
||||
//
|
||||
Detection* detections = nullptr;
|
||||
int detections_count = 0;
|
||||
|
||||
std::cout << "Performing detection with conf=" << conf_threshold << ", iou=" << iou_threshold << ", size=" << input_width << "x" << input_height << std::endl;
|
||||
|
||||
int result = perform_detection(
|
||||
model_path,
|
||||
//
|
||||
int result = perform_detection_on_session(
|
||||
detector_handle, //
|
||||
image.data,
|
||||
image.cols,
|
||||
image.rows,
|
||||
&detections,
|
||||
&detections_count,
|
||||
class_names,
|
||||
class_count,
|
||||
conf_threshold,
|
||||
iou_threshold,
|
||||
input_width,
|
||||
input_height
|
||||
iou_threshold
|
||||
);
|
||||
|
||||
if (result != 0) {
|
||||
std::cerr << "Detection failed with code: " << result << std::endl;
|
||||
free_memory(detections);
|
||||
return -1;
|
||||
free_memory(detections); //
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "Detection successful. Found " << detections_count << " objects." << std::endl;
|
||||
|
||||
// --- 3. 打印检测结果 ---
|
||||
for (int i = 0; i < detections_count; ++i) {
|
||||
const auto& d = detections[i];
|
||||
std::cout << " - Class: " << class_names[d.class_id]
|
||||
|
|
@ -59,7 +77,6 @@ int main()
|
|||
<< ", Box: [" << d.x << ", " << d.y << ", " << d.width << ", " << d.height << "]" << std::endl;
|
||||
}
|
||||
|
||||
// --- 4. 调用DLL函数绘制结果并显示 ---
|
||||
unsigned char* output_image_bytes = nullptr;
|
||||
int output_image_size = 0;
|
||||
|
||||
|
|
@ -79,28 +96,23 @@ int main()
|
|||
std::vector<unsigned char> buffer(output_image_bytes, output_image_bytes + output_image_size);
|
||||
cv::Mat result_image = cv::imdecode(buffer, cv::IMREAD_COLOR);
|
||||
|
||||
// 定义要保存的文件名
|
||||
std::string output_filename = "detection_result.jpg";
|
||||
|
||||
// 使用 OpenCV 的 imwrite 函数将图片保存到硬盘
|
||||
bool success = cv::imwrite(output_filename, result_image);
|
||||
|
||||
// 检查是否保存成功并打印提示信息
|
||||
if (success) {
|
||||
std::cout << "Annotated image successfully saved to: " << output_filename << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error: Failed to save the annotated image." << std::endl;
|
||||
}
|
||||
//
|
||||
std::string output_filename = "result_" + image_path.substr(image_path.find_last_of('/') + 1);
|
||||
cv::imwrite(output_filename, result_image);
|
||||
std::cout << "Annotated image saved to: " << output_filename << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// --- 5. 释放内存 ---
|
||||
std::cout << "Freeing memory..." << std::endl;
|
||||
// --- 5. [修改]
|
||||
//
|
||||
free_memory(detections);
|
||||
free_image_memory(output_image_bytes);
|
||||
|
||||
std::cout << "Done." << std::endl;
|
||||
} //
|
||||
|
||||
// --- 6. [新增]
|
||||
std::cout << "\nFreeing detector model..." << std::endl;
|
||||
free_detector(detector_handle);
|
||||
|
||||
std::cout << "Done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.8 MiB |
|
After Width: | Height: | Size: 6.1 MiB |
|
After Width: | Height: | Size: 4.8 MiB |
|
After Width: | Height: | Size: 6.1 MiB |
|
After Width: | Height: | Size: 6.2 MiB |
|
After Width: | Height: | Size: 5.3 MiB |
|
After Width: | Height: | Size: 5.8 MiB |
|
After Width: | Height: | Size: 5.1 MiB |
|
After Width: | Height: | Size: 4.8 MiB |
|
|
@ -1,8 +1,7 @@
|
|||
// YoloV8_ONNX.cpp (最终优化版)
|
||||
|
||||
#include "pch.h"
|
||||
#include "Yolo_ONNX.h"
|
||||
|
||||
//
|
||||
#include <onnxruntime_c_api.h>
|
||||
#include <onnxruntime_cxx_api.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
|
@ -10,10 +9,101 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <stdexcept> //
|
||||
|
||||
namespace {
|
||||
|
||||
// 【优化】预处理函数
|
||||
cv::Mat preprocess(const cv::Mat& img, int target_width, int target_height, int& pad_w, int& pad_h, float& scale);
|
||||
|
||||
std::vector<Detection> postprocess(Ort::Value& output_tensor, float scale, int pad_w, int pad_h, int img_w, int img_h, float conf_threshold, float iou_threshold);
|
||||
|
||||
class YoloDetector {
|
||||
public:
|
||||
//
|
||||
Ort::Env env;
|
||||
std::unique_ptr<Ort::Session> session;
|
||||
|
||||
//
|
||||
int input_width = 0;
|
||||
int input_height = 0;
|
||||
|
||||
//
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
std::string input_name_str;
|
||||
std::string output_name_str;
|
||||
std::vector<const char*> input_node_names;
|
||||
std::vector<const char*> output_node_names;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
YoloDetector(const wchar_t* model_path, int in_width, int in_height)
|
||||
: env(ORT_LOGGING_LEVEL_WARNING, "YOLOv8-ONNX-GPU"),
|
||||
input_width(in_width),
|
||||
input_height(in_height)
|
||||
{
|
||||
//
|
||||
Ort::SessionOptions session_options;
|
||||
OrtCUDAProviderOptions cuda_options; //
|
||||
session_options.AppendExecutionProvider_CUDA(cuda_options);
|
||||
|
||||
//
|
||||
session = std::make_unique<Ort::Session>(env, model_path, session_options);
|
||||
|
||||
//
|
||||
//
|
||||
input_name_str = session->GetInputNameAllocated(0, allocator).get();
|
||||
output_name_str = session->GetOutputNameAllocated(0, allocator).get();
|
||||
input_node_names.push_back(input_name_str.c_str());
|
||||
output_node_names.push_back(output_name_str.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
std::vector<Detection> detect(
|
||||
unsigned char* image_bytes,
|
||||
int image_width,
|
||||
int image_height,
|
||||
float conf_threshold,
|
||||
float iou_threshold)
|
||||
{
|
||||
//
|
||||
cv::Mat image(image_height, image_width, CV_8UC3, image_bytes);
|
||||
if (image.empty()) {
|
||||
throw std::runtime_error("Input image is empty.");
|
||||
}
|
||||
|
||||
//
|
||||
int pad_w, pad_h;
|
||||
float scale;
|
||||
cv::Mat preprocessed_img = preprocess(image, input_width, input_height, pad_w, pad_h, scale); //
|
||||
|
||||
//
|
||||
cv::Mat blob;
|
||||
cv::dnn::blobFromImage(preprocessed_img, blob, 1 / 255.0, cv::Size(), cv::Scalar(), true, false);
|
||||
std::vector<int64_t> input_shape = { 1, 3, (int64_t)input_height, (int64_t)input_width };
|
||||
std::cout <<"input shape: " << input_shape[0] << "," << input_shape[1] << "," << input_shape[2] << "," << input_shape[3] << "," << std::endl;
|
||||
|
||||
//
|
||||
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
|
||||
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, blob.ptr<float>(), blob.total(), input_shape.data(), input_shape.size());
|
||||
|
||||
//
|
||||
auto output_tensors = session->Run(Ort::RunOptions{ nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
|
||||
|
||||
//
|
||||
return postprocess(output_tensors[0], scale, pad_w, pad_h, image_width, image_height, conf_threshold, iou_threshold);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ========================================================================
|
||||
//
|
||||
// ========================================================================
|
||||
|
||||
//
|
||||
cv::Mat preprocess(const cv::Mat& img, int target_width, int target_height, int& pad_w, int& pad_h, float& scale) {
|
||||
cv::Mat resized_img;
|
||||
int w = img.cols;
|
||||
|
|
@ -21,31 +111,35 @@ namespace {
|
|||
scale = std::min(static_cast<float>(target_width) / w, static_cast<float>(target_height) / h);
|
||||
int new_w = static_cast<int>(w * scale);
|
||||
int new_h = static_cast<int>(h * scale);
|
||||
|
||||
// 【优化】使用 INTER_AREA 插值算法,更适合图像缩小,与主流Python库行为更接近
|
||||
cv::resize(img, resized_img, cv::Size(new_w, new_h), 0, 0, cv::INTER_AREA);
|
||||
|
||||
pad_w = target_width - new_w;
|
||||
pad_h = target_height - new_h;
|
||||
pad_w = target_width - new_w; //
|
||||
pad_h = target_height - new_h; //
|
||||
|
||||
//
|
||||
int top = pad_h / 2;
|
||||
int bottom = pad_h - top;
|
||||
int left = pad_w / 2;
|
||||
int right = pad_w - left;
|
||||
//
|
||||
|
||||
cv::Mat padded_img;
|
||||
cv::copyMakeBorder(resized_img, padded_img, 0, pad_h, 0, pad_w, cv::BORDER_CONSTANT, cv::Scalar(114, 114, 114));
|
||||
//
|
||||
cv::copyMakeBorder(resized_img, padded_img, top, bottom, left, right, cv::BORDER_CONSTANT, cv::Scalar(114, 114, 114));
|
||||
return padded_img;
|
||||
}
|
||||
|
||||
// 后处理函数
|
||||
//
|
||||
std::vector<Detection> postprocess(Ort::Value& output_tensor, float scale, int pad_w, int pad_h, int img_w, int img_h, float conf_threshold, float iou_threshold) {
|
||||
const auto output_shape = output_tensor.GetTensorTypeAndShapeInfo().GetShape();
|
||||
const float* raw_output = output_tensor.GetTensorData<float>();
|
||||
int num_classes = static_cast<int>(output_shape[1]) - 4;
|
||||
int num_proposals = static_cast<int>(output_shape[2]);
|
||||
|
||||
std::vector<cv::Rect> boxes;
|
||||
std::vector<float> scores;
|
||||
std::vector<int> class_ids;
|
||||
|
||||
cv::Mat raw_data_mat(num_classes + 4, num_proposals, CV_32F, (void*)raw_output);
|
||||
raw_data_mat = raw_data_mat.t();
|
||||
|
||||
for (int i = 0; i < num_proposals; ++i) {
|
||||
const float* proposal = raw_data_mat.ptr<float>(i);
|
||||
const float* class_scores = proposal + 4;
|
||||
|
|
@ -63,7 +157,7 @@ namespace {
|
|||
float w = proposal[2];
|
||||
float h = proposal[3];
|
||||
int left = static_cast<int>((cx - w / 2 - (pad_w / 2.0f)) / scale);
|
||||
int top = static_cast<int>((cy - h / 2 - (pad_h / 2.0f)) / scale);
|
||||
int top = static_cast<int>((cy - h / 2 - (pad_w / 2.0f)) / scale);
|
||||
int width = static_cast<int>(w / scale);
|
||||
int height = static_cast<int>(h / scale);
|
||||
left = std::max(0, std::min(left, img_w - 1));
|
||||
|
|
@ -75,7 +169,6 @@ namespace {
|
|||
class_ids.push_back(class_id);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> nms_result;
|
||||
cv::dnn::NMSBoxes(boxes, scores, conf_threshold, iou_threshold, nms_result);
|
||||
std::vector<Detection> detections;
|
||||
|
|
@ -84,11 +177,92 @@ namespace {
|
|||
}
|
||||
return detections;
|
||||
}
|
||||
}
|
||||
} //
|
||||
|
||||
|
||||
extern "C" {
|
||||
// 【修改】函数签名更新,增加了四个新参数
|
||||
|
||||
// ========================================================================
|
||||
//
|
||||
// ========================================================================
|
||||
|
||||
YOLO_API void* create_detector(
|
||||
const wchar_t* model_path,
|
||||
int input_width,
|
||||
int input_height)
|
||||
{
|
||||
try {
|
||||
//
|
||||
YoloDetector* detector = new YoloDetector(model_path, input_width, input_height);
|
||||
//
|
||||
return static_cast<void*>(detector);
|
||||
}
|
||||
catch (const Ort::Exception& e) {
|
||||
std::cerr << "ONNX Runtime Error creating detector: " << e.what() << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error creating detector: " << e.what() << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
YOLO_API void free_detector(void* detector_handle)
|
||||
{
|
||||
if (detector_handle) {
|
||||
YoloDetector* detector = static_cast<YoloDetector*>(detector_handle);
|
||||
delete detector;
|
||||
}
|
||||
}
|
||||
|
||||
YOLO_API int perform_detection_on_session(
|
||||
void* detector_handle,
|
||||
unsigned char* image_bytes,
|
||||
int image_width,
|
||||
int image_height,
|
||||
Detection** out_detections,
|
||||
int* out_detections_count,
|
||||
float conf_threshold,
|
||||
float iou_threshold)
|
||||
{
|
||||
if (!detector_handle) return -1; //
|
||||
|
||||
//
|
||||
YoloDetector* detector = static_cast<YoloDetector*>(detector_handle);
|
||||
|
||||
try {
|
||||
//
|
||||
std::vector<Detection> detections = detector->detect(
|
||||
image_bytes, image_width, image_height,
|
||||
conf_threshold, iou_threshold
|
||||
);
|
||||
|
||||
//
|
||||
*out_detections_count = static_cast<int>(detections.size());
|
||||
if (*out_detections_count > 0) {
|
||||
*out_detections = new Detection[*out_detections_count];
|
||||
std::copy(detections.begin(), detections.end(), *out_detections);
|
||||
}
|
||||
else {
|
||||
*out_detections = nullptr;
|
||||
}
|
||||
return 0; //
|
||||
}
|
||||
catch (const Ort::Exception& e) {
|
||||
std::cerr << "ONNX Runtime Error during detection: " << e.what() << std::endl;
|
||||
return -2;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error during detection: " << e.what() << std::endl;
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
//
|
||||
// ========================================================================
|
||||
|
||||
YOLO_API int perform_detection(
|
||||
const wchar_t* model_path,
|
||||
unsigned char* image_bytes,
|
||||
|
|
@ -98,18 +272,17 @@ extern "C" {
|
|||
int* out_detections_count,
|
||||
const char** class_names,
|
||||
int class_names_count,
|
||||
float conf_threshold, // 使用传入的置信度阈值
|
||||
float iou_threshold, // 使用传入的IOU阈值
|
||||
int input_width, // 使用传入的模型输入宽度
|
||||
int input_height // 使用传入的模型输入高度
|
||||
float conf_threshold,
|
||||
float iou_threshold,
|
||||
int input_width,
|
||||
int input_height
|
||||
) {
|
||||
//
|
||||
static Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "YOLOv8-ONNX-GPU");
|
||||
static std::unique_ptr<Ort::Session> session = nullptr;
|
||||
// 【新增】用于判断模型是否需要重新加载的变量
|
||||
static std::wstring current_model_path = L"";
|
||||
|
||||
try {
|
||||
// 如果模型路径发生变化,则重新创建Session
|
||||
if (!session || current_model_path != model_path) {
|
||||
Ort::SessionOptions session_options;
|
||||
OrtCUDAProviderOptions cuda_options;
|
||||
|
|
@ -118,13 +291,10 @@ extern "C" {
|
|||
current_model_path = model_path;
|
||||
}
|
||||
|
||||
// 【修改】移除硬编码的尺寸,使用接口传入的参数
|
||||
std::vector<int64_t> input_shape = { 1, 3, input_height, input_width };
|
||||
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
std::string input_name_str = session->GetInputNameAllocated(0, allocator).get();
|
||||
std::vector<const char*> input_node_names = { input_name_str.c_str() };
|
||||
|
||||
std::string output_name_str = session->GetOutputNameAllocated(0, allocator).get();
|
||||
std::vector<const char*> output_node_names = { output_name_str.c_str() };
|
||||
|
||||
|
|
@ -133,17 +303,15 @@ extern "C" {
|
|||
|
||||
int pad_w, pad_h;
|
||||
float scale;
|
||||
// 【修改】使用接口传入的参数进行预处理
|
||||
cv::Mat preprocessed_img = preprocess(image, input_width, input_height, pad_w, pad_h, scale);
|
||||
|
||||
cv::Mat blob;
|
||||
cv::dnn::blobFromImage(preprocessed_img, blob, 1 / 255.0, cv::Size(), cv::Scalar(), false, false);
|
||||
cv::dnn::blobFromImage(preprocessed_img, blob, 1 / 255.0, cv::Size(), cv::Scalar(), true, false);
|
||||
|
||||
auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
|
||||
Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, blob.ptr<float>(), blob.total(), input_shape.data(), input_shape.size());
|
||||
auto output_tensors = session->Run(Ort::RunOptions{ nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
|
||||
|
||||
// 【修改】使用接口传入的参数进行后处理
|
||||
std::vector<Detection> detections = postprocess(output_tensors[0], scale, pad_w, pad_h, image_width, image_height, conf_threshold, iou_threshold);
|
||||
|
||||
*out_detections_count = static_cast<int>(detections.size());
|
||||
|
|
@ -170,7 +338,7 @@ extern "C" {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// 以下函数保持不变
|
||||
//
|
||||
YOLO_API void free_memory(Detection* detections) {
|
||||
delete[] detections;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
//
|
||||
#ifdef YOLO_EXPORTS
|
||||
#define YOLO_API __declspec(dllexport)
|
||||
#else
|
||||
|
|
@ -8,6 +9,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
//
|
||||
struct Detection
|
||||
{
|
||||
int class_id;
|
||||
|
|
@ -19,6 +21,63 @@ struct Detection
|
|||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
// ========================================================================
|
||||
//
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief [新增] 创建一个检测器实例 (有状态)
|
||||
* @details 此函数加载ONNX模型并初始化Session,返回一个句柄。
|
||||
* @param model_path ONNX模型的绝对路径
|
||||
* @param input_width 模型输入宽度 (例如 640)
|
||||
* @param input_height 模型输入高度 (例如 640)
|
||||
* @return void* 指向检测器实例的句柄。如果失败则返回 nullptr。
|
||||
*/
|
||||
YOLO_API void* create_detector(
|
||||
const wchar_t* model_path,
|
||||
int input_width,
|
||||
int input_height
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief [新增] 释放由 create_detector 创建的检测器实例
|
||||
* @param detector_handle 要释放的句柄
|
||||
*/
|
||||
YOLO_API void free_detector(void* detector_handle);
|
||||
|
||||
/**
|
||||
* @brief [新增] 使用已加载的检测器执行检测 (线程安全)
|
||||
* @details
|
||||
* @param detector_handle 由 create_detector 返回的句柄
|
||||
* @param image_bytes 指向图像数据(BGR格式)的指针
|
||||
* @param image_width 图像宽度
|
||||
* @param image_height 图像高度
|
||||
* @param out_detections [输出] Detection结构体数组指针
|
||||
* @param out_detections_count [输出] 检测到的物体数量
|
||||
* @param conf_threshold 置信度阈值
|
||||
* @param iou_threshold NMS的IOU阈值
|
||||
* @return int 0表示成功
|
||||
*/
|
||||
YOLO_API int perform_detection_on_session(
|
||||
void* detector_handle,
|
||||
unsigned char* image_bytes,
|
||||
int image_width,
|
||||
int image_height,
|
||||
Detection** out_detections,
|
||||
int* out_detections_count,
|
||||
float conf_threshold,
|
||||
float iou_threshold
|
||||
);
|
||||
|
||||
|
||||
// ========================================================================
|
||||
//
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* @brief [保留] 原始的无状态检测函数 (非线程安全)
|
||||
*/
|
||||
YOLO_API int perform_detection(
|
||||
const wchar_t* model_path,
|
||||
unsigned char* image_bytes,
|
||||
|
|
@ -34,8 +93,14 @@ extern "C" {
|
|||
int input_height // Ä£ÐÍÊäÈë¸ß¶È (ÀýÈç 640)
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief [保留] 释放由 perform_detection* 分配的内存
|
||||
*/
|
||||
YOLO_API void free_memory(Detection* detections);
|
||||
|
||||
/**
|
||||
* @brief [保留] 绘制函数
|
||||
*/
|
||||
YOLO_API void draw_and_encode_image(
|
||||
unsigned char* image_bytes,
|
||||
int image_width,
|
||||
|
|
@ -48,5 +113,8 @@ extern "C" {
|
|||
int* out_image_size
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief [保留] 释放由 draw_and_encode_image 分配的内存
|
||||
*/
|
||||
YOLO_API void free_image_memory(unsigned char* image_bytes);
|
||||
}
|
||||