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
|
# 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