Add support to IMAQ conversion

This commit is contained in:
2026-04-12 21:55:09 +10:00
parent 0a8aaed215
commit 749c7db3c6
6 changed files with 151 additions and 3 deletions

View File

@@ -109,7 +109,8 @@
"Bash(grep -rn \"catch.*cv::Exception\" modules/ANSODEngine/*.cpp)", "Bash(grep -rn \"catch.*cv::Exception\" modules/ANSODEngine/*.cpp)",
"Bash(grep -l \"ANS_DBG\" modules/ANSLPR/*.cpp modules/ANSCV/*.cpp modules/ANSODEngine/*.cpp)", "Bash(grep -l \"ANS_DBG\" modules/ANSLPR/*.cpp modules/ANSCV/*.cpp modules/ANSODEngine/*.cpp)",
"Bash(grep -h \"ANS_DBG\\(\\\\\"\" modules/ANSLPR/*.cpp modules/ANSCV/ANSRTSP.cpp modules/ANSODEngine/ANSONNXYOLO.cpp modules/ANSODEngine/ANSRTYOLO.cpp modules/ANSODEngine/NV12PreprocessHelper.cpp)", "Bash(grep -h \"ANS_DBG\\(\\\\\"\" modules/ANSLPR/*.cpp modules/ANSCV/ANSRTSP.cpp modules/ANSODEngine/ANSONNXYOLO.cpp modules/ANSODEngine/ANSRTYOLO.cpp modules/ANSODEngine/NV12PreprocessHelper.cpp)",
"Bash(grep -v \"DNError\\\\|ViewerConfigPath\\\\|Failed to get\\\\|RecursiveDirectory\\\\|qt.qpa\\\\|DispBroker\\\\|SyncInvokeTable\\\\|Created new AppDomain\\\\|Destroying AppDomain\\\\|Trace Start\\\\|ExpandNode\\\\|PublisherMetadata\\\\|at System\\\\.\\\\|at NationalInstruments\\\\|at Mscorlib\\\\|Parameter name\\\\|^[[:space:]]*$\\\\|ArgumentException\\\\|Wrong type\\\\|Concerning target\\\\|Unable to get\\\\|RenderEventToBuffer\\\\|Getting next\\\\|Fetching Next\\\\|Image.Dispose\\\\|Graphics.Dispose\\\\|Image.FromStream\\\\|Inner Exception\\\\|FontFamily\\\\|InitHash\\\\|get_Item\\\\|MethodHandle.InvokeMethod\\\\|RuntimeMethodInfo\\\\|TargetInvocationException\\\\|Hashtable\\\\|LookupControl\\\\|RemoveControl\\\\|CloseInstance\\\\|FreeInstance\\\\|CrossDomainServer\" \"C:/Users/nghia/Downloads/AVNET-8845HS1.log\")" "Bash(grep -v \"DNError\\\\|ViewerConfigPath\\\\|Failed to get\\\\|RecursiveDirectory\\\\|qt.qpa\\\\|DispBroker\\\\|SyncInvokeTable\\\\|Created new AppDomain\\\\|Destroying AppDomain\\\\|Trace Start\\\\|ExpandNode\\\\|PublisherMetadata\\\\|at System\\\\.\\\\|at NationalInstruments\\\\|at Mscorlib\\\\|Parameter name\\\\|^[[:space:]]*$\\\\|ArgumentException\\\\|Wrong type\\\\|Concerning target\\\\|Unable to get\\\\|RenderEventToBuffer\\\\|Getting next\\\\|Fetching Next\\\\|Image.Dispose\\\\|Graphics.Dispose\\\\|Image.FromStream\\\\|Inner Exception\\\\|FontFamily\\\\|InitHash\\\\|get_Item\\\\|MethodHandle.InvokeMethod\\\\|RuntimeMethodInfo\\\\|TargetInvocationException\\\\|Hashtable\\\\|LookupControl\\\\|RemoveControl\\\\|CloseInstance\\\\|FreeInstance\\\\|CrossDomainServer\" \"C:/Users/nghia/Downloads/AVNET-8845HS1.log\")",
"Bash(grep -E \"\\\\.\\(h|cpp\\)$\")"
] ]
} }
} }

View File

