Add unit tests
This commit is contained in:
1471
tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp
Normal file
1471
tests/ANSCV-UnitTest/ANSCV-UnitTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
41
tests/ANSCV-UnitTest/CMakeLists.txt
Normal file
41
tests/ANSCV-UnitTest/CMakeLists.txt
Normal 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)
|
||||
469
tests/ANSCV-UnitTest/OpenCVTest.cpp
Normal file
469
tests/ANSCV-UnitTest/OpenCVTest.cpp
Normal 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;
|
||||
//}
|
||||
1346
tests/ANSFR-UnitTest/ANSFR-UnitTest.cpp
Normal file
1346
tests/ANSFR-UnitTest/ANSFR-UnitTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
65
tests/ANSFR-UnitTest/CMakeLists.txt
Normal file
65
tests/ANSFR-UnitTest/CMakeLists.txt
Normal 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)
|
||||
2780
tests/ANSLPR-UnitTest/ANSLPR-UnitTest.cpp
Normal file
2780
tests/ANSLPR-UnitTest/ANSLPR-UnitTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
52
tests/ANSLPR-UnitTest/CMakeLists.txt
Normal file
52
tests/ANSLPR-UnitTest/CMakeLists.txt
Normal 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)
|
||||
404
tests/ANSOCR-UnitTest/ANSOCR-UnitTest.cpp
Normal file
404
tests/ANSOCR-UnitTest/ANSOCR-UnitTest.cpp
Normal 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;
|
||||
}
|
||||
23
tests/ANSOCR-UnitTest/CMakeLists.txt
Normal file
23
tests/ANSOCR-UnitTest/CMakeLists.txt
Normal 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)
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user