Add unit tests
This commit is contained in:
1912
tests/ANSODEngine-UnitTest/ANSODEngine-UnitTest.cpp
Normal file
1912
tests/ANSODEngine-UnitTest/ANSODEngine-UnitTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2744
tests/ANSODEngine-UnitTest/ANSODTest.cpp
Normal file
2744
tests/ANSODEngine-UnitTest/ANSODTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
119
tests/ANSODEngine-UnitTest/ANSODTest.h
Normal file
119
tests/ANSODEngine-UnitTest/ANSODTest.h
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include "boost/property_tree/ptree.hpp"
|
||||
#include "boost/property_tree/json_parser.hpp"
|
||||
#include "boost/foreach.hpp"
|
||||
#include "boost/optional.hpp"
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
#include "ANSODEngine.h"
|
||||
#include "openvino/openvino.hpp"
|
||||
#include <iostream>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include "format_reader/include/format_reader_ptr.h"
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <openvino/op/transpose.hpp>
|
||||
#include <openvino/core/node.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <fstream>
|
||||
//#include "inference_engine.hpp"
|
||||
#include <filesystem>
|
||||
#include "ANSPOSE.h"
|
||||
#include "ANSSAM.h"
|
||||
#include "ANSEngineCommon.h"
|
||||
#include "ANSLPR.h"
|
||||
#include "ANSLPR_CPU.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace dnn;
|
||||
template<typename T>
|
||||
T GetOptionalValue(const boost::property_tree::ptree& pt, std::string attribute, T defaultValue) {
|
||||
if (pt.count(attribute)) {
|
||||
return pt.get<T>(attribute);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
template <typename T>
|
||||
T GetData(const boost::property_tree::ptree& pt, const std::string& key)
|
||||
{
|
||||
T ret;
|
||||
if (boost::optional<T> data = pt.get_optional<T>(key))
|
||||
{
|
||||
ret = data.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Could not read the data from ptree: [key: " + key + "]");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int GPUYolov10EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int OpenVINOYolov10EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int OpenVINOYolov10EngineUnitTestLoop(std::string modelFilePath, std::string videoFilePath);
|
||||
int GPUEngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int ONNXEngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int GPUEngineImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int OpenVINOEngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int FacialDetectorTest(std::string modelFilePath, std::string imagePath);
|
||||
int AnomalibTest(std::string abmodelFilePath, std::string abImageFilePath);
|
||||
int HumanPoseTest(std::string modelFilePath, std::string imagePath);
|
||||
int HumanPoseImageTest(std::string modelFilePath, std::string imagePath);
|
||||
int ANSSAMTest(std::string modelFilePath, std::string imagePath);
|
||||
int ODHUBAPITest(std::string modelFilePath, std::string videoFilePath);
|
||||
int ODHUBOpenCVAPITest(std::string modelFilePath, std::string videoFilePath);
|
||||
int ALPRPipeLineTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int ODHUBAPIImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int ODHUBCVAPIImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int CustomCodeImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int UnitTests();
|
||||
int FallDetection();
|
||||
int HeadDetection();
|
||||
int FireNSmokeDetection();
|
||||
int VehicleDetection();
|
||||
void TestODHUB();
|
||||
void DissemTest();
|
||||
int DissemParallelTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int CustomTest();
|
||||
int CocoTest();
|
||||
int PersonHead();
|
||||
int GenericModelTest();
|
||||
int FaceDetector(std::string modelFilePath, std::string videoFilePath);
|
||||
int TiledInferenceTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int NormalInferenceTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int TiledInferenceTest();
|
||||
int MotionDetection(std::string modelFilePath, std::string videoFilePath);
|
||||
int MotionDetectionForFireNSmoke();
|
||||
int StressTest();
|
||||
int GPU11EngineImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int GPU11EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int Yolov11RT_Test();
|
||||
int Yolov10RT_Test();
|
||||
int OpenVINOCLEngineImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int TENSORRTCLEngineImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int TestCL();
|
||||
int Engine_Test();
|
||||
int SegEngineImageTest(std::string modelFilePath, std::string imageFilePath);
|
||||
int SegmentationTest();
|
||||
int Yolov8EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int Yolov5EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int Yolov12EngineUnitTest(std::string modelFilePath, std::string videoFilePath);
|
||||
int LocSetTest();
|
||||
int RectifierTest();
|
||||
int FaceTest();
|
||||
int FaceOVTest();
|
||||
int FaceYoloTest();
|
||||
int TestYOLOV12();
|
||||
int PPETest();
|
||||
int RVATest();
|
||||
int CustomModel_StressTest_FilePlayer();
|
||||
154
tests/ANSODEngine-UnitTest/ANSSAM3-UnitTest.cpp
Normal file
154
tests/ANSODEngine-UnitTest/ANSSAM3-UnitTest.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// Separate translation unit for ANSSAM3 (TensorRT) tests.
|
||||
// TensorRT/CUDA headers conflict with Windows SDK (ACCESS_MASK ambiguous symbol)
|
||||
// when included in the same .cpp as ONNX Runtime headers, so we isolate them here.
|
||||
|
||||
#include "ANSSAM3.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
int SAM3TRT_UnitTest()
|
||||
{
|
||||
std::string videoFile = "E:\\Programs\\DemoAssets\\Videos\\video_20.mp4";
|
||||
std::string modelFolder = "C:\\Projects\\ANSVIS\\Models\\ANS_SAM_v3.0";
|
||||
|
||||
ANSCENTER::ANSSAM3 infHandle;
|
||||
ANSCENTER::ModelConfig modelConfig;
|
||||
modelConfig.modelConfThreshold = 0.5f;
|
||||
std::string labelmap;
|
||||
|
||||
if (!infHandle.LoadModelFromFolder("", modelConfig, "anssam3", "", modelFolder, labelmap)) {
|
||||
std::cerr << "SAM3TRT_UnitTest: LoadModelFromFolder failed\n";
|
||||
return -1;
|
||||
}
|
||||
infHandle.SetPrompt("person");
|
||||
|
||||
cv::VideoCapture capture(videoFile);
|
||||
if (!capture.isOpened()) {
|
||||
std::cerr << "SAM3TRT_UnitTest: could not open video file\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cv::Mat frame;
|
||||
if (!capture.read(frame)) {
|
||||
std::cout << "\nEnd of video.\n";
|
||||
break;
|
||||
}
|
||||
auto start = std::chrono::system_clock::now();
|
||||
std::vector<ANSCENTER::Object> masks = infHandle.RunInference(frame);
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
printf("Time = %lld ms\n", static_cast<long long int>(elapsed.count()));
|
||||
|
||||
for (size_t i = 0; i < masks.size(); i++) {
|
||||
cv::rectangle(frame, masks[i].box, 123, 2);
|
||||
}
|
||||
cv::imshow("SAM3 TensorRT Test", frame);
|
||||
if (cv::waitKey(30) == 27) break;
|
||||
}
|
||||
capture.release();
|
||||
cv::destroyAllWindows();
|
||||
infHandle.Destroy();
|
||||
std::cout << "SAM3TRT_UnitTest: done.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SAM3TRT_ImageTest()
|
||||
{
|
||||
std::string modelFilePath = "C:\\Projects\\ANSVIS\\Models\\ANS_SAM_v3.0.zip";
|
||||
|
||||
std::string modelFolder = "C:\\Projects\\ANSVIS\\Models\\ANS_SAM_v3.0";
|
||||
std::string imageFile = "C:\\Projects\\Research\\sam3onnx\\sam3-onnx\\images\\dog.jpg";
|
||||
|
||||
ANSCENTER::ANSSAM3 infHandle;
|
||||
ANSCENTER::ModelConfig modelConfig;
|
||||
modelConfig.modelConfThreshold = 0.5f;
|
||||
std::string labelmap;
|
||||
std::string licenseKey = "";
|
||||
std::string modelZipFilePassword = "";
|
||||
if (!infHandle.Initialize(licenseKey, modelConfig, modelFilePath, modelZipFilePassword, labelmap)) {
|
||||
std::cerr << "SAM3TRT_ImageTest: LoadModelFromFolder failed\n";
|
||||
return -1;
|
||||
}
|
||||
infHandle.SetPrompt("dog");
|
||||
|
||||
cv::Mat image = cv::imread(imageFile);
|
||||
if (image.empty()) {
|
||||
std::cerr << "SAM3TRT_ImageTest: could not read image: " << imageFile << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int NUM_RUNS = 5;
|
||||
for (int run = 0; run < NUM_RUNS; run++) {
|
||||
auto start = std::chrono::system_clock::now();
|
||||
std::vector<ANSCENTER::Object> results = infHandle.RunInference(image);
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
|
||||
std::cout << "SAM3TRT_ImageTest run " << (run + 1) << "/" << NUM_RUNS
|
||||
<< ": " << results.size() << " detections in "
|
||||
<< elapsed.count() << " ms\n";
|
||||
|
||||
if (run == NUM_RUNS - 1) {
|
||||
for (size_t i = 0; i < results.size(); i++) {
|
||||
const auto& obj = results[i];
|
||||
std::cout << " [" << i << "] box=" << obj.box
|
||||
<< " conf=" << obj.confidence
|
||||
<< " polygon=" << obj.polygon.size() << " pts\n";
|
||||
|
||||
// Draw bounding box
|
||||
cv::Scalar boxColor(0, 255, 0);
|
||||
cv::rectangle(image, obj.box, boxColor, 2);
|
||||
|
||||
// Draw label
|
||||
std::string label = obj.className + " " + std::to_string(obj.confidence).substr(0, 4);
|
||||
int baseline = 0;
|
||||
cv::Size textSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseline);
|
||||
cv::rectangle(image,
|
||||
cv::Point(obj.box.x, obj.box.y - textSize.height - 4),
|
||||
cv::Point(obj.box.x + textSize.width, obj.box.y),
|
||||
boxColor, cv::FILLED);
|
||||
cv::putText(image, label, cv::Point(obj.box.x, obj.box.y - 2),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1, cv::LINE_AA);
|
||||
|
||||
// Draw polygon (normalized coordinates)
|
||||
if (obj.polygon.size() >= 3) {
|
||||
std::vector<cv::Point> polyPts;
|
||||
polyPts.reserve(obj.polygon.size());
|
||||
for (const auto& pt : obj.polygon) {
|
||||
polyPts.emplace_back(
|
||||
static_cast<int>(pt.x * image.cols),
|
||||
static_cast<int>(pt.y * image.rows));
|
||||
}
|
||||
cv::Mat overlay = image.clone();
|
||||
std::vector<std::vector<cv::Point>> polys = { polyPts };
|
||||
cv::Scalar polyColor((i * 67 + 50) % 256, (i * 123 + 100) % 256, (i * 37 + 150) % 256);
|
||||
cv::fillPoly(overlay, polys, polyColor);
|
||||
cv::addWeighted(overlay, 0.4, image, 0.6, 0, image);
|
||||
cv::polylines(image, polys, true, polyColor, 2, cv::LINE_AA);
|
||||
}
|
||||
// Mask overlay fallback
|
||||
else if (!obj.mask.empty()) {
|
||||
cv::Mat colorMask(obj.mask.size(), CV_8UC3,
|
||||
cv::Scalar((i * 67 + 50) % 256, (i * 123 + 100) % 256, (i * 37 + 150) % 256));
|
||||
cv::Mat roiImg = image(obj.box);
|
||||
cv::Mat maskBool;
|
||||
if (obj.mask.type() != CV_8UC1)
|
||||
obj.mask.convertTo(maskBool, CV_8UC1, 255.0);
|
||||
else
|
||||
maskBool = obj.mask;
|
||||
colorMask.copyTo(roiImg, maskBool);
|
||||
cv::addWeighted(roiImg, 0.4, image(obj.box), 0.6, 0, image(obj.box));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cv::imshow("SAM3 TRT Image Test", image);
|
||||
cv::waitKey(0);
|
||||
cv::destroyAllWindows();
|
||||
infHandle.Destroy();
|
||||
std::cout << "SAM3TRT_ImageTest: done.\n";
|
||||
return 0;
|
||||
}
|
||||
49
tests/ANSODEngine-UnitTest/CMakeLists.txt
Normal file
49
tests/ANSODEngine-UnitTest/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
# ANSODEngine Unit Test
|
||||
add_executable(ANSODEngine-UnitTest
|
||||
ANSODEngine-UnitTest.cpp
|
||||
ANSODTest.cpp
|
||||
ANSODTest.h
|
||||
ANSSAM3-UnitTest.cpp
|
||||
CustomModel-StressTest.cpp
|
||||
yolov10.h
|
||||
Yolov10OV.h
|
||||
Yolov10RT.h
|
||||
)
|
||||
|
||||
target_include_directories(ANSODEngine-UnitTest PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSODEngine
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSODEngine/CUDA
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSLPR
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSLPR/include
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSOCR/ANSPaddleOCR
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSOCR/ANSPaddleOCR/include
|
||||
${CMAKE_SOURCE_DIR}/modules/ANSMOT
|
||||
${CMAKE_SOURCE_DIR}/engines/ONNXEngine
|
||||
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/include
|
||||
${CMAKE_SOURCE_DIR}/engines/TensorRTAPI/include
|
||||
${ANSLIBS_DIR}/OpenVINO/samples/cpp/common
|
||||
${SHARED_INCLUDE_DIR}
|
||||
${ANSLIBS_DIR}/pybind11/include
|
||||
${ANSLIBS_DIR}/Python311/include
|
||||
)
|
||||
|
||||
target_link_libraries(ANSODEngine-UnitTest
|
||||
PRIVATE ANSODEngine
|
||||
PRIVATE ANSLicensingSystem
|
||||
PRIVATE ANSLPR
|
||||
PRIVATE ANSMOT
|
||||
PRIVATE opencv
|
||||
PRIVATE onnxruntime
|
||||
PRIVATE openvino
|
||||
PRIVATE tensorrt
|
||||
PRIVATE boost
|
||||
PRIVATE python311
|
||||
PRIVATE CUDA::cudart
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(ANSODEngine-UnitTest PRIVATE ${WIN_COMMON_LIBS})
|
||||
endif()
|
||||
|
||||
target_compile_definitions(ANSODEngine-UnitTest PRIVATE UNICODE _UNICODE)
|
||||
551
tests/ANSODEngine-UnitTest/CustomModel-StressTest.cpp
Normal file
551
tests/ANSODEngine-UnitTest/CustomModel-StressTest.cpp
Normal file
@@ -0,0 +1,551 @@
|
||||
// =============================================================================
|
||||
// CustomModel-StressTest.cpp
|
||||
//
|
||||
// Multi-task stress test using ANSODEngine's extern "C" API functions
|
||||
// (same path as LabVIEW). Uses FilePlayer + CloneImage + RunInferenceComplete_CPP
|
||||
// to reproduce the full LabVIEW production flow for custom model DLLs.
|
||||
//
|
||||
// This test loads ANSCV.dll at runtime via LoadLibrary/GetProcAddress
|
||||
// so it does NOT require linking ANSCV.lib.
|
||||
// =============================================================================
|
||||
|
||||
// windows.h MUST come before ANSODTest.h to avoid ACCESS_MASK conflict with TensorRT
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include "ANSODTest.h"
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
// Note: NOT linking cudart.lib — use GetProcAddress for CUDA if needed
|
||||
|
||||
// --- Forward declarations of ANSODEngine extern "C" functions ---
|
||||
// These are linked via ANSODEngine.lib
|
||||
extern "C" __declspec(dllimport) std::string CreateANSODHandle(
|
||||
ANSCENTER::ANSODBase** Handle,
|
||||
const char* licenseKey, const char* modelFilePath,
|
||||
const char* modelFileZipPassword,
|
||||
float detectionScoreThreshold, float modelConfThreshold, float modelMNSThreshold,
|
||||
int autoDetectEngine, int modelType, int detectionType, int loadEngineOnCreation);
|
||||
|
||||
extern "C" __declspec(dllimport) int RunInferenceComplete_CPP(
|
||||
ANSCENTER::ANSODBase** Handle, cv::Mat** cvImage, const char* cameraId,
|
||||
const char* activeROIMode, std::vector<ANSCENTER::Object>& detectionResult);
|
||||
|
||||
extern "C" __declspec(dllimport) int ReleaseANSODHandle(ANSCENTER::ANSODBase** Handle);
|
||||
|
||||
// --- ANSCV function pointer types (loaded at runtime) ---
|
||||
typedef int (*FnCreateFilePlayer)(void** Handle, const char* licenseKey, const char* url);
|
||||
typedef int (*FnStartFilePlayer)(void** Handle);
|
||||
typedef int (*FnStopFilePlayer)(void** Handle);
|
||||
typedef int (*FnGetFilePlayerCVImage)(void** Handle, int& w, int& h, int64_t& pts, cv::Mat** image);
|
||||
typedef void(*FnSetFilePlayerDisplayRes)(void** Handle, int w, int h);
|
||||
typedef int (*FnReleaseFilePlayer)(void** Handle);
|
||||
typedef int (*FnCloneImage)(cv::Mat** imageIn, cv::Mat** imageOut);
|
||||
typedef int (*FnReleaseImage)(cv::Mat** imageIn);
|
||||
typedef void(*FnInitCameraNetwork)();
|
||||
typedef void(*FnDeinitCameraNetwork)();
|
||||
|
||||
// --- ANSCV function pointers ---
|
||||
static FnCreateFilePlayer pCreateFilePlayer = nullptr;
|
||||
static FnStartFilePlayer pStartFilePlayer = nullptr;
|
||||
static FnStopFilePlayer pStopFilePlayer = nullptr;
|
||||
static FnGetFilePlayerCVImage pGetFilePlayerCVImage = nullptr;
|
||||
static FnSetFilePlayerDisplayRes pSetFilePlayerDisplayRes = nullptr;
|
||||
static FnReleaseFilePlayer pReleaseFilePlayer = nullptr;
|
||||
static FnCloneImage pCloneImage = nullptr;
|
||||
static FnReleaseImage pReleaseImage = nullptr;
|
||||
static FnInitCameraNetwork pInitCameraNetwork = nullptr;
|
||||
static FnDeinitCameraNetwork pDeinitCameraNetwork = nullptr;
|
||||
|
||||
static HMODULE g_hANSCV = nullptr;
|
||||
|
||||
static bool LoadANSCV() {
|
||||
g_hANSCV = LoadLibraryA("ANSCV.dll");
|
||||
if (!g_hANSCV) {
|
||||
printf("ERROR: Failed to load ANSCV.dll (error %lu)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
pCreateFilePlayer = (FnCreateFilePlayer)GetProcAddress(g_hANSCV, "CreateANSFilePlayerHandle");
|
||||
pStartFilePlayer = (FnStartFilePlayer)GetProcAddress(g_hANSCV, "StartFilePlayer");
|
||||
pStopFilePlayer = (FnStopFilePlayer)GetProcAddress(g_hANSCV, "StopFilePlayer");
|
||||
pGetFilePlayerCVImage = (FnGetFilePlayerCVImage)GetProcAddress(g_hANSCV, "GetFilePlayerCVImage");
|
||||
pSetFilePlayerDisplayRes = (FnSetFilePlayerDisplayRes)GetProcAddress(g_hANSCV, "SetFilePlayerDisplayResolution");
|
||||
pReleaseFilePlayer = (FnReleaseFilePlayer)GetProcAddress(g_hANSCV, "ReleaseANSFilePlayerHandle");
|
||||
pCloneImage = (FnCloneImage)GetProcAddress(g_hANSCV, "ANSCV_CloneImage_S");
|
||||
pReleaseImage = (FnReleaseImage)GetProcAddress(g_hANSCV, "ANSCV_ReleaseImage_S");
|
||||
pInitCameraNetwork = (FnInitCameraNetwork)GetProcAddress(g_hANSCV, "InitCameraNetwork");
|
||||
pDeinitCameraNetwork = (FnDeinitCameraNetwork)GetProcAddress(g_hANSCV, "DeinitCameraNetwork");
|
||||
|
||||
if (!pCreateFilePlayer || !pStartFilePlayer || !pStopFilePlayer ||
|
||||
!pGetFilePlayerCVImage || !pReleaseFilePlayer ||
|
||||
!pCloneImage || !pReleaseImage) {
|
||||
printf("ERROR: Failed to resolve one or more ANSCV functions\n");
|
||||
FreeLibrary(g_hANSCV);
|
||||
g_hANSCV = nullptr;
|
||||
return false;
|
||||
}
|
||||
printf("ANSCV.dll loaded successfully\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void UnloadANSCV() {
|
||||
if (g_hANSCV) {
|
||||
FreeLibrary(g_hANSCV);
|
||||
g_hANSCV = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Shared state ---
|
||||
static std::atomic<bool> g_stressRunning{true};
|
||||
|
||||
struct StressTaskState {
|
||||
std::mutex mtx;
|
||||
cv::Mat displayFrame;
|
||||
double fps = 0;
|
||||
double inferenceMs = 0;
|
||||
double grabMs = 0;
|
||||
int frameCount = 0;
|
||||
int detectionCount = 0;
|
||||
int gpuDeviceId = -1;
|
||||
size_t vramUsedMiB = 0;
|
||||
std::string statusMsg = "Initializing";
|
||||
std::string lastDetection;
|
||||
bool engineLoaded = false;
|
||||
};
|
||||
|
||||
// --- GPU VRAM helpers (via cudart.dll at runtime) ---
|
||||
typedef int (*FnCudaGetDeviceCount)(int*);
|
||||
typedef int (*FnCudaSetDevice)(int);
|
||||
typedef int (*FnCudaMemGetInfo)(size_t*, size_t*);
|
||||
|
||||
static std::vector<size_t> GetPerGpuFreeMiB() {
|
||||
static HMODULE hCudart = LoadLibraryA("cudart64_12.dll");
|
||||
if (!hCudart) hCudart = LoadLibraryA("cudart64_110.dll");
|
||||
if (!hCudart) return {};
|
||||
|
||||
auto fnGetCount = (FnCudaGetDeviceCount)GetProcAddress(hCudart, "cudaGetDeviceCount");
|
||||
auto fnSetDev = (FnCudaSetDevice)GetProcAddress(hCudart, "cudaSetDevice");
|
||||
auto fnMemInfo = (FnCudaMemGetInfo)GetProcAddress(hCudart, "cudaMemGetInfo");
|
||||
if (!fnGetCount || !fnSetDev || !fnMemInfo) return {};
|
||||
|
||||
int count = 0;
|
||||
fnGetCount(&count);
|
||||
std::vector<size_t> result(count, 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
fnSetDev(i);
|
||||
size_t freeMem = 0, totalMem = 0;
|
||||
fnMemInfo(&freeMem, &totalMem);
|
||||
result[i] = freeMem / (1024 * 1024);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- Worker thread ---
|
||||
// Mimics LabVIEW flow: GetImage → CloneImage → RunInferenceComplete_CPP → ReleaseImage
|
||||
static void ODWorkerThread(int taskId,
|
||||
void* fpClient,
|
||||
ANSCENTER::ANSODBase* odHandle,
|
||||
StressTaskState& state) {
|
||||
char tag[32];
|
||||
snprintf(tag, sizeof(tag), "[Task%d]", taskId);
|
||||
printf("%s Worker thread started\n", tag);
|
||||
|
||||
int width = 0, height = 0;
|
||||
int64_t pts = 0;
|
||||
int emptyFrames = 0;
|
||||
std::string cameraId = "StressCam" + std::to_string(taskId);
|
||||
|
||||
std::deque<std::chrono::steady_clock::time_point> fpsTimestamps;
|
||||
|
||||
while (g_stressRunning.load()) {
|
||||
// --- Step 1: Get image from FilePlayer (like camera process) ---
|
||||
auto grabStart = std::chrono::steady_clock::now();
|
||||
cv::Mat* framePtr = nullptr;
|
||||
pGetFilePlayerCVImage(&fpClient, width, height, pts, &framePtr);
|
||||
auto grabEnd = std::chrono::steady_clock::now();
|
||||
double grabMs = std::chrono::duration<double, std::milli>(grabEnd - grabStart).count();
|
||||
|
||||
if (!framePtr || framePtr->empty()) {
|
||||
emptyFrames++;
|
||||
if (emptyFrames > 500) {
|
||||
printf("%s Too many empty frames (%d), stopping\n", tag, emptyFrames);
|
||||
break;
|
||||
}
|
||||
if (framePtr) { pReleaseImage(&framePtr); }
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
continue;
|
||||
}
|
||||
emptyFrames = 0;
|
||||
|
||||
// --- Step 2: Clone image (like LabVIEW consumer) ---
|
||||
cv::Mat* clonedImage = nullptr;
|
||||
int cloneResult = pCloneImage(&framePtr, &clonedImage);
|
||||
if (cloneResult != 1 || !clonedImage) {
|
||||
printf("%s CloneImage failed (result=%d)\n", tag, cloneResult);
|
||||
pReleaseImage(&framePtr);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Release original frame (camera process would do this)
|
||||
pReleaseImage(&framePtr);
|
||||
|
||||
// --- Step 3: Run inference on clone (like AI task) ---
|
||||
auto infStart = std::chrono::steady_clock::now();
|
||||
std::vector<ANSCENTER::Object> detections;
|
||||
int infResult = RunInferenceComplete_CPP(&odHandle, &clonedImage, cameraId.c_str(), "", detections);
|
||||
auto infEnd = std::chrono::steady_clock::now();
|
||||
double infMs = std::chrono::duration<double, std::milli>(infEnd - infStart).count();
|
||||
|
||||
// --- Step 4: Draw results on clone for display ---
|
||||
cv::Mat display;
|
||||
if (clonedImage && !clonedImage->empty()) {
|
||||
display = clonedImage->clone();
|
||||
}
|
||||
|
||||
std::string lastDet;
|
||||
int detCount = 0;
|
||||
if (infResult > 0) {
|
||||
for (const auto& obj : detections) {
|
||||
if (!display.empty()) {
|
||||
cv::rectangle(display, obj.box, cv::Scalar(0, 255, 0), 2);
|
||||
std::string label = obj.className + " " +
|
||||
std::to_string((int)(obj.confidence * 100)) + "%";
|
||||
cv::putText(display, label,
|
||||
cv::Point(obj.box.x, obj.box.y - 5),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.5,
|
||||
cv::Scalar(0, 255, 0), 1);
|
||||
}
|
||||
lastDet = obj.className;
|
||||
detCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Step 5: Release clone (like LabVIEW task cleanup) ---
|
||||
pReleaseImage(&clonedImage);
|
||||
|
||||
// --- FPS calculation ---
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
fpsTimestamps.push_back(now);
|
||||
while (!fpsTimestamps.empty() &&
|
||||
std::chrono::duration<double>(now - fpsTimestamps.front()).count() > 2.0) {
|
||||
fpsTimestamps.pop_front();
|
||||
}
|
||||
double fps = fpsTimestamps.size() / 2.0;
|
||||
|
||||
// --- Update state ---
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(state.mtx);
|
||||
if (!display.empty()) state.displayFrame = display;
|
||||
state.fps = fps;
|
||||
state.inferenceMs = infMs;
|
||||
state.grabMs = grabMs;
|
||||
state.frameCount++;
|
||||
state.detectionCount += detCount;
|
||||
if (!lastDet.empty()) state.lastDetection = lastDet;
|
||||
}
|
||||
|
||||
// Periodic log
|
||||
if ((state.frameCount % 200) == 0) {
|
||||
printf("%s %d frames | %.1f FPS | Inf: %.0f ms | Det: %d\n",
|
||||
tag, state.frameCount, fps, infMs, state.detectionCount);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s Worker thread finished (%d frames)\n", tag, state.frameCount);
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Main test function
|
||||
//
|
||||
// Config (edit these):
|
||||
// NUM_STREAMS — number of FilePlayer instances (cameras)
|
||||
// NUM_TASKS — number of AI tasks
|
||||
// videoFiles[] — paths to video files
|
||||
// modelFolder — path to custom model folder
|
||||
// modelType — engine type (31=RTYOLO, 30=ONNXYOLO, 10=CustomDetector, etc.)
|
||||
// =============================================================================
|
||||
int CustomModel_StressTest_FilePlayer() {
|
||||
printf("\n");
|
||||
printf("============================================================\n");
|
||||
printf(" Custom Model Multi-Task Stress Test (FilePlayer)\n");
|
||||
printf(" Uses RunInferenceComplete_CPP (same path as LabVIEW)\n");
|
||||
printf(" Press ESC to stop\n");
|
||||
printf("============================================================\n\n");
|
||||
|
||||
// --- Load ANSCV.dll at runtime ---
|
||||
if (!LoadANSCV()) return -1;
|
||||
if (pInitCameraNetwork) pInitCameraNetwork();
|
||||
|
||||
// =====================================================================
|
||||
// CONFIGURATION — EDIT THESE FOR YOUR TEST
|
||||
// =====================================================================
|
||||
const int NUM_STREAMS = 2;
|
||||
const int NUM_TASKS = 4; // 2 tasks per camera
|
||||
|
||||
// Video files (one per stream)
|
||||
const std::string videoFiles[NUM_STREAMS] = {
|
||||
"E:\\Programs\\DemoAssets\\Videos\\Helmet\\HM1.mp4",
|
||||
"E:\\Programs\\DemoAssets\\Videos\\Helmet\\HM2.mp4",
|
||||
};
|
||||
|
||||
// Which stream each task uses
|
||||
const int taskStreamMap[NUM_TASKS] = { 0, 0, 1, 1 };
|
||||
|
||||
// Model config — EDIT for your custom model
|
||||
const std::string modelFolder = "C:\\Projects\\ANSVIS\\Models\\ANS_Helmet_v2.0.zip";
|
||||
//const char* modelName = "detector";
|
||||
//const char* className = "detector.names";
|
||||
const int modelType = 16; // 16 = CustomDetector, 31 = RTYOLO, 30 = ONNXYOLO
|
||||
const float scoreThresh = 0.5f;
|
||||
const float confThresh = 0.5f;
|
||||
const float nmsThresh = 0.45f;
|
||||
// =====================================================================
|
||||
int detectorType = 1; // Detection
|
||||
|
||||
|
||||
std::cout << "\n--- Test 1: Handle creation (elastic mode) ---\n" << std::endl;
|
||||
|
||||
std::cout << "Optimizing model, please wait..." << std::endl;
|
||||
std::string optimizedFolder = OptimizeModelStr(
|
||||
modelFolder.c_str(), "",
|
||||
modelType, detectorType, 1);
|
||||
std::cout << "Optimized model folder: " << optimizedFolder << std::endl;
|
||||
|
||||
|
||||
|
||||
StressTaskState taskStates[NUM_TASKS];
|
||||
|
||||
// --- Create FilePlayer instances ---
|
||||
void* fpClients[NUM_STREAMS] = {};
|
||||
for (int s = 0; s < NUM_STREAMS; s++) {
|
||||
printf("[Stream%d] Creating FilePlayer: %s\n", s, videoFiles[s].c_str());
|
||||
int result = pCreateFilePlayer(&fpClients[s], "", videoFiles[s].c_str());
|
||||
if (result != 1 || !fpClients[s]) {
|
||||
printf("[Stream%d] FAILED to create FilePlayer (result=%d)\n", s, result);
|
||||
fpClients[s] = nullptr;
|
||||
continue;
|
||||
}
|
||||
if (pSetFilePlayerDisplayRes) {
|
||||
pSetFilePlayerDisplayRes(&fpClients[s], 1920, 1080);
|
||||
}
|
||||
printf("[Stream%d] FilePlayer created (display: 1920x1080)\n", s);
|
||||
}
|
||||
|
||||
// --- Create OD engine handles sequentially ---
|
||||
ANSCENTER::ANSODBase* odHandles[NUM_TASKS] = {};
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
char tag[32];
|
||||
snprintf(tag, sizeof(tag), "[Task%d]", i);
|
||||
|
||||
int streamIdx = taskStreamMap[i];
|
||||
if (!fpClients[streamIdx]) {
|
||||
printf("%s Skipped — Stream%d not available\n", tag, streamIdx);
|
||||
std::lock_guard<std::mutex> lk(taskStates[i].mtx);
|
||||
taskStates[i].statusMsg = "Stream not available";
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(taskStates[i].mtx);
|
||||
taskStates[i].statusMsg = "Loading model...";
|
||||
}
|
||||
|
||||
printf("%s Creating OD handle (modelType=%d)...\n", tag, modelType);
|
||||
auto loadStart = std::chrono::steady_clock::now();
|
||||
auto vramBefore = GetPerGpuFreeMiB();
|
||||
|
||||
// Use CreateANSODHandle — same API as VideoDetectorEngine and LabVIEW
|
||||
std::string labelMap = CreateANSODHandle(
|
||||
&odHandles[i],
|
||||
"", // licenseKey
|
||||
modelFolder.c_str(),// modelFilePath (zip or folder)
|
||||
"", // modelZipFilePassword
|
||||
scoreThresh, // detectionScoreThreshold
|
||||
confThresh, // modelConfThreshold
|
||||
nmsThresh, // modelMNSThreshold
|
||||
1, // autoDetectEngine
|
||||
modelType, // modelType (16=custom, 31=RTYOLO, etc.)
|
||||
1, // detectionType (1=Detection)
|
||||
1); // loadEngineOnCreation
|
||||
|
||||
auto loadEnd = std::chrono::steady_clock::now();
|
||||
double loadMs = std::chrono::duration<double, std::milli>(loadEnd - loadStart).count();
|
||||
|
||||
if (!odHandles[i]) {
|
||||
printf("%s FAILED to create OD handle\n", tag);
|
||||
std::lock_guard<std::mutex> lk(taskStates[i].mtx);
|
||||
taskStates[i].statusMsg = "Model load failed";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto vramAfter = GetPerGpuFreeMiB();
|
||||
int bestGpu = 0;
|
||||
size_t maxDelta = 0;
|
||||
for (size_t g = 0; g < vramBefore.size() && g < vramAfter.size(); g++) {
|
||||
size_t delta = (vramBefore[g] > vramAfter[g]) ? vramBefore[g] - vramAfter[g] : 0;
|
||||
if (delta > maxDelta) { maxDelta = delta; bestGpu = (int)g; }
|
||||
}
|
||||
|
||||
printf("%s Model loaded in %.0f ms | GPU[%d] | VRAM: %zu MiB | Labels: %s\n",
|
||||
tag, loadMs, bestGpu, maxDelta,
|
||||
labelMap.empty() ? "(none)" : labelMap.substr(0, 80).c_str());
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(taskStates[i].mtx);
|
||||
taskStates[i].engineLoaded = true;
|
||||
taskStates[i].statusMsg = "Running";
|
||||
taskStates[i].gpuDeviceId = bestGpu;
|
||||
taskStates[i].vramUsedMiB = maxDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Start video playback ---
|
||||
for (int s = 0; s < NUM_STREAMS; s++) {
|
||||
if (fpClients[s]) {
|
||||
pStartFilePlayer(&fpClients[s]);
|
||||
printf("[Stream%d] Playback started\n", s);
|
||||
}
|
||||
}
|
||||
// Give FilePlayer time to decode first frames
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
// --- Launch worker threads ---
|
||||
std::thread workers[NUM_TASKS];
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
int streamIdx = taskStreamMap[i];
|
||||
if (fpClients[streamIdx] && odHandles[i]) {
|
||||
workers[i] = std::thread(ODWorkerThread, i,
|
||||
fpClients[streamIdx], odHandles[i],
|
||||
std::ref(taskStates[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Display loop ---
|
||||
const int cols = (NUM_TASKS <= 2) ? NUM_TASKS : 2;
|
||||
const int rows = (NUM_TASKS + cols - 1) / cols;
|
||||
const int cellW = 640, cellH = 480;
|
||||
const char* windowName = "Custom Model Stress Test";
|
||||
cv::namedWindow(windowName, cv::WINDOW_NORMAL);
|
||||
cv::resizeWindow(windowName, cellW * cols, cellH * rows + 40);
|
||||
|
||||
auto testStart = std::chrono::steady_clock::now();
|
||||
|
||||
while (g_stressRunning.load()) {
|
||||
cv::Mat canvas(cellH * rows + 40, cellW * cols, CV_8UC3, cv::Scalar(30, 30, 30));
|
||||
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
int row = i / cols, col = i % cols;
|
||||
cv::Rect roi(col * cellW, row * cellH, cellW, cellH);
|
||||
|
||||
cv::Mat cell;
|
||||
double fps = 0, infMs = 0;
|
||||
int fCount = 0, dCount = 0;
|
||||
int gpuId = -1;
|
||||
std::string statusMsg, lastDet;
|
||||
bool engineLoaded = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(taskStates[i].mtx);
|
||||
if (!taskStates[i].displayFrame.empty()) {
|
||||
cv::resize(taskStates[i].displayFrame, cell, cv::Size(cellW, cellH));
|
||||
}
|
||||
fps = taskStates[i].fps;
|
||||
infMs = taskStates[i].inferenceMs;
|
||||
fCount = taskStates[i].frameCount;
|
||||
dCount = taskStates[i].detectionCount;
|
||||
gpuId = taskStates[i].gpuDeviceId;
|
||||
statusMsg = taskStates[i].statusMsg;
|
||||
lastDet = taskStates[i].lastDetection;
|
||||
engineLoaded = taskStates[i].engineLoaded;
|
||||
}
|
||||
|
||||
if (cell.empty()) {
|
||||
cell = cv::Mat(cellH, cellW, CV_8UC3, cv::Scalar(40, 40, 40));
|
||||
cv::putText(cell, "Task " + std::to_string(i) + ": " + statusMsg,
|
||||
cv::Point(20, cellH / 2),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(100, 100, 255), 2);
|
||||
}
|
||||
|
||||
// Status bar
|
||||
cv::rectangle(cell, cv::Rect(0, cellH - 45, cellW, 45), cv::Scalar(0, 0, 0), cv::FILLED);
|
||||
char bar1[256], bar2[128];
|
||||
snprintf(bar1, sizeof(bar1), "T%d | %.1f FPS | %.0fms | Frames:%d | Det:%d",
|
||||
i, fps, infMs, fCount, dCount);
|
||||
snprintf(bar2, sizeof(bar2), "GPU[%d] | %s",
|
||||
gpuId, lastDet.empty() ? "-" : lastDet.c_str());
|
||||
cv::Scalar barColor = engineLoaded ? cv::Scalar(0, 255, 0) : cv::Scalar(0, 100, 255);
|
||||
cv::putText(cell, bar1, cv::Point(5, cellH - 25),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.45, barColor, 1);
|
||||
cv::putText(cell, bar2, cv::Point(5, cellH - 5),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.45, cv::Scalar(0, 200, 255), 1);
|
||||
|
||||
cell.copyTo(canvas(roi));
|
||||
}
|
||||
|
||||
// Bottom status bar
|
||||
double elapsed = std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now() - testStart).count();
|
||||
double totalFps = 0;
|
||||
for (int i = 0; i < NUM_TASKS; i++) totalFps += taskStates[i].fps;
|
||||
char bottomBar[256];
|
||||
snprintf(bottomBar, sizeof(bottomBar),
|
||||
"Elapsed: %.0fs | Total: %.1f FPS | %d streams, %d tasks | Press ESC to stop",
|
||||
elapsed, totalFps, NUM_STREAMS, NUM_TASKS);
|
||||
cv::putText(canvas, bottomBar, cv::Point(10, cellH * rows + 25),
|
||||
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(200, 200, 200), 1);
|
||||
|
||||
cv::imshow(windowName, canvas);
|
||||
int key = cv::waitKey(30);
|
||||
if (key == 27) {
|
||||
printf("\nESC pressed — stopping...\n");
|
||||
g_stressRunning.store(false);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Wait for workers ---
|
||||
printf("Waiting for worker threads...\n");
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
if (workers[i].joinable()) workers[i].join();
|
||||
}
|
||||
|
||||
// --- Final summary ---
|
||||
double totalElapsed = std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now() - testStart).count();
|
||||
printf("\n============================================================\n");
|
||||
printf(" FINAL SUMMARY (runtime: %.0fs)\n", totalElapsed);
|
||||
printf("============================================================\n");
|
||||
double totalFps = 0;
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
printf(" Task %d: GPU[%d] | %d frames | %d detections | %.1f FPS | Inf: %.0fms\n",
|
||||
i, taskStates[i].gpuDeviceId,
|
||||
taskStates[i].frameCount, taskStates[i].detectionCount,
|
||||
taskStates[i].fps, taskStates[i].inferenceMs);
|
||||
totalFps += taskStates[i].fps;
|
||||
}
|
||||
printf(" Total throughput: %.1f FPS across %d tasks\n", totalFps, NUM_TASKS);
|
||||
printf("============================================================\n");
|
||||
|
||||
// --- Release ---
|
||||
for (int i = 0; i < NUM_TASKS; i++) {
|
||||
if (odHandles[i]) ReleaseANSODHandle(&odHandles[i]);
|
||||
}
|
||||
for (int s = 0; s < NUM_STREAMS; s++) {
|
||||
if (fpClients[s]) {
|
||||
pStopFilePlayer(&fpClients[s]);
|
||||
pReleaseFilePlayer(&fpClients[s]);
|
||||
}
|
||||
}
|
||||
|
||||
cv::destroyAllWindows();
|
||||
if (pDeinitCameraNetwork) pDeinitCameraNetwork();
|
||||
UnloadANSCV();
|
||||
|
||||
return 0;
|
||||
}
|
||||
189
tests/ANSODEngine-UnitTest/Yolov10OV.h
Normal file
189
tests/ANSODEngine-UnitTest/Yolov10OV.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// https://www.cnblogs.com/guojin-blogs/p/18284497
|
||||
/// wget https://github.com/jameslahm/yolov10/releases/download/v1.0/yolov10s.pt
|
||||
// yolo export model = yolov10s.pt format = onnx opset = 13 simplify
|
||||
/// </summary>
|
||||
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include <openvino/op/transpose.hpp>
|
||||
#include <openvino/core/node.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <models/detection_model_ssd.h>
|
||||
|
||||
namespace Yolov10OV {
|
||||
struct DetResult {
|
||||
cv::Rect bbox;
|
||||
float conf;
|
||||
int lable;
|
||||
DetResult(cv::Rect bbox, float conf, int lable) :bbox(bbox), conf(conf), lable(lable) {}
|
||||
};
|
||||
|
||||
void pre_process(cv::Mat* img, int length, float* factor, std::vector<float>& data) {
|
||||
cv::Mat mat;
|
||||
int rh = img->rows;
|
||||
int rw = img->cols;
|
||||
int rc = img->channels();
|
||||
cv::cvtColor(*img, mat, cv::COLOR_BGR2RGB);
|
||||
int max_image_length = rw > rh ? rw : rh;
|
||||
cv::Mat max_image = cv::Mat::zeros(max_image_length, max_image_length, CV_8UC3);
|
||||
max_image = max_image * 255;
|
||||
cv::Rect roi(0, 0, rw, rh);
|
||||
mat.copyTo(cv::Mat(max_image, roi));
|
||||
cv::Mat resize_img;
|
||||
cv::resize(max_image, resize_img, cv::Size(length, length), 0.0f, 0.0f, cv::INTER_LINEAR);
|
||||
|
||||
*factor = (float)((float)max_image_length / (float)length);
|
||||
resize_img.convertTo(resize_img, CV_32FC3, 1 / 255.0);
|
||||
rh = resize_img.rows;
|
||||
rw = resize_img.cols;
|
||||
rc = resize_img.channels();
|
||||
for (int i = 0; i < rc; ++i) {
|
||||
cv::extractChannel(resize_img, cv::Mat(rh, rw, CV_32FC1, data.data() + i * rh * rw), i);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DetResult> post_process(float* result, float factor, int outputLength) {
|
||||
std::vector<cv::Rect> position_boxes;
|
||||
std::vector <int> class_ids;
|
||||
std::vector <float> confidences;
|
||||
// Preprocessing output results
|
||||
for (int i = 0; i < outputLength; i++)
|
||||
{
|
||||
int s = 6 * i;
|
||||
if ((float)result[s + 4] > 0.2)
|
||||
{
|
||||
float cx = result[s + 0];
|
||||
float cy = result[s + 1];
|
||||
float dx = result[s + 2];
|
||||
float dy = result[s + 3];
|
||||
int x = (int)((cx)*factor);
|
||||
int y = (int)((cy)*factor);
|
||||
int width = (int)((dx - cx) * factor);
|
||||
int height = (int)((dy - cy) * factor);
|
||||
cv::Rect box(x, y, width, height);
|
||||
|
||||
position_boxes.push_back(box);
|
||||
class_ids.push_back((int)result[s + 5]);
|
||||
confidences.push_back((float)result[s + 4]);
|
||||
}
|
||||
}
|
||||
std::vector<DetResult> re;
|
||||
for (int i = 0; i < position_boxes.size(); i++)
|
||||
{
|
||||
DetResult det(position_boxes[i], confidences[i], class_ids[i]);
|
||||
re.push_back(det);
|
||||
}
|
||||
return re;
|
||||
|
||||
}
|
||||
|
||||
void draw_bbox(cv::Mat& img, std::vector<DetResult>& res) {
|
||||
for (size_t j = 0; j < res.size(); j++) {
|
||||
cv::rectangle(img, res[j].bbox, cv::Scalar(255, 0, 255), 2);
|
||||
cv::putText(img, std::to_string(res[j].lable) + "-" + std::to_string(res[j].conf),
|
||||
cv::Point(res[j].bbox.x, res[j].bbox.y - 1), cv::FONT_HERSHEY_PLAIN,
|
||||
1.2, cv::Scalar(0, 0, 255), 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void yolov10_infer_without_process() {
|
||||
std::string videoPath = "E:\\Text_dataset\\car_test.mov";
|
||||
std::string model_path = "E:\\Text_Model\\yolov10s_openvino_model\\yolov10s.xml";
|
||||
ov::Core core;
|
||||
auto model = core.read_model(model_path);
|
||||
auto compiled_model = core.compile_model(model, "CPU");
|
||||
ov::InferRequest request = compiled_model.create_infer_request();
|
||||
cv::VideoCapture capture(videoPath);
|
||||
if (!capture.isOpened()) {
|
||||
std::cerr << "ERROR: " << std::endl;
|
||||
return;
|
||||
}
|
||||
float factor = 0;
|
||||
request.get_input_tensor().set_shape(std::vector<size_t>{1, 3, 640, 640});
|
||||
std::vector<float> inputData(640 * 640 * 3);
|
||||
std::chrono::time_point<std::chrono::steady_clock> t_beg;
|
||||
std::chrono::time_point<std::chrono::steady_clock> t_end;
|
||||
while (true)
|
||||
{
|
||||
cv::Mat frame;
|
||||
if (!capture.read(frame)) {
|
||||
break;
|
||||
}
|
||||
t_beg = std::chrono::high_resolution_clock::now();
|
||||
pre_process(&frame, 640, &factor, inputData);
|
||||
memcpy(request.get_input_tensor().data<float>(), inputData.data(), 640 * 640 * 3);
|
||||
request.infer();
|
||||
float* output_data = request.get_output_tensor().data<float>();
|
||||
std::vector<DetResult> result = post_process(output_data, factor, 300);
|
||||
t_end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
cv::putText(frame, "FPS: " + std::to_string(1000.0 / std::chrono::duration<float, std::milli>(t_end - t_beg).count())
|
||||
+ ", Time: " + std::to_string(std::chrono::duration<float, std::milli>(t_end - t_beg).count()) + "ms",
|
||||
cv::Point(20, 40), 1, 2, cv::Scalar(255, 0, 255), 2);
|
||||
draw_bbox(frame, result);
|
||||
imshow("Frame", frame);
|
||||
cv::waitKey(1); //30
|
||||
}
|
||||
cv::destroyAllWindows();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void yolov10_infer_ansy_without_process() {
|
||||
std::string videoPath = "E:\\Text_dataset\\car_test.mov";
|
||||
std::string model_path = "E:\\Text_Model\\yolov10s_openvino_model\\yolov10s.xml";
|
||||
ov::Core core;
|
||||
auto model = core.read_model(model_path);
|
||||
auto compiled_model = core.compile_model(model, "CPU");
|
||||
std::vector<ov::InferRequest>requests = { compiled_model.create_infer_request(), compiled_model.create_infer_request() };
|
||||
cv::VideoCapture capture(videoPath);
|
||||
if (!capture.isOpened()) {
|
||||
std::cerr << "ERROR:" << std::endl;
|
||||
return;
|
||||
}
|
||||
float factor = 0;
|
||||
requests[0].get_input_tensor().set_shape(std::vector<size_t>{1, 3, 640, 640});
|
||||
requests[1].get_input_tensor().set_shape(std::vector<size_t>{1, 3, 640, 640});
|
||||
cv::Mat frame;
|
||||
capture.read(frame);
|
||||
std::vector<float> inputData(640 * 640 * 3);
|
||||
pre_process(&frame, 640, &factor, inputData);
|
||||
memcpy(requests[0].get_input_tensor().data<float>(), inputData.data(), 640 * 640 * 3);
|
||||
requests[0].start_async();
|
||||
std::chrono::time_point<std::chrono::steady_clock> t_beg;
|
||||
std::chrono::time_point<std::chrono::steady_clock> t_end;
|
||||
while (true)
|
||||
{
|
||||
cv::Mat next_frame;
|
||||
if (!capture.read(next_frame)) {
|
||||
break;
|
||||
}
|
||||
t_beg = std::chrono::high_resolution_clock::now();
|
||||
pre_process(&next_frame, 640, &factor, inputData);
|
||||
memcpy(requests[1].get_input_tensor().data<float>(), inputData.data(), 640 * 640 * 3);
|
||||
requests[1].start_async();
|
||||
requests[0].wait();
|
||||
float* output_data = requests[0].get_output_tensor().data<float>();
|
||||
std::vector<DetResult> result = post_process(output_data, factor, 300);
|
||||
t_end = std::chrono::high_resolution_clock::now();
|
||||
draw_bbox(frame, result);
|
||||
cv::putText(frame, "FPS: " + std::to_string(1000.0 / std::chrono::duration<float, std::milli>(t_end - t_beg).count())
|
||||
+ ", Time: " + std::to_string(std::chrono::duration<float, std::milli>(t_end - t_beg).count()) + "ms",
|
||||
cv::Point(20, 40), 1, 2, cv::Scalar(255, 0, 255), 2);
|
||||
imshow("Frame", frame);
|
||||
cv::waitKey(1); //30
|
||||
frame = next_frame;
|
||||
std::swap(requests[0], requests[1]);
|
||||
}
|
||||
cv::destroyAllWindows();
|
||||
return;
|
||||
}
|
||||
}
|
||||
229
tests/ANSODEngine-UnitTest/Yolov10RT.h
Normal file
229
tests/ANSODEngine-UnitTest/Yolov10RT.h
Normal file
@@ -0,0 +1,229 @@
|
||||
#pragma once
|
||||
|
||||
/// <summary>
|
||||
/// //https://www.cnblogs.com/guojin-blogs/p/18258877
|
||||
/// wget https://github.com/jameslahm/yolov10/releases/download/v1.0/yolov10s.pt
|
||||
// yolo export model = yolov10s.pt format = onnx opset = 13 simplify
|
||||
/// </summary>
|
||||
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "cuda.h"
|
||||
#include "NvInfer.h"
|
||||
#include "NvOnnxParser.h"
|
||||
|
||||
namespace Yolov10RT {
|
||||
class Logger : public nvinfer1::ILogger
|
||||
{
|
||||
void log(Severity severity, const char* msg) noexcept override
|
||||
{
|
||||
if (severity <= Severity::kWARNING)
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
} logger;
|
||||
|
||||
struct DetResult {
|
||||
cv::Rect bbox;
|
||||
float conf;
|
||||
int lable;
|
||||
DetResult(cv::Rect bbox, float conf, int lable) :bbox(bbox), conf(conf), lable(lable) {}
|
||||
};
|
||||
|
||||
void onnxToEngine(const char* onnxFile, int memorySize) {
|
||||
std::string path(onnxFile);
|
||||
std::string::size_type iPos = (path.find_last_of('\\') + 1) == 0 ? path.find_last_of('/') + 1 : path.find_last_of('\\') + 1;
|
||||
std::string modelPath = path.substr(0, iPos);//
|
||||
std::string modelName = path.substr(iPos, path.length() - iPos);//
|
||||
std::string modelName_ = modelName.substr(0, modelName.rfind("."));//
|
||||
std::string engineFile = modelPath + modelName_ + ".engine";
|
||||
nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(logger);
|
||||
#if NV_TENSORRT_MAJOR >= 10
|
||||
nvinfer1::INetworkDefinition* network = builder->createNetworkV2(0);
|
||||
#else
|
||||
const auto explicitBatch = 1U << static_cast<uint32_t>(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH);
|
||||
nvinfer1::INetworkDefinition* network = builder->createNetworkV2(explicitBatch);
|
||||
#endif
|
||||
nvonnxparser::IParser* parser = nvonnxparser::createParser(*network, logger);
|
||||
|
||||
parser->parseFromFile(onnxFile, 2);
|
||||
for (int i = 0; i < parser->getNbErrors(); ++i) {
|
||||
std::cout << "load error: " << parser->getError(i)->desc() << std::endl;
|
||||
}
|
||||
printf("tensorRT load mask onnx model successfully!!!...\n");
|
||||
|
||||
nvinfer1::IBuilderConfig* config = builder->createBuilderConfig();
|
||||
#if NV_TENSORRT_MAJOR < 10
|
||||
config->setMaxWorkspaceSize(1024 * 1024 * memorySize);
|
||||
#else
|
||||
config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, 1024ULL * 1024 * memorySize);
|
||||
#endif
|
||||
config->setFlag(nvinfer1::BuilderFlag::kFP16);
|
||||
|
||||
#if NV_TENSORRT_MAJOR >= 10
|
||||
nvinfer1::IHostMemory* plan = builder->buildSerializedNetwork(*network, *config);
|
||||
std::cout << "try to save engine file now~~~" << std::endl;
|
||||
std::ofstream filePtr(engineFile, std::ios::binary);
|
||||
if (!filePtr) {
|
||||
std::cerr << "could not open plan output file" << std::endl;
|
||||
return;
|
||||
}
|
||||
filePtr.write(reinterpret_cast<const char*>(plan->data()), plan->size());
|
||||
delete plan;
|
||||
delete network;
|
||||
delete parser;
|
||||
#else
|
||||
nvinfer1::ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config);
|
||||
std::cout << "try to save engine file now~~~" << std::endl;
|
||||
std::ofstream filePtr(engineFile, std::ios::binary);
|
||||
if (!filePtr) {
|
||||
std::cerr << "could not open plan output file" << std::endl;
|
||||
return;
|
||||
}
|
||||
nvinfer1::IHostMemory* modelStream = engine->serialize();
|
||||
filePtr.write(reinterpret_cast<const char*>(modelStream->data()), modelStream->size());
|
||||
modelStream->destroy();
|
||||
engine->destroy();
|
||||
network->destroy();
|
||||
parser->destroy();
|
||||
#endif
|
||||
std::cout << "convert onnx model to TensorRT engine model successfully!" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void preProcess(cv::Mat* img, int length, float* factor, std::vector<float>& data) {
|
||||
cv::Mat mat;
|
||||
int rh = img->rows;
|
||||
int rw = img->cols;
|
||||
int rc = img->channels();
|
||||
cv::cvtColor(*img, mat, cv::COLOR_BGR2RGB);
|
||||
int maxImageLength = rw > rh ? rw : rh;
|
||||
cv::Mat maxImage = cv::Mat::zeros(maxImageLength, maxImageLength, CV_8UC3);
|
||||
maxImage = maxImage * 255;
|
||||
cv::Rect roi(0, 0, rw, rh);
|
||||
mat.copyTo(cv::Mat(maxImage, roi));
|
||||
cv::Mat resizeImg;
|
||||
cv::resize(maxImage, resizeImg, cv::Size(length, length), 0.0f, 0.0f, cv::INTER_LINEAR);
|
||||
*factor = (float)((float)maxImageLength / (float)length);
|
||||
resizeImg.convertTo(resizeImg, CV_32FC3, 1 / 255.0);
|
||||
rh = resizeImg.rows;
|
||||
rw = resizeImg.cols;
|
||||
rc = resizeImg.channels();
|
||||
for (int i = 0; i < rc; ++i) {
|
||||
cv::extractChannel(resizeImg, cv::Mat(rh, rw, CV_32FC1, data.data() + i * rh * rw), i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<DetResult> postProcess(float* result, float factor, int outputLength) {
|
||||
std::vector<cv::Rect> positionBoxes;
|
||||
std::vector <int> classIds;
|
||||
std::vector <float> confidences;
|
||||
// Preprocessing output results
|
||||
for (int i = 0; i < outputLength; i++)
|
||||
{
|
||||
int s = 6 * i;
|
||||
if ((float)result[s + 4] > 0.2)
|
||||
{
|
||||
float cx = result[s + 0];
|
||||
float cy = result[s + 1];
|
||||
float dx = result[s + 2];
|
||||
float dy = result[s + 3];
|
||||
int x = (int)((cx)*factor);
|
||||
int y = (int)((cy)*factor);
|
||||
int width = (int)((dx - cx) * factor);
|
||||
int height = (int)((dy - cy) * factor);
|
||||
cv::Rect box(x, y, width, height);
|
||||
positionBoxes.push_back(box);
|
||||
classIds.push_back((int)result[s + 5]);
|
||||
confidences.push_back((float)result[s + 4]);
|
||||
}
|
||||
}
|
||||
std::vector<DetResult> re;
|
||||
for (int i = 0; i < positionBoxes.size(); i++)
|
||||
{
|
||||
DetResult det(positionBoxes[i], confidences[i], classIds[i]);
|
||||
re.push_back(det);
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
void drawBbox(cv::Mat& img, std::vector<DetResult>& res) {
|
||||
for (size_t j = 0; j < res.size(); j++) {
|
||||
cv::rectangle(img, res[j].bbox, cv::Scalar(255, 0, 255), 2);
|
||||
cv::putText(img, std::to_string(res[j].lable) + "-" + std::to_string(res[j].conf),
|
||||
cv::Point(res[j].bbox.x, res[j].bbox.y - 1), cv::FONT_HERSHEY_PLAIN,
|
||||
1.2, cv::Scalar(0, 0, 255), 2);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<nvinfer1::IExecutionContext> creatContext(std::string modelPath) {
|
||||
std::ifstream filePtr(modelPath, std::ios::binary);
|
||||
if (!filePtr.good()) {
|
||||
std::cerr << "Errror" << std::endl;
|
||||
return std::shared_ptr<nvinfer1::IExecutionContext>();
|
||||
}
|
||||
size_t size = 0;
|
||||
filePtr.seekg(0, filePtr.end); //
|
||||
size = filePtr.tellg(); //
|
||||
filePtr.seekg(0, filePtr.beg); //
|
||||
char* modelStream = new char[size];
|
||||
filePtr.read(modelStream, size);
|
||||
filePtr.close();
|
||||
nvinfer1::IRuntime* runtime = nvinfer1::createInferRuntime(logger);
|
||||
nvinfer1::ICudaEngine* engine = runtime->deserializeCudaEngine(modelStream, size);
|
||||
return std::shared_ptr<nvinfer1::IExecutionContext>(engine->createExecutionContext());
|
||||
}
|
||||
|
||||
|
||||
void yolov10Infer() {
|
||||
const char* videoPath = "E:\\Text_dataset\\car_test.mov";
|
||||
const char* enginePath = "E:\\Text_Model\\yolov10s.engine";
|
||||
|
||||
std::shared_ptr<nvinfer1::IExecutionContext> context = creatContext(enginePath);
|
||||
cv::VideoCapture capture(videoPath);
|
||||
if (!capture.isOpened()) {
|
||||
std::cerr << "ERROR:" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
void* inputSrcDevice;
|
||||
void* outputSrcDevice;
|
||||
|
||||
cudaMalloc(&inputSrcDevice, 3 * 640 * 640 * sizeof(float));
|
||||
cudaMalloc(&outputSrcDevice, 1 * 300 * 6 * sizeof(float));
|
||||
std::vector<float> output_data(300 * 6);
|
||||
std::vector<float> inputData(640 * 640 * 3);
|
||||
while (true)
|
||||
{
|
||||
cv::Mat frame;
|
||||
if (!capture.read(frame)) {
|
||||
break;
|
||||
}
|
||||
float factor = 0;
|
||||
preProcess(&frame, 640, &factor, inputData);
|
||||
cudaMemcpyAsync(inputSrcDevice, inputData.data(), 3 * 640 * 640 * sizeof(float),
|
||||
cudaMemcpyHostToDevice, stream);
|
||||
#if NV_TENSORRT_MAJOR >= 10
|
||||
context->setTensorAddress("images", inputSrcDevice);
|
||||
context->setTensorAddress("output0", outputSrcDevice);
|
||||
context->enqueueV3(stream);
|
||||
#else
|
||||
void* bindings[] = { inputSrcDevice, outputSrcDevice };
|
||||
context->enqueueV2((void**)bindings, stream, nullptr);
|
||||
#endif
|
||||
cudaMemcpyAsync(output_data.data(), outputSrcDevice, 300 * 6 * sizeof(float),
|
||||
cudaMemcpyDeviceToHost, stream);
|
||||
cudaStreamSynchronize(stream);
|
||||
std::vector<DetResult> result = postProcess(output_data.data(), factor, 300);
|
||||
drawBbox(frame, result);
|
||||
imshow("Frame", frame);
|
||||
cv::waitKey(10);
|
||||
}
|
||||
cv::destroyAllWindows();
|
||||
}
|
||||
}
|
||||
187
tests/ANSODEngine-UnitTest/yolov10.h
Normal file
187
tests/ANSODEngine-UnitTest/yolov10.h
Normal file
@@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
#include <openvino/op/transpose.hpp>
|
||||
#include <openvino/core/node.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <models/detection_model_ssd.h>
|
||||
#include <random>
|
||||
namespace Yolov10 {
|
||||
struct YoloDetection {
|
||||
short class_id;
|
||||
float confidence;
|
||||
cv::Rect box;
|
||||
};
|
||||
class Inference {
|
||||
public:
|
||||
Inference() {}
|
||||
Inference(const std::string& model_path, const float& model_confidence_threshold);
|
||||
Inference(const std::string& model_path, const cv::Size model_input_shape, const float& model_confidence_threshold);
|
||||
|
||||
std::vector<YoloDetection> RunInference(const cv::Mat& frame);
|
||||
|
||||
private:
|
||||
void InitialModel(const std::string& model_path);
|
||||
void Preprocessing(const cv::Mat& frame);
|
||||
void PostProcessing();
|
||||
cv::Rect GetBoundingBox(const cv::Rect& src) const;
|
||||
std::vector<YoloDetection> detections_;
|
||||
float model_confidence_threshold_;
|
||||
cv::Mat resized_frame_;
|
||||
cv::Point2f factor_;
|
||||
cv::Size2f model_input_shape_;
|
||||
cv::Size model_output_shape_;
|
||||
std::string _modelFilePath;
|
||||
ov::Tensor input_tensor_;
|
||||
ov::InferRequest inference_request_;
|
||||
ov::CompiledModel compiled_model_;
|
||||
};
|
||||
|
||||
void DrawDetectedObject(cv::Mat& frame, const std::vector<YoloDetection>& detections, const std::vector<std::string>& class_names);
|
||||
std::vector<std::string> GetClassNameFromMetadata(const std::string& metadata_path);
|
||||
|
||||
|
||||
Inference::Inference(const std::string& model_path, const float& model_confidence_threshold) {
|
||||
model_input_shape_ = cv::Size(640, 640); // Set the default size for models with dynamic shapes to prevent errors.
|
||||
model_confidence_threshold_ = model_confidence_threshold;
|
||||
_modelFilePath = model_path;
|
||||
InitialModel(model_path);
|
||||
}
|
||||
|
||||
// If the model has dynamic shapes, we need to set the input shape.
|
||||
Inference::Inference(const std::string& model_path, const cv::Size model_input_shape, const float& model_confidence_threshold) {
|
||||
model_input_shape_ = model_input_shape;
|
||||
model_confidence_threshold_ = model_confidence_threshold;
|
||||
_modelFilePath = model_path;
|
||||
|
||||
InitialModel(model_path);
|
||||
}
|
||||
|
||||
|
||||
void Inference::InitialModel(const std::string& model_path) {
|
||||
ov::Core core;
|
||||
std::shared_ptr<ov::Model> model = core.read_model(model_path);
|
||||
if (model->is_dynamic()) {
|
||||
model->reshape({ 1, 3, static_cast<long int>(model_input_shape_.height), static_cast<long int>(model_input_shape_.width) });
|
||||
}
|
||||
ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
|
||||
|
||||
ppp.input().tensor().set_element_type(ov::element::u8).set_layout("NHWC").set_color_format(ov::preprocess::ColorFormat::BGR);
|
||||
ppp.input().preprocess().convert_element_type(ov::element::f32).convert_color(ov::preprocess::ColorFormat::RGB).scale({ 255, 255, 255 });
|
||||
ppp.input().model().set_layout("NCHW");
|
||||
ppp.output().tensor().set_element_type(ov::element::f32);
|
||||
|
||||
model = ppp.build();
|
||||
//compiled_model_ = core.compile_model(model, "AUTO:GPU,CPU");
|
||||
//core.set_property("AUTO", ov::device::priorities("GPU,CPU"));
|
||||
compiled_model_ = core.compile_model(model, "C");
|
||||
std::vector<std::string> available_devices = core.get_available_devices();
|
||||
auto num_requests = compiled_model_.get_property(ov::optimal_number_of_infer_requests);
|
||||
|
||||
inference_request_ = compiled_model_.create_infer_request();
|
||||
const std::vector<ov::Output<ov::Node>> inputs = model->inputs();
|
||||
const ov::Shape input_shape = inputs[0].get_shape();
|
||||
|
||||
short height = input_shape[1];
|
||||
short width = input_shape[2];
|
||||
model_input_shape_ = cv::Size2f(width, height);
|
||||
|
||||
const std::vector<ov::Output<ov::Node>> outputs = model->outputs();
|
||||
const ov::Shape output_shape = outputs[0].get_shape();
|
||||
|
||||
height = output_shape[1];
|
||||
width = output_shape[2];
|
||||
model_output_shape_ = cv::Size(width, height);
|
||||
}
|
||||
|
||||
std::vector<YoloDetection> Inference::RunInference(const cv::Mat& frame) {
|
||||
Preprocessing(frame);
|
||||
inference_request_.infer();
|
||||
PostProcessing();
|
||||
|
||||
return detections_;
|
||||
}
|
||||
|
||||
void Inference::Preprocessing(const cv::Mat& frame) {
|
||||
cv::resize(frame, resized_frame_, model_input_shape_, 0, 0, cv::INTER_AREA);
|
||||
factor_.x = static_cast<float>(frame.cols / model_input_shape_.width);
|
||||
factor_.y = static_cast<float>(frame.rows / model_input_shape_.height);
|
||||
float* input_data = (float*)resized_frame_.data;
|
||||
input_tensor_ = ov::Tensor(compiled_model_.input().get_element_type(), compiled_model_.input().get_shape(), input_data);
|
||||
inference_request_.set_input_tensor(input_tensor_);
|
||||
}
|
||||
|
||||
void Inference::PostProcessing() {
|
||||
const float* detections = inference_request_.get_output_tensor().data<const float>();
|
||||
detections_.clear();
|
||||
/*
|
||||
* 0 1 2 3 4 5
|
||||
* x, y, w. h, confidence, class_id
|
||||
*/
|
||||
|
||||
for (unsigned int i = 0; i < model_output_shape_.height; ++i) {
|
||||
const unsigned int index = i * model_output_shape_.width;
|
||||
const float& confidence = detections[index + 4];
|
||||
if (confidence > model_confidence_threshold_) {
|
||||
const float& x = detections[index + 0];
|
||||
const float& y = detections[index + 1];
|
||||
const float& w = detections[index + 2];
|
||||
const float& h = detections[index + 3];
|
||||
YoloDetection result;
|
||||
result.class_id = static_cast<const short>(detections[index + 5]);
|
||||
if (result.class_id > 9) result.class_id = 9;
|
||||
result.confidence = confidence;
|
||||
result.box = GetBoundingBox(cv::Rect(x, y, w, h));
|
||||
detections_.push_back(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DrawDetectedObject(cv::Mat& frame, const std::vector<YoloDetection>& detections, const std::vector<std::string>& class_names) {
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<int> dis(120, 255);
|
||||
|
||||
for (const auto& detection : detections) {
|
||||
const cv::Rect& box = detection.box;
|
||||
const float& confidence = detection.confidence;
|
||||
const int& class_id = detection.class_id;
|
||||
|
||||
const cv::Scalar color = cv::Scalar(dis(gen), dis(gen), dis(gen));
|
||||
cv::rectangle(frame, box, color, 3);
|
||||
|
||||
std::string class_string;
|
||||
|
||||
if (class_names.empty())
|
||||
class_string = "id[" + std::to_string(class_id) + "] " + std::to_string(confidence).substr(0, 4);
|
||||
else
|
||||
class_string = class_names[class_id] + " " + std::to_string(confidence).substr(0, 4);
|
||||
|
||||
const cv::Size text_size = cv::getTextSize(class_string, cv::FONT_HERSHEY_SIMPLEX, 0.6, 2, 0);
|
||||
const cv::Rect text_box(box.x - 2, box.y - 27, text_size.width + 10, text_size.height + 15);
|
||||
|
||||
cv::rectangle(frame, text_box, color, cv::FILLED);
|
||||
cv::putText(frame, class_string, cv::Point(box.x + 5, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 0), 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> GetClassNameFromMetadata(const std::string& metadata_path) {
|
||||
std::vector<std::string> class_names;
|
||||
|
||||
class_names.push_back("person");
|
||||
class_names.push_back("bicycle");
|
||||
class_names.push_back("car");
|
||||
class_names.push_back("motorcycle");
|
||||
class_names.push_back("airplane");
|
||||
class_names.push_back("bus");
|
||||
class_names.push_back("train");
|
||||
class_names.push_back("truck");
|
||||
class_names.push_back("boat");
|
||||
class_names.push_back("traffic light");
|
||||
class_names.push_back("fire hydrant");
|
||||
|
||||
return class_names;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user