@@ -8,7 +8,7 @@
// Set to 0 for production builds to eliminate all debug output overhead. // Set to 0 for production builds to eliminate all debug output overhead.
// ============================================================================ // ============================================================================
#ifndef ANSCORE_DEBUGVIEW #ifndef ANSCORE_DEBUGVIEW
#define ANSCORE_DEBUGVIEW 1 // 1 = enabled (debug), 0 = disabled (production) #define ANSCORE_DEBUGVIEW 0 // 1 = enabled (debug), 0 = disabled (production)
#endif #endif
// ANS_DBG: Debug logging macro for DebugView (OutputDebugStringA on Windows). // ANS_DBG: Debug logging macro for DebugView (OutputDebugStringA on Windows).

View File

@@ -1,5 +1,6 @@
#include "ANSOpenCV.h" #include "ANSOpenCV.h"
#include "ANSMatRegistry.h" #include "ANSMatRegistry.h"
#include <nivision.h>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <json.hpp> #include <json.hpp>
@@ -5104,3 +5105,130 @@ extern "C" __declspec(dllexport) int ANSCV_AddSpeckleNoise_V2(uint64_t handleVal
} }
catch (...) { return -1; } catch (...) { return -1; }
} }
// ── IMAQ <-> cv::Mat conversion ──────────────────────────────────
extern "C" __declspec(dllexport) int ANSCV_IMAQ2Image(Image* imaqImage, cv::Mat** imageOut) {
try {
if (!imaqImage || !imageOut) return -2;
ImageInfo info;
if (!imaqGetImageInfo(imaqImage, &info)) return -4;
if (!info.imageStart || info.xRes <= 0 || info.yRes <= 0) return -2;
int width = info.xRes;
int height = info.yRes;
int stride = info.pixelsPerLine; // pixels per row (may include padding)
cv::Mat result;
switch (info.imageType) {
case IMAQ_IMAGE_U8: {
// 8-bit grayscale: stride is in pixels = bytes
cv::Mat wrapper(height, width, CV_8UC1, info.imageStart, stride * sizeof(unsigned char));
result = wrapper.clone();
break;
}
case IMAQ_IMAGE_U16: {
// 16-bit grayscale
cv::Mat wrapper(height, width, CV_16UC1, info.imageStart, stride * sizeof(unsigned short));
result = wrapper.clone();
break;
}
case IMAQ_IMAGE_RGB: {
// IMAQ RGB is 32-bit RGBX (RGBValue: B,G,R,alpha) — same layout as BGRA
cv::Mat bgra(height, width, CV_8UC4, info.imageStart, stride * sizeof(RGBValue));
cv::cvtColor(bgra, result, cv::COLOR_BGRA2BGR);
break;
}
case IMAQ_IMAGE_SGL: {
// 32-bit float grayscale
cv::Mat wrapper(height, width, CV_32FC1, info.imageStart, stride * sizeof(float));
result = wrapper.clone();
break;
}
default:
return -5; // Unsupported image type
}
*imageOut = anscv_mat_new(result);
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error in ANSCV_IMAQ2Image: " << e.what() << std::endl;
return -3;
}
catch (...) { return -1; }
}
extern "C" __declspec(dllexport) int ANSCV_Image2IMAQ(cv::Mat** imageIn, Image* imaqImage) {
try {
if (!imageIn || !(*imageIn) || (*imageIn)->empty() || !imaqImage) return -2;
const cv::Mat& mat = **imageIn;
int width = mat.cols;
int height = mat.rows;
// Set the IMAQ image size (allocates pixel buffer)
if (!imaqSetImageSize(imaqImage, width, height)) return -4;
ImageInfo info;
if (!imaqGetImageInfo(imaqImage, &info)) return -4;
if (!info.imageStart) return -4;
int dstStride = info.pixelsPerLine;
switch (mat.type()) {
case CV_8UC1: {
// Grayscale -> IMAQ_IMAGE_U8
for (int y = 0; y < height; y++) {
memcpy(static_cast<unsigned char*>(info.imageStart) + y * dstStride,
mat.ptr<unsigned char>(y), width * sizeof(unsigned char));
}
break;
}
case CV_16UC1: {
// 16-bit grayscale -> IMAQ_IMAGE_U16
for (int y = 0; y < height; y++) {
memcpy(static_cast<unsigned char*>(info.imageStart) + y * dstStride * sizeof(unsigned short),
mat.ptr<unsigned short>(y), width * sizeof(unsigned short));
}
break;
}
case CV_8UC3: {
// BGR -> IMAQ_IMAGE_RGB (BGRA with alpha=0)
cv::Mat bgra;
cv::cvtColor(mat, bgra, cv::COLOR_BGR2BGRA);
for (int y = 0; y < height; y++) {
memcpy(static_cast<unsigned char*>(info.imageStart) + y * dstStride * sizeof(RGBValue),
bgra.ptr<unsigned char>(y), width * sizeof(RGBValue));
}
break;
}
case CV_8UC4: {
// BGRA -> IMAQ_IMAGE_RGB directly
for (int y = 0; y < height; y++) {
memcpy(static_cast<unsigned char*>(info.imageStart) + y * dstStride * sizeof(RGBValue),
mat.ptr<unsigned char>(y), width * sizeof(RGBValue));
}
break;
}
case CV_32FC1: {
// Float -> IMAQ_IMAGE_SGL
for (int y = 0; y < height; y++) {
memcpy(static_cast<unsigned char*>(info.imageStart) + y * dstStride * sizeof(float),
mat.ptr<float>(y), width * sizeof(float));
}
break;
}
default:
return -5; // Unsupported cv::Mat type
}
return 1;
}
catch (const std::exception& e) {
std::cerr << "Error in ANSCV_Image2IMAQ: " << e.what() << std::endl;
return -3;
}
catch (...) { return -1; }
}

