Add unit tests

This commit is contained in:
2026-03-29 08:45:38 +11:00
parent 8a2e721058
commit 2392b6785b
19 changed files with 12790 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
# ANSCV Unit Test
add_executable(ANSCV-UnitTest
ANSCV-UnitTest.cpp
OpenCVTest.cpp
)
target_include_directories(ANSCV-UnitTest PRIVATE
${CMAKE_SOURCE_DIR}/modules/ANSCV
${CMAKE_SOURCE_DIR}/MediaClient
${CMAKE_SOURCE_DIR}/MediaClient/media
${CMAKE_SOURCE_DIR}/MediaClient/rtsp
${CMAKE_SOURCE_DIR}/MediaClient/rtp
${CMAKE_SOURCE_DIR}/MediaClient/bm
${CMAKE_SOURCE_DIR}/MediaClient/http
${CMAKE_SOURCE_DIR}/MediaClient/directx
${CMAKE_SOURCE_DIR}/MediaClient/rtmp
${CMAKE_SOURCE_DIR}/MediaClient/librtmp
${CMAKE_SOURCE_DIR}/MediaClient/srt
${CMAKE_SOURCE_DIR}/MediaClient/ffmpeg/include
${CMAKE_SOURCE_DIR}/MediaClient/openssl/include
${CMAKE_SOURCE_DIR}/MediaClient/libsrt/include
${SHARED_INCLUDE_DIR}
${ANLS_ROOT}/TurboJpeg
${RESEARCH_DIR}/QRCode
)
target_link_libraries(ANSCV-UnitTest
PRIVATE ANSCV
PRIVATE ANSLicensingSystem
PRIVATE anslicensing
PRIVATE labview
PRIVATE opencv
PRIVATE turbojpeg
PRIVATE zxing
)
if(WIN32)
target_link_libraries(ANSCV-UnitTest PRIVATE ${WIN_COMMON_LIBS})
endif()
target_compile_definitions(ANSCV-UnitTest PRIVATE UNICODE _UNICODE)

View File