View File

@@ -7,6 +7,12 @@
#include <vector> #include <vector>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
// Forward declaration for NI Vision IMAQ Image (avoids nivision.h dependency for consumers)
#ifndef NI_IMAGE_TYPE_DEF
#define NI_IMAGE_TYPE_DEF
typedef struct Image_struct Image;
#endif
#define MUTEX_TIMEOUT_MS 45000 #define MUTEX_TIMEOUT_MS 45000
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace ANSCENTER namespace ANSCENTER
@@ -161,4 +167,8 @@ extern "C" __declspec(dllexport) int ANSCV_ImagePatternMatchs_S(cv::Mat** image
extern "C" __declspec(dllexport) int ANSCV_ImagesToMP4_S(const char* imageFolder, const char* outputVideoPath, int targetDurationSec); extern "C" __declspec(dllexport) int ANSCV_ImagesToMP4_S(const char* imageFolder, const char* outputVideoPath, int targetDurationSec);
// IMAQ <-> cv::Mat conversion functions
extern "C" __declspec(dllexport) int ANSCV_IMAQ2Image(Image* imaqImage, cv::Mat** imageOut);
extern "C" __declspec(dllexport) int ANSCV_Image2IMAQ(cv::Mat** imageIn, Image* imaqImage);
#endif #endif

View File

@@ -45,6 +45,15 @@ target_include_directories(ANSCV PUBLIC
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
) )
# NI Vision (IMAQ) support
target_include_directories(ANSCV PRIVATE
"C:/Program Files (x86)/National Instruments/Shared/ExternalCompilerSupport/C/include"
)
target_link_directories(ANSCV PRIVATE
"C:/Program Files (x86)/National Instruments/Shared/ExternalCompilerSupport/C/lib64/msvc"
)
target_link_libraries(ANSCV PRIVATE nivision)
# MediaClient includes (referenced from original ANLS) # MediaClient includes (referenced from original ANLS)
target_include_directories(ANSCV PRIVATE target_include_directories(ANSCV PRIVATE
${CMAKE_SOURCE_DIR}/MediaClient ${CMAKE_SOURCE_DIR}/MediaClient

View File

@@ -3656,7 +3656,7 @@ int ALPR_OCR_Test() {
ANSCENTER::ANSALPR* infHandle = nullptr; ANSCENTER::ANSALPR* infHandle = nullptr;
std::string licenseKey = ""; std::string licenseKey = "";
std::string modelFilePath = "C:\\Projects\\ANSVIS\\Models\\ANS_GenericALPR_v2.0.zip"; std::string modelFilePath = "C:\\Projects\\ANSVIS\\Models\\ANS_GenericALPR_v2.0.zip";
std::string imagePath = "C:\\Programs\\ModelTraining\\JLPD\\data\\test7.jpg"; std::string imagePath = "C:\\Programs\\ModelTraining\\JLPD\\data\\test3.jpg";
int engineType = 2; // ANSALPR_OCR int engineType = 2; // ANSALPR_OCR
double detectionThreshold = 0.3; double detectionThreshold = 0.3;