@@ -0,0 +1,469 @@
//
//bool isRed(Vec3b color) {
// // Define the lower and upper bounds for red color
// Scalar lower_red = Scalar(0, 0, 100); // Adjust as needed
// Scalar upper_red = Scalar(80, 80, 255); // Adjust as needed
//
// // Convert the input color to a scalar for comparison
// Scalar target_color = Scalar(color[0], color[1], color[2]);
//
// // Check if the input color is within the specified range of red
// return (target_color.val[0] >= lower_red.val[0] && target_color.val[0] <= upper_red.val[0] &&
// target_color.val[1] >= lower_red.val[1] && target_color.val[1] <= upper_red.val[1] &&
// target_color.val[2] >= lower_red.val[2] && target_color.val[2] <= upper_red.val[2]);
//}
//
//int DominantColour() {
// // Read the input image
// //cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
// cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
// if (image.empty()) {
// std::cout << "Could not open or find the image" << std::endl;
// return -1;
// }
//
// // Reshape the image into a 2D array of pixels
// Mat pixels = image.reshape(1, image.rows * image.cols);
//
// // Convert pixel values to floats
// pixels.convertTo(pixels, CV_32F);
//
// // Define the number of clusters (colors) to find
// int numClusters = 3; // Adjust as needed
//
// // Perform K-means clustering
// Mat labels, centers;
// kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
// // Find the dominant colors
// vector<Vec3b> dominantColors;
// for (int i = 0; i < numClusters; ++i) {
// Vec3b color;
// color[0] = centers.at<float>(i, 0); // Blue
// color[1] = centers.at<float>(i, 1); // Green
// color[2] = centers.at<float>(i, 2); // Red
// dominantColors.push_back(color);
// }
//
// // Print the dominant colors
// cout << "Dominant colors:" << endl;
// for (int i = 0; i < numClusters; ++i) {
// cout << "Color " << i + 1 << ": BGR(" << (int)dominantColors[i][0] << ", " << (int)dominantColors[i][1] << ", " << (int)dominantColors[i][2] << ")" << endl;
// }
//
// // Display the dominant colors
// Mat colorPalette(100, 100 * numClusters, CV_8UC3);
// for (int i = 0; i < numClusters; ++i) {
// rectangle(colorPalette, Point(i * 100, 0), Point((i + 1) * 100, 100), Scalar(dominantColors[i]), -1); // Filled rectangle
// }
// imshow("Dominant Colors", colorPalette);
//
// // Wait for key press to exit
// waitKey(0);
//
// return 0;
//}
//// Function to determine basic color from 8 basic colors based on BGR values
//string getBasicColor(Vec3b color) {
// // Define 8 basic colors and their BGR values
// map<string, Vec3b> basicColors = {
// {"Red", {0, 0, 255}},
// {"Green", {0, 255, 0}},
// {"Blue", {255, 0, 0}},
// {"Yellow", {0, 255, 255}},
// {"Black", {0, 0, 0}},
// {"White", {255, 255, 255}},
// {"Brown", {42, 42, 165}},
// {"Gray", {128, 128, 128}}
// };
//
// string basicColor = "Other";
//
// // Find the basic color closest to the given color
// int minDistance = INT_MAX;
// for (const auto& entry : basicColors) {
// int dist = norm(entry.second, color, NORM_L2SQR);
// if (dist < minDistance) {
// minDistance = dist;
// basicColor = entry.first;
// }
// }
//
// return basicColor;
//}
//
//int GetColour() {
// // Read the image
// Mat image = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
// if (image.empty()) {
// cerr << "Error: Unable to read image." << endl;
// return -1;
// }
//
// // Initialize variables to count occurrences of 8 basic colors
// map<string, int> colorCounts;
// for (const auto& entry : {
// "Red", "Green", "Blue", "Yellow", "Black", "White", "Brown", "Gray"
// }) {
// colorCounts[entry] = 0;
// }
//
// // Iterate over image pixels to count occurrences of 8 basic colors
// for (int i = 0; i < image.rows; ++i) {
// for (int j = 0; j < image.cols; ++j) {
// Vec3b pixelColor = image.at<Vec3b>(i, j);
// string basicColor = getBasicColor(pixelColor);
// colorCounts[basicColor]++;
// }
// }
//
// // Find the dominant basic color
// string dominantBasicColor = "Other";
// int maxCount = 0;
// for (const auto& entry : colorCounts) {
// if (entry.second > maxCount) {
// maxCount = entry.second;
// dominantBasicColor = entry.first;
// }
// }
//
// // Get the BGR color code of the dominant basic color
// Vec3b dominantBGRColor;
// if (dominantBasicColor == "Red")
// dominantBGRColor = Vec3b(0, 0, 255);
// else if (dominantBasicColor == "Green")
// dominantBGRColor = Vec3b(0, 255, 0);
// else if (dominantBasicColor == "Blue")
// dominantBGRColor = Vec3b(255, 0, 0);
// else if (dominantBasicColor == "Yellow")
// dominantBGRColor = Vec3b(0, 255, 255);
// else if (dominantBasicColor == "Black")
// dominantBGRColor = Vec3b(0, 0, 0);
// else if (dominantBasicColor == "White")
// dominantBGRColor = Vec3b(255, 255, 255);
// else if (dominantBasicColor == "Brown")
// dominantBGRColor = Vec3b(42, 42, 165);
// else if (dominantBasicColor == "Gray")
// dominantBGRColor = Vec3b(128, 128, 128);
//
// // Create a new image with the dominant color filled
// Mat dominantColorImage(image.size(), CV_8UC3, dominantBGRColor);
//
// // Display the dominant color in a separate window
// namedWindow("Dominant Color", WINDOW_AUTOSIZE);
// imshow("Dominant Color", dominantColorImage);
// waitKey(0);
//
// return 0;
//}
//
//int DetectRedCar() {
// // Read the input image
// cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
// if (image.empty()) {
// cout << "Could not open or find the image" << endl;
// return -1;
// }
//
// // Reshape the image into a 2D array of pixels
// Mat pixels = image.reshape(1, image.rows * image.cols);
//
// // Convert pixel values to floats
// pixels.convertTo(pixels, CV_32F);
//
// // Define the number of clusters (colors) to find
// int numClusters = 3; // Adjust as needed
//
// // Perform K-means clustering
// Mat labels, centers;
// kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
// // Find the dominant colors
// vector<Vec3b> dominantColors;
// for (int i = 0; i < numClusters; ++i) {
// Vec3b color;
// color[0] = centers.at<float>(i, 0); // Blue
// color[1] = centers.at<float>(i, 1); // Green
// color[2] = centers.at<float>(i, 2); // Red
// dominantColors.push_back(color);
// }
//
// // Check if any of the dominant colors are red
// bool redDetected = false;
// for (int i = 0; i < numClusters; ++i) {
// if (isRed(dominantColors[i])) {
// redDetected = true;
// break;
// }
// }
//
// // Print the result
// if (redDetected) {
// cout << "A red car is detected in the image." << endl;
// }
// else {
// cout << "No red car is detected in the image." << endl;
// }
//
// return 0;
//}
//
//double CalculateIoU(const cv::Rect& box1, const cv::Rect& box2) {
// int x1 = std::max(box1.x, box2.x);
// int y1 = std::max(box1.y, box2.y);
// int x2 = std::min(box1.x + box1.width, box2.x + box2.width);
// int y2 = std::min(box1.y + box1.height, box2.y + box2.height);
//
// int intersectionArea = std::max(0, x2 - x1) * std::max(0, y2 - y1);
// int box1Area = box1.width * box1.height;
// int box2Area = box2.width * box2.height;
//
// double iou = static_cast<double>(intersectionArea) / (box1Area + box2Area - intersectionArea);
// return iou;
//}
//void NonMaximumSuppression(std::vector<DetectionObject>& detectedObjects, double iouThreshold) {
// std::sort(detectedObjects.begin(), detectedObjects.end(),
// [](const DetectionObject& a, const DetectionObject& b) {
// return a.confidence > b.confidence;
// });
//
// std::vector<DetectionObject> finalDetections;
// while (!detectedObjects.empty()) {
// finalDetections.push_back(detectedObjects.front());
// detectedObjects.erase(detectedObjects.begin());
//
// for (auto it = detectedObjects.begin(); it != detectedObjects.end(); ) {
// if (CalculateIoU(finalDetections.back().box, it->box) > iouThreshold) {
// it = detectedObjects.erase(it);
// }
// else {
// ++it;
// }
// }
// }
//
// detectedObjects = std::move(finalDetections);
//}
//std::vector<DetectionObject> findMatches(cv::Mat& img, cv::Mat& templ, double threshold) {
// // Create the result matrix
// std::vector<DetectionObject> detectedObjects;
// int result_cols = img.cols - templ.cols + 1;
// int result_rows = img.rows - templ.rows + 1;
// cv::Mat result(result_rows, result_cols, CV_32FC1);
//
// // Perform match
// cv::matchTemplate(img, templ, result, cv::TM_CCOEFF_NORMED);
// cv::normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
//
// std::vector<cv::Rect> boundingBoxes;
//
// // Threshold and find non-zero locations
// for (int i = 0; i < result.rows; i++) {
// for (int j = 0; j < result.cols; j++) {
// if (result.at<float>(i, j) > threshold) {
// cv::Rect rect(j, i, templ.cols, templ.rows);
// DetectionObject object;
// object.box = rect;
// boundingBoxes.push_back(rect);
// detectedObjects.push_back(object);
// // Optional: Draw rectangles on the image
// cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 2);
// }
// }
// }
// NonMaximumSuppression(detectedObjects, 0.5);
// std::cout << "Bounding box size:" << boundingBoxes.size()<<std::endl;
// std::cout << "detectedObjects box size:" << detectedObjects.size() << std::endl;
//
// return detectedObjects;
//}
//
//int PatternMatching() {
// // Load the image and the template
// cv::Mat img = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\QRSample.jpg", cv::IMREAD_COLOR);
// cv::Mat templ = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Ultracode.jpg", cv::IMREAD_COLOR);
//
// if (img.empty() || templ.empty()) {
// std::cout << "Could not open or find the image or template" << std::endl;
// return -1;
// }
//
// // Call findMatches with a threshold, e.g., 0.8 for 80% similarity
// std::vector<DetectionObject> matches = findMatches(img, templ, 0.8);
//
// // Display the image with drawn rectangles
// cv::imshow("Matches", img);
// cv::waitKey(0);
//
//
// return 0;
//}
//int TestZingQRcode() {
//
// // load your image data from somewhere. ImageFormat::Lum assumes grey scale image data
//
// cv::Mat inputImage = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Code128.jpg");
// cv::Mat grayMat;
// if (inputImage.channels() == 3) {
// cv::cvtColor(inputImage, grayMat, cv::COLOR_BGR2GRAY);
// }
// else if (inputImage.channels() == 4) {
// cv::cvtColor(inputImage, grayMat, cv::COLOR_BGRA2GRAY);
// }
// else {
// grayMat = inputImage; // Already grayscale
// }
//
// int width = grayMat.cols;
// int height= grayMat.rows;
// unsigned char* data = grayMat.data;
// auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// auto options = ZXing::ReaderOptions().setFormats(ZXing::BarcodeFormat::Any);
// auto barcodes = ZXing::ReadBarcodes(image, options);
// if (barcodes.size() > 0) {
// for (const auto& b : barcodes) {
// std::cout << ZXing::ToString(b.format()) << ": " << b.text() << "\n";
// ZXing::Position pos =b.position();
// std::cout<<"Pos 1:("<<pos[0].x<<","<< pos[0].x<<")"<<std::endl;
// }
//
// }
// else {
// std::cout << "Could not find any barcode"<<std::endl;
// }
//
// return 0;
//}
//
//
//
//Vec3f estimateIllumination(Mat& src, float percentile) {
// Mat src_float;
// src.convertTo(src_float, CV_32FC3);
// vector<Mat> channels(3);
// split(src_float, channels);
//
// Mat magnitude = Mat::zeros(src.size(), CV_32FC1);
//
// for (int i = 0; i < 3; i++) {
// Mat sobelx, sobely;
// Sobel(channels[i], sobelx, CV_32F, 1, 0);
// Sobel(channels[i], sobely, CV_32F, 0, 1);
// magnitude += sobelx.mul(sobelx) + sobely.mul(sobely);
// }
//
// sqrt(magnitude, magnitude);
// Mat flatMagnitude = magnitude.reshape(1, 1);
// cv::sort(flatMagnitude, flatMagnitude, SORT_EVERY_ROW + SORT_DESCENDING);
// int thresholdIdx = static_cast<int>(percentile * flatMagnitude.total() / 100.0);
// double threshold = flatMagnitude.at<float>(thresholdIdx);
//
// Mat mask = magnitude >= threshold;
// Scalar meanVal = mean(src_float, mask);
//
// cout << "Estimated illumination: " << meanVal << endl;
// return Vec3f(meanVal[0], meanVal[1], meanVal[2]);
//}
//
//void applyWhiteBalance(Mat& src, Mat& dst, Vec3f illumination) {
// vector<Mat> channels(3);
// src.convertTo(src, CV_32FC3);
// split(src, channels);
//
// for (int i = 0; i < 3; i++) {
// channels[i] /= illumination[i];
// }
//
// merge(channels, dst);
// dst.convertTo(dst, CV_8U);
//}
//
//void simpleWhiteBalance(Mat& src, Mat& dst) {
// // Convert image to floating point for precision
// src.convertTo(dst, CV_32F);
//
// // Split the image into separate color channels
// vector<Mat> channels(3);
// split(dst, channels);
//
// // Calculate the average intensity for each channel
// double avgB = mean(channels[0])[0];
// double avgG = mean(channels[1])[0];
// double avgR = mean(channels[2])[0];
//
// // Calculate the total average intensity
// double avgTotal = (avgB + avgG + avgR) / 3.0;
//
// // Scale each channel to adjust the white balance
// channels[0] *= avgTotal / avgB;
// channels[1] *= avgTotal / avgG;
// channels[2] *= avgTotal / avgR;
//
// // Merge the channels back into one image
// merge(channels, dst);
//
// // Convert back to 8-bit color
// dst.convertTo(dst, CV_8U);
//}
//int AutoWhiteBalance() {
// Mat src = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\cat.jpg");
// if (src.empty()) {
// cout << "Could not open or find the image" << endl;
// return -1;
// }
//
// Mat dst;
// Vec3f illumination = estimateIllumination(src, 0.1); // Top 1% of gradients
// applyWhiteBalance(src, dst, illumination);
//
// //simpleWhiteBalance(src,dst);
// imshow("Original Image", src);
// imshow("White Balanced Image", dst);
// cv::waitKey(0);
//
// return 0;
//}
//
//
//int BrightEnhancement() {
// // Load the input image
// Mat inputImage = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\dark.jpg", IMREAD_COLOR);
//
// // Check if the image was loaded successfully
// if (inputImage.empty()) {
// cout << "Error: Could not open or find the image" << endl;
// return -1;
// }
//
// // Separate the input image into B, G, and R channels
// vector<Mat> channels;
// split(inputImage, channels);
//
// // Enhance brightness for each channel individually
// double brightnessScaleFactor = 1.5; // Scaling factor for brightness enhancement
// for (int i = 0; i < channels.size(); ++i) {
// channels[i] *= brightnessScaleFactor;
// }
//
// // Merge the channels back into a BGR image
// Mat enhancedImage;
// merge(channels, enhancedImage);
//
// // Display original and enhanced images
// namedWindow("Original Image", WINDOW_AUTOSIZE);
// imshow("Original Image", inputImage);
//
// namedWindow("Enhanced Image", WINDOW_AUTOSIZE);
// imshow("Enhanced Image", enhancedImage);
//
// // Wait for a keystroke in the window
// waitKey(0);
//
// // Close all OpenCV windows
// destroyAllWindows();
//
// return 0;
//}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
# ANSFR Unit Test
# vcxproj also compiles ANSFRCommon.cpp and OpenVINO engine sources inline
add_executable(ANSFR-UnitTest
ANSFR-UnitTest.cpp
${CMAKE_SOURCE_DIR}/modules/ANSFR/ANSFRCommon.cpp
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/src/faceapp/cnn.cpp
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/src/utils/args_helper.cpp
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/src/utils/common.cpp
)
target_include_directories(ANSFR-UnitTest PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/modules/ANSFR
${CMAKE_SOURCE_DIR}/modules/ANSODEngine
${CMAKE_SOURCE_DIR}/modules/ANSODEngine/CUDA
${CMAKE_SOURCE_DIR}/modules/ANSCV
${CMAKE_SOURCE_DIR}/modules/ANSMOT
${CMAKE_SOURCE_DIR}/engines/ONNXEngine
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/include
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/include/faceapp
${CMAKE_SOURCE_DIR}/engines/TensorRTAPI/include
${CMAKE_SOURCE_DIR}/MediaClient
${CMAKE_SOURCE_DIR}/MediaClient/media
${CMAKE_SOURCE_DIR}/MediaClient/rtsp
${CMAKE_SOURCE_DIR}/MediaClient/rtp
${CMAKE_SOURCE_DIR}/MediaClient/bm
${CMAKE_SOURCE_DIR}/MediaClient/http
${CMAKE_SOURCE_DIR}/MediaClient/directx
${CMAKE_SOURCE_DIR}/MediaClient/rtmp
${CMAKE_SOURCE_DIR}/MediaClient/librtmp
${CMAKE_SOURCE_DIR}/MediaClient/srt
${CMAKE_SOURCE_DIR}/MediaClient/ffmpeg/include
${CMAKE_SOURCE_DIR}/MediaClient/openssl/include
${CMAKE_SOURCE_DIR}/MediaClient/libsrt/include
${SHARED_INCLUDE_DIR}
${ANLS_ROOT}/TurboJpeg
${ANSLIBS_DIR}/faiss
${ANSLIBS_DIR}/TensorRT/include
${RESEARCH_DIR}/boost_1_88_0
C:/fastdeploy_gpu/include
)
target_link_libraries(ANSFR-UnitTest
PRIVATE ANSFR
PRIVATE ANSODEngine
PRIVATE ANSCV
PRIVATE ANSLicensingSystem
PRIVATE anslicensing
PRIVATE ANSMOT
PRIVATE opencv
PRIVATE onnxruntime
PRIVATE openvino
PRIVATE boost
PRIVATE CUDA::cudart
PRIVATE CUDA::cudart_static
PRIVATE CUDA::cublas
PRIVATE CUDA::cublasLt
PRIVATE CUDA::nvjpeg
)
if(WIN32)
target_link_libraries(ANSFR-UnitTest PRIVATE ${WIN_COMMON_LIBS})
endif()
target_compile_definitions(ANSFR-UnitTest PRIVATE UNICODE _UNICODE)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
# ANSLPR Unit Test
add_executable(ANSLPR-UnitTest
ANSLPR-UnitTest.cpp
)
target_include_directories(ANSLPR-UnitTest PRIVATE
${CMAKE_SOURCE_DIR}/modules/ANSLPR
${CMAKE_SOURCE_DIR}/modules/ANSLPR/include
${CMAKE_SOURCE_DIR}/modules/ANSODEngine
${CMAKE_SOURCE_DIR}/modules/ANSCV
${CMAKE_SOURCE_DIR}/MediaClient
${CMAKE_SOURCE_DIR}/MediaClient/media
${CMAKE_SOURCE_DIR}/MediaClient/rtsp
${CMAKE_SOURCE_DIR}/MediaClient/rtp
${CMAKE_SOURCE_DIR}/MediaClient/bm
${CMAKE_SOURCE_DIR}/MediaClient/http
${CMAKE_SOURCE_DIR}/MediaClient/directx
${CMAKE_SOURCE_DIR}/MediaClient/rtmp
${CMAKE_SOURCE_DIR}/MediaClient/librtmp
${CMAKE_SOURCE_DIR}/MediaClient/srt
${CMAKE_SOURCE_DIR}/MediaClient/ffmpeg/include
${CMAKE_SOURCE_DIR}/MediaClient/openssl/include
${CMAKE_SOURCE_DIR}/MediaClient/libsrt/include
${ANLS_ROOT}/TurboJpeg
${CMAKE_SOURCE_DIR}/modules/ANSMOT
${CMAKE_SOURCE_DIR}/modules/ANSOCR/ANSPaddleOCR
${CMAKE_SOURCE_DIR}/modules/ANSOCR/ANSPaddleOCR/include
${CMAKE_SOURCE_DIR}/engines/ONNXEngine
${CMAKE_SOURCE_DIR}/engines/OpenVINOEngine/include
${CMAKE_SOURCE_DIR}/engines/TensorRTAPI/include
${SHARED_INCLUDE_DIR}
)
target_link_libraries(ANSLPR-UnitTest
PRIVATE ANSLPR
PRIVATE ANSODEngine
PRIVATE ANSCV
PRIVATE ANSLicensingSystem
PRIVATE anslicensing
PRIVATE ANSMOT
PRIVATE opencv
PRIVATE onnxruntime
PRIVATE openvino
PRIVATE boost
PRIVATE CUDA::cudart
)
if(WIN32)
target_link_libraries(ANSLPR-UnitTest PRIVATE ${WIN_COMMON_LIBS})
endif()
target_compile_definitions(ANSLPR-UnitTest PRIVATE UNICODE _UNICODE)

View File

@@ -0,0 +1,404 @@
#include <iostream>
#include <opencv2/highgui.hpp>
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/json_parser.hpp"
#include "boost/foreach.hpp"
#include "boost/optional.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/dnn/dnn.hpp>
#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <functional>
#include <filesystem>
#include <algorithm>
#include <chrono>
#include <ANSOCRBase.h>
#ifdef WIN32
const char sep = '\\';
#else
const char sep = '/';
#endif
using namespace cv;
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();
}
return ret;
}
unsigned char* CVMatToBytes(cv::Mat image, unsigned int& bufferLengh)
{
int size = int(image.total() * image.elemSize());
std::cout << "size:" << size << std::endl;
unsigned char* bytes = new unsigned char[size]; // you will have to delete[] that later
std::memcpy(bytes, image.data, size * sizeof(unsigned char));
bufferLengh = size * sizeof(unsigned char);
return bytes;
}
int TestOCRImage() {
ANSCENTER::ANSOCRBase* infHandle = nullptr;
boost::property_tree::ptree root;
boost::property_tree::ptree detectionObjects;
boost::property_tree::ptree pt;
std::filesystem::path currentPath = std::filesystem::current_path();
std::cout << "Current working directory: " << currentPath << std::endl;
std::string licenseKey = "";
std::string modelFilePath = currentPath.string() + "\\ansocrmodels.zip";
std::string imagePath = currentPath.string() + "\\ocrsample.png";
std::string defaultDir = "C:\\Programs\\DemoAssets\\ANSAIModels";
if (!std::filesystem::exists(modelFilePath)) modelFilePath = defaultDir + "\\ANS_GenericOCR_v1.0.zip";
if (!std::filesystem::exists(imagePath)) imagePath = defaultDir + "\\ocrsample.png";
imagePath = "C:\\Projects\\ANSVIS\\Documentation\\TestImages\\OCR\\ocrsample.png";
int language = 0; // CUSTOM
int engine = 0;
int createResult = CreateANSOCRHandle(&infHandle, licenseKey.c_str(), modelFilePath.c_str(), "", language, engine);
std::cout << "ANSOCR Engine Creation:" << createResult << std::endl;
cv::Mat input = cv::imread(imagePath, cv::IMREAD_COLOR);
cv::Mat frame = input.clone();
int height = frame.rows;
int width = frame.cols;
unsigned int bufferLength = 0;
unsigned char* jpeg_string = CVMatToBytes(frame, bufferLength);
std::string detectionResult = RunInferenceBinary(&infHandle, jpeg_string, width, height);
std::cout << "Result:" << detectionResult;
delete jpeg_string;
if (!detectionResult.empty()) {
pt.clear();
std::stringstream ss;
ss.clear();
ss << detectionResult;
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH(const boost::property_tree::ptree::value_type & child, pt.get_child("results"))
{
const boost::property_tree::ptree& result = child.second;
const auto class_id = GetData<int>(result, "class_id");
const auto class_name = GetData<std::string>(result, "class_name");
const auto x = GetData<float>(result, "x");
const auto y = GetData<float>(result, "y");
const auto width = GetData<float>(result, "width");
const auto height = GetData<float>(result, "height");
cv::rectangle(frame, cv::Rect(x, y, width, height), 123, 2);
cv::putText(frame, cv::format("%s", class_name), cv::Point(x, y - 5),
0, 2.0, cv::Scalar(0, 0, 255), 3, cv::LINE_AA);
}
}
cv::resize(frame, frame, cv::Size(frame.cols / 2, frame.rows / 2)); // to half size or even smaller
frame.release();
ReleaseANSOCRHandle(&infHandle);
return 0;
}
int ANSOCR_VideoTest() {
// Get the current working directory
std::filesystem::path currentPath = std::filesystem::current_path();
// Print the current working directory
std::cout << "Current working directory: " << currentPath << std::endl;
boost::property_tree::ptree root;
boost::property_tree::ptree detectionObjects;
boost::property_tree::ptree pt;
ANSCENTER::ANSOCRBase* infHandle;
std::string licenseKey = "";
std::string modelFilePath = "C:\\ProgramData\\ANSCENTER\\Shared\\ANS_GenericOCR_v1.0.zip";
std::string videoFilePath = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\ALPR1.mp4";
cv::VideoCapture capture(videoFilePath);
if (!capture.isOpened()) {
printf("could not read this video file...\n");
return -1;
}
int language = 0;// CUSTOM
int engine = 0;
int createResult = CreateANSOCRHandle(&infHandle, licenseKey.c_str(), modelFilePath.c_str(), "", language, engine);
while (true)
{
cv::Mat frame;
if (!capture.read(frame)) // if not success, break loop
{
std::cout << "\n Cannot read the video file. please check your video.\n";
break;
}
auto start = std::chrono::system_clock::now();
unsigned int bufferLength = 0;
unsigned char* jpeg_string = CVMatToBytes(frame, bufferLength);
int height = frame.rows;
int width = frame.cols;
std::string detectionResult = RunInferenceBinary(&infHandle, jpeg_string, width, height);
if (!detectionResult.empty()) {
pt.clear();
std::stringstream ss;
ss.clear();
ss << detectionResult;
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH(const boost::property_tree::ptree::value_type & child, pt.get_child("results"))
{
const boost::property_tree::ptree& result = child.second;
const auto class_id = GetData<int>(result, "class_id");
const auto class_name = GetData<std::string>(result, "class_name");
const auto x = GetData<float>(result, "x");
const auto y = GetData<float>(result, "y");
const auto width = GetData<float>(result, "width");
const auto height = GetData<float>(result, "height");
cv::rectangle(frame, cv::Rect(x, y, width, height), 123, 2);
cv::putText(frame, cv::format("%s", class_name), cv::Point(x, y - 5),
0, 2.0, cv::Scalar(0, 0, 255), 3, cv::LINE_AA);
}
}
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()));
// cv::resize(frame, frame, cv::Size(frame.cols / 2, frame.rows / 2)); // to half size or even smaller
cv::imshow("ANSOCR", frame);
if (cv::waitKey(30) == 27) // Wait for 'esc' key press to exit
{
std::cout << "End of inserting faces.\n";
}
frame.release();
delete jpeg_string;
}
capture.release();
cv::destroyAllWindows();
ReleaseANSOCRHandle(&infHandle);
}
// Viewer state for zoom/pan
struct ImageViewerState {
cv::Mat image; // Full-resolution annotated image
double zoom = 1.0; // 1.0 = fit-to-screen
double panX = 0.0; // Top-left corner in original image coords
double panY = 0.0;
int dispW, dispH; // Display window size (pixels)
double fitScale; // Base scale to fit image into window
bool dragging = false;
int dragX0, dragY0;
double panX0, panY0;
bool dirty = true;
};
static void onViewerMouse(int event, int x, int y, int flags, void* userdata) {
ImageViewerState& s = *(ImageViewerState*)userdata;
if (event == cv::EVENT_MOUSEWHEEL) {
double factor = (cv::getMouseWheelDelta(flags) > 0) ? 1.25 : 0.8;
// Zoom centered on mouse cursor position
double sc = s.fitScale * s.zoom;
double imgX = s.panX + x / sc;
double imgY = s.panY + y / sc;
s.zoom = std::clamp(s.zoom * factor, 0.2, 50.0);
double newSc = s.fitScale * s.zoom;
s.panX = imgX - x / newSc;
s.panY = imgY - y / newSc;
s.dirty = true;
}
else if (event == cv::EVENT_LBUTTONDOWN) {
s.dragging = true;
s.dragX0 = x; s.dragY0 = y;
s.panX0 = s.panX; s.panY0 = s.panY;
}
else if (event == cv::EVENT_MOUSEMOVE && s.dragging) {
double sc = s.fitScale * s.zoom;
s.panX = s.panX0 - (x - s.dragX0) / sc;
s.panY = s.panY0 - (y - s.dragY0) / sc;
s.dirty = true;
}
else if (event == cv::EVENT_LBUTTONUP) {
s.dragging = false;
}
}
int TestOCRv5mage() {
ANSCENTER::ANSOCRBase* infHandle = nullptr;
boost::property_tree::ptree root;
boost::property_tree::ptree detectionObjects;
boost::property_tree::ptree pt;
std::filesystem::path currentPath = std::filesystem::current_path();
std::cout << "Current working directory: " << currentPath << std::endl;
std::string licenseKey = "";
std::string modelFilePath = "C:\\Projects\\ANSVIS\\Models\\ANS_GenericOCR_v2.0.zip";
std::string imagePath = "E:\\Programs\\DemoAssets\\Images\\OCR\\ref3_000.bmp";
int language = 0; // CUSTOM
int engine = 1;// GPU
// For high-resolution images with PP-OCRv5 server models, use higher limitSideLen
// (default 960 downscales large images too aggressively, missing small text)
int gpuId = 0;
double detDBThresh = 0.3, detBoxThresh = 0.6, detUnclipRatio = 1.5;
double clsThresh = 0.9;
int useDilation = 0;
int limitSideLen = 2560; // 2560 Higher resolution for server-grade detection
int createResult = CreateANSOCRHandleEx(&infHandle, licenseKey.c_str(), modelFilePath.c_str(), "",
language, engine, gpuId, detDBThresh, detBoxThresh, detUnclipRatio, clsThresh, useDilation, limitSideLen);
std::cout << "ANSOCR Engine Creation:" << createResult << std::endl;
cv::Mat input = cv::imread(imagePath, cv::IMREAD_COLOR);
if (input.empty()) {
std::cerr << "Failed to load image: " << imagePath << std::endl;
ReleaseANSOCRHandle(&infHandle);
return -1;
}
cv::Mat frame = input.clone();
int height = frame.rows;
int width = frame.cols;
unsigned int bufferLength = 0;
unsigned char* jpeg_string = CVMatToBytes(frame, bufferLength);
// --- Warmup run (first run includes GPU kernel compilation / cache warmup) ---
auto warmupStart = std::chrono::high_resolution_clock::now();
std::string detectionResult = RunInferenceBinary(&infHandle, jpeg_string, width, height);
auto warmupEnd = std::chrono::high_resolution_clock::now();
double warmupMs = std::chrono::duration<double, std::milli>(warmupEnd - warmupStart).count();
std::cout << "Warmup inference: " << warmupMs << " ms" << std::endl;
std::cout << "Result:" << detectionResult << std::endl;
// --- Benchmark: run N iterations and report stats ---
const int benchmarkIterations = 10;
std::vector<double> times;
times.reserve(benchmarkIterations);
for (int i = 0; i < benchmarkIterations; ++i) {
auto t0 = std::chrono::high_resolution_clock::now();
std::string result = RunInferenceBinary(&infHandle, jpeg_string, width, height);
auto t1 = std::chrono::high_resolution_clock::now();
double ms = std::chrono::duration<double, std::milli>(t1 - t0).count();
times.push_back(ms);
std::cout << " Run " << (i + 1) << "/" << benchmarkIterations << ": " << ms << " ms" << std::endl;
}
std::sort(times.begin(), times.end());
double sum = std::accumulate(times.begin(), times.end(), 0.0);
double avg = sum / benchmarkIterations;
double median = (benchmarkIterations % 2 == 0)
? (times[benchmarkIterations / 2 - 1] + times[benchmarkIterations / 2]) / 2.0
: times[benchmarkIterations / 2];
std::cout << "\n=== Benchmark (" << benchmarkIterations << " runs) ===" << std::endl;
std::cout << " Avg: " << avg << " ms" << std::endl;
std::cout << " Median: " << median << " ms" << std::endl;
std::cout << " Min: " << times.front() << " ms" << std::endl;
std::cout << " Max: " << times.back() << " ms" << std::endl;
std::cout << " FPS: " << (1000.0 / avg) << std::endl;
delete[] jpeg_string;
// Draw OCR results on frame — 1.5x of original (was fontScale=1.5, thickness=3, offset=5)
double fontScale = 2.25; // 1.5 * 1.5
int boxThickness = 3;
int fontThickness = 5; // ceil(3 * 1.5)
int textOffset = 8;
if (!detectionResult.empty()) {
pt.clear();
std::stringstream ss;
ss.clear();
ss << detectionResult;
boost::property_tree::read_json(ss, pt);
BOOST_FOREACH(const boost::property_tree::ptree::value_type & child, pt.get_child("results"))
{
const boost::property_tree::ptree& result = child.second;
const auto class_id = GetData<int>(result, "class_id");
const auto class_name = GetData<std::string>(result, "class_name");
const auto x = GetData<float>(result, "x");
const auto y = GetData<float>(result, "y");
const auto w = GetData<float>(result, "width");
const auto h = GetData<float>(result, "height");
cv::rectangle(frame, cv::Rect((int)x, (int)y, (int)w, (int)h),
cv::Scalar(0, 255, 0), boxThickness);
cv::putText(frame, class_name, cv::Point((int)x, (int)y - textOffset),
cv::FONT_HERSHEY_SIMPLEX, fontScale, cv::Scalar(0, 0, 255), fontThickness, cv::LINE_AA);
}
}
// === Interactive Image Viewer (zoom/pan) ===
ImageViewerState vs;
vs.image = frame;
// Calculate scale to fit image into ~80% of a 1920x1080 screen
const int maxWinW = 1600, maxWinH = 900;
double scaleX = (double)maxWinW / frame.cols;
double scaleY = (double)maxWinH / frame.rows;
vs.fitScale = std::min(scaleX, scaleY);
if (vs.fitScale > 1.0) vs.fitScale = 1.0; // Don't upscale small images
vs.dispW = (int)(frame.cols * vs.fitScale);
vs.dispH = (int)(frame.rows * vs.fitScale);
const std::string winName = "ANSOCR [Scroll=Zoom | Drag=Pan | R=Reset | ESC=Quit]";
cv::namedWindow(winName, cv::WINDOW_AUTOSIZE);
cv::setMouseCallback(winName, onViewerMouse, &vs);
while (true) {
if (vs.dirty) {
double sc = vs.fitScale * vs.zoom;
int srcW = std::min((int)(vs.dispW / sc), vs.image.cols);
int srcH = std::min((int)(vs.dispH / sc), vs.image.rows);
if (srcW <= 0) srcW = 1;
if (srcH <= 0) srcH = 1;
int sx = std::clamp((int)vs.panX, 0, std::max(0, vs.image.cols - srcW));
int sy = std::clamp((int)vs.panY, 0, std::max(0, vs.image.rows - srcH));
vs.panX = sx;
vs.panY = sy;
cv::Mat roi = vs.image(cv::Rect(sx, sy, srcW, srcH));
cv::Mat display;
cv::resize(roi, display, cv::Size(vs.dispW, vs.dispH), 0, 0,
(sc >= 1.0) ? cv::INTER_LINEAR : cv::INTER_AREA);
// Overlay zoom info
cv::putText(display, cv::format("Zoom: %.1fx (%dx%d)", vs.zoom, vs.image.cols, vs.image.rows),
cv::Point(10, 25), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 255, 0), 2);
cv::imshow(winName, display);
vs.dirty = false;
}
int key = cv::waitKey(30) & 0xFF;
if (key == 27) break; // ESC to quit
if (key == 'r' || key == 'R') {
vs.zoom = 1.0; vs.panX = 0; vs.panY = 0; vs.dirty = true; // Reset view
}
if (key == '+' || key == '=') {
vs.zoom = std::min(vs.zoom * 1.25, 50.0); vs.dirty = true; // Keyboard zoom in
}
if (key == '-' || key == '_') {
vs.zoom = std::max(vs.zoom * 0.8, 0.2); vs.dirty = true; // Keyboard zoom out
}
// Quit when user closes the window (clicks X button)
if (cv::getWindowProperty(winName, cv::WND_PROP_VISIBLE) < 1) break;
}
cv::destroyAllWindows();
frame.release();
input.release();
ReleaseANSOCRHandle(&infHandle);
return 0;
}
int main()
{
TestOCRv5mage();
//ANSOCR_VideoTest();
// TestOCRImage();
/* for (int i = 0; i < 20; i++) {
TestOCRImage();
}*/
return 0;
}

View File

@@ -0,0 +1,23 @@
# ANSOCR Unit Test
add_executable(ANSOCR-UnitTest
ANSOCR-UnitTest.cpp
)
target_include_directories(ANSOCR-UnitTest PRIVATE
${CMAKE_SOURCE_DIR}/modules/ANSOCR
${SHARED_INCLUDE_DIR}
)
target_link_libraries(ANSOCR-UnitTest
PRIVATE ANSOCR
PRIVATE ANSLicensingSystem
PRIVATE anslicensing
PRIVATE opencv
PRIVATE boost
)
if(WIN32)
target_link_libraries(ANSOCR-UnitTest PRIVATE ${WIN_COMMON_LIBS})
endif()
target_compile_definitions(ANSOCR-UnitTest PRIVATE UNICODE _UNICODE)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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();

View 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;
}

View 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)

View 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;
}

View 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;
}
}

View 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();
}
}

View 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;
}
}

View File

@@ -1,2 +1,6 @@
# ANSCORE Unit Tests
# Add test executables here as needed
add_subdirectory(ANSCV-UnitTest)
add_subdirectory(ANSODEngine-UnitTest)
add_subdirectory(ANSFR-UnitTest)
add_subdirectory(ANSLPR-UnitTest)
add_subdirectory(ANSOCR-UnitTest)