From 2c32889753c587ce4a23f9449ad6f35379d0dddb Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Mon, 18 Nov 2024 17:25:11 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=98=88?= =?UTF-8?q?=E5=80=BC=E8=B0=83=E6=95=B4=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 8 +- Matrox/color_range.cpp | 256 ++++++++++++++++++++++++----------------- Matrox/color_range.h | 58 ++++++++++ Matrox/utils.cpp | 9 ++ Matrox/utils.h | 21 ++++ 5 files changed, 241 insertions(+), 111 deletions(-) create mode 100644 Matrox/utils.cpp create mode 100644 Matrox/utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 299634d..bb94a0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,8 @@ add_executable(cotton_color cotton_color.cpp) target_link_libraries(cotton_color Qt6::Widgets ${OpenCV_LIBS} comdlg32) # 添加可执行文件 cotton_color -add_executable(cotton_range Matrox/color_range.cpp) +add_executable(cotton_range Matrox/color_range.cpp + Matrox/color_range.h Matrox/utils.h Matrox/utils.cpp) # 链接 OpenCV 和 Qt 库 target_link_libraries(cotton_range Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) @@ -52,11 +53,12 @@ add_executable(cotton_color2 cotton_color2.cpp) # 链接 OpenCV 和 Qt 库 target_link_libraries(cotton_color2 Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) -add_executable(color_matching Matrox/template_matching.cpp) +add_executable(color_matching Matrox/template_matching.cpp + Matrox/utils.cpp + Matrox/utils.h) target_link_libraries(color_matching Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) - add_executable(ui Matrox/ui.cpp) target_link_libraries(ui Qt6::Widgets) diff --git a/Matrox/color_range.cpp b/Matrox/color_range.cpp index e4d93ef..d070f69 100644 --- a/Matrox/color_range.cpp +++ b/Matrox/color_range.cpp @@ -1,44 +1,28 @@ -// -// Created by zjc on 24-11-12. -// - -#include #include -#include -#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton2.bmp") +#include +#include +#include +#include "utils.h" -// 全局变量,方便在各个函数中使用 +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton_image\\174.bmp") +#define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\diguandai.png") + +// Define LabRange structure +struct LabRange { + std::pair rangeL; + std::pair rangeA; + std::pair rangeB; +}; + +// Global variables MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; - -// 时间测量模板函数 -template -void measureExecutionTime(Func func) { - // 获取当前时间作为起点 - auto start = std::chrono::high_resolution_clock::now(); - - // 执行传入的函数 - func(); - - // 获取当前时间作为结束点 - auto end = std::chrono::high_resolution_clock::now(); - - // 计算时间差并转换为毫秒 - auto duration = std::chrono::duration_cast(end - start); - - std::cout << "Function execution time: " << duration.count() << " milliseconds" << std::endl; -} - -// LabProcess 函数,支持通过参数控制阈值范围,提供默认值 -void LabProcess(MIL_ID& inputImage, MIL_ID& outputImageLab, - MIL_DOUBLE lowerL = 101.0, MIL_DOUBLE upperL = 135.0, - MIL_DOUBLE lowerA = 101.0, MIL_DOUBLE upperA = 120.0, - MIL_DOUBLE lowerB = 95.0, MIL_DOUBLE upperB = 134.0) +// Optimized LabProcess function +void lab_process(MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params) { MIL_ID MilLabImage = M_NULL, MilLChannel = M_NULL, MilAChannel = M_NULL, MilBChannel = M_NULL; - MIL_ID MilBinaryL = M_NULL, MilBinaryA = M_NULL, MilBinaryB = M_NULL; - // 检查输入图像的通道数 + // Check number of bands MIL_INT NumBands = 0; MbufInquire(inputImage, M_SIZE_BAND, &NumBands); if (NumBands != 3) @@ -47,62 +31,84 @@ void LabProcess(MIL_ID& inputImage, MIL_ID& outputImageLab, return; } - // 分配用于存储 Lab 图像的缓冲区 - MbufAllocColor(MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL), 3, - MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), - 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, - &MilLabImage); + // Inquire image properties once + MIL_ID MilSystem = MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL); + MIL_INT SizeX = MbufInquire(inputImage, M_SIZE_X, M_NULL); + MIL_INT SizeY = MbufInquire(inputImage, M_SIZE_Y, M_NULL); - // 将图像从 sRGB 转换到 Lab + // Allocate buffer for Lab image + MbufAllocColor(MilSystem, 3, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilLabImage); + + // Convert image from sRGB to Lab MimConvert(inputImage, MilLabImage, M_SRGB_TO_LAB); - // 创建 Lab 通道的子缓冲区 + // Create child buffers for L, a, b channels MbufChildColor(MilLabImage, 0, &MilLChannel); MbufChildColor(MilLabImage, 1, &MilAChannel); MbufChildColor(MilLabImage, 2, &MilBChannel); - // 分配二值图像缓冲区 - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryL); - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryA); - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryB); + // Allocate output image as 1-bit image + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &outputImageLab); + MbufClear(outputImageLab, 0); // Initialize to 0 - // 对每个通道进行阈值分割 - MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, lowerL, upperL); - MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, lowerA, upperA); - MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, lowerB, upperB); + // Pre-allocate binary buffers as 1-bit images + MIL_ID MilBinaryL = M_NULL, MilBinaryA = M_NULL, MilBinaryB = M_NULL, MilResultLab = M_NULL; + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryL); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryA); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryB); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilResultLab); - // 分配输出图像缓冲区 - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &outputImageLab); + const std::vector colors = {"green", "blue", "orange", "black", "red", "purple"}; - // 将结果合并 - MimArith(MilBinaryL, MilBinaryA, outputImageLab, M_AND); - MimArith(outputImageLab, MilBinaryB, outputImageLab, M_AND); + // Iterate over colors + // 遍历颜色 + for (const auto& color : colors) { + // 构建参数键 + std::string L_min_key = color + "_L_min"; + std::string L_max_key = color + "_L_max"; + std::string a_min_key = color + "_a_min"; + std::string a_max_key = color + "_a_max"; + std::string b_min_key = color + "_b_min"; + std::string b_max_key = color + "_b_max"; - // 释放资源 + // 获取参数值 + int L_min = params.at(L_min_key); + int L_max = params.at(L_max_key); + int a_min = params.at(a_min_key); + int a_max = params.at(a_max_key); + int b_min = params.at(b_min_key); + int b_max = params.at(b_max_key); + + // 对每个通道进行二值化 + MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, L_min, L_max); + MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, a_min, a_max); + MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, b_min, b_max); + + // 合并阈值结果 + MimArith(MilBinaryL, MilBinaryA, MilResultLab, M_AND); + MimArith(MilResultLab, MilBinaryB, MilResultLab, M_AND); + + // 与输出图像合并 + MimArith(outputImageLab, MilResultLab, outputImageLab, M_OR); + } + + // Free binary buffers MbufFree(MilBinaryL); MbufFree(MilBinaryA); MbufFree(MilBinaryB); + MbufFree(MilResultLab); + + // Free resources MbufFree(MilLChannel); MbufFree(MilAChannel); MbufFree(MilBChannel); MbufFree(MilLabImage); } -// HSVProcess 函数,支持通过参数控制饱和度阈值,提供默认值 -void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturationThreshold = 120.0) +void hsv_process(MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params) { MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL; - + int saturationThreshold = params.at("saturation_threshold"); // 检查输入图像的通道数 MIL_INT NumBands = 0; MbufInquire(inputImage, M_SIZE_BAND, &NumBands); @@ -134,7 +140,8 @@ void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturatio M_IMAGE + M_PROC + M_DISP, &outputImageHSV); // 对 S 通道进行阈值分割 - MimBinarize(MilSChannel, outputImageHSV, M_GREATER, saturationThreshold, M_NULL); + MimBinarize(MilSChannel, outputImageHSV, M_GREATER, + saturationThreshold, M_NULL); // 释放资源 MbufFree(MilHChannel); @@ -143,62 +150,95 @@ void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturatio MbufFree(MilHSVImage); } -// 综合测试函数,调用 LabProcess 和 HSVProcess 并合并结果 -void test_hsv(MIL_ID& inputImage, - MIL_DOUBLE lowerL = 101.0, MIL_DOUBLE upperL = 135.0, - MIL_DOUBLE lowerA = 101.0, MIL_DOUBLE upperA = 120.0, - MIL_DOUBLE lowerB = 95.0, MIL_DOUBLE upperB = 134.0, - MIL_DOUBLE saturationThreshold = 120.0) -{ - MIL_ID MilResultLab = M_NULL, MilResultHSV = M_NULL, MilCombinedResult = M_NULL; +void high_sat_detect(MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { + MIL_ID output_hsv=M_NULL, output_lab=M_NULL; - // 调用 LabProcess - LabProcess(inputImage, MilResultLab, lowerL, upperL, lowerA, upperA, lowerB, upperB); + hsv_process(inputImage, output_hsv, params); + lab_process(inputImage, output_lab, params); - // 调用 HSVProcess - HSVProcess(inputImage, MilResultHSV, saturationThreshold); - - // 分配合并结果的缓冲区 MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilCombinedResult); + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, + M_IMAGE + M_PROC, &outputImage); // 合并 Lab 和 HSV 的结果(取“或”运算) - MimArith(MilResultLab, MilResultHSV, MilCombinedResult, M_OR); + MimArith(output_hsv, output_lab, outputImage, M_OR); - //// 显示合并后的结果图像 - MdispSelect(MilDisplay, MilCombinedResult); - - //// 等待用户查看处理后的图像 - printf("图像已处理并合并,按下 退出程序。\n"); - getchar(); - - // 释放资源 - MbufFree(MilResultLab); - MbufFree(MilResultHSV); - MbufFree(MilCombinedResult); + MbufFree(output_lab); + MbufFree(output_hsv); } - int main() { - MIL_ID MilImage = M_NULL; - - // 初始化 MIL 应用程序 + // Initialize MIL application MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); - // 加载输入图像 + // Load input image + MIL_ID MilImage = M_NULL; MbufRestore(IMAGE_PATH, MilSystem, &MilImage); - // 使用 lambda 表达式测量 test_hsv() 的执行时间 - measureExecutionTime([&]() { - test_hsv(MilImage); - }); + // Define color ranges + std::map params; + params["green_L_min"] = 68; + params["green_L_max"] = 125; + params["green_a_min"] = 101; + params["green_a_max"] = 120; + params["green_b_min"] = 130; + params["green_b_max"] = 140; + params["blue_L_min"] = 45; + params["blue_L_max"] = 66; + params["blue_a_min"] = 130; + params["blue_a_max"] = 145; + params["blue_b_min"] = 95; + params["blue_b_max"] = 105; - // 释放资源 + params["orange_L_min"] = 166; + params["orange_L_max"] = 191; + params["orange_a_min"] = 135; + params["orange_a_max"] = 142; + params["orange_b_min"] = 160; + params["orange_b_max"] = 174; + + params["black_L_min"] = 0; + params["black_L_max"] = 21; + params["black_a_min"] = 127; + params["black_a_max"] = 133; + params["black_b_min"] = 126; + params["black_b_max"] = 134; + + params["red_L_min"] = 71; + params["red_L_max"] = 97; + params["red_a_min"] = 143; + params["red_a_max"] = 153; + params["red_b_min"] = 33; + params["red_b_max"] = 154; + + params["purple_L_min"] = 171; + params["purple_L_max"] = 197; + params["purple_a_min"] = 131; + params["purple_a_max"] = 141; + params["purple_b_min"] = 108; + params["purple_b_max"] = 123; + + params["saturation_threshold"] = 150; + + // Initialize combined result + MIL_ID detection_result = M_NULL; + + // Measure execution time + measure_execution_time([&]() { + high_sat_detect(MilImage, detection_result, params); + }); + MbufSave(SAVE_PATH, detection_result); + // Display result + + std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; + getchar(); + + // Free resources + MbufFree(detection_result); MbufFree(MilImage); MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); return 0; -} \ No newline at end of file +} diff --git a/Matrox/color_range.h b/Matrox/color_range.h index 8a567e9..c50e1a1 100644 --- a/Matrox/color_range.h +++ b/Matrox/color_range.h @@ -5,4 +5,62 @@ #ifndef COLOR_RANGE_H #define COLOR_RANGE_H +#include +#include +#include + +void lab_process(MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params); +// 用法 +// std::map params; +// params["saturation_threshold"] = 150; + +void hsv_process(MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params); +// 用法 +// std::map params; +// params["green_L_min"] = 68; +// params["green_L_max"] = 125; +// params["green_a_min"] = 101; +// params["green_a_max"] = 120; +// params["green_b_min"] = 130; +// params["green_b_max"] = 140; +// +// params["blue_L_min"] = 45; +// params["blue_L_max"] = 66; +// params["blue_a_min"] = 130; +// params["blue_a_max"] = 145; +// params["blue_b_min"] = 95; +// params["blue_b_max"] = 105; +// +// params["orange_L_min"] = 166; +// params["orange_L_max"] = 191; +// params["orange_a_min"] = 135; +// params["orange_a_max"] = 142; +// params["orange_b_min"] = 160; +// params["orange_b_max"] = 174; +// +// params["black_L_min"] = 0; +// params["black_L_max"] = 21; +// params["black_a_min"] = 127; +// params["black_a_max"] = 133; +// params["black_b_min"] = 126; +// params["black_b_max"] = 134; +// +// params["red_L_min"] = 71; +// params["red_L_max"] = 97; +// params["red_a_min"] = 143; +// params["red_a_max"] = 153; +// params["red_b_min"] = 33; +// params["red_b_max"] = 154; +// +// params["purple_L_min"] = 171; +// params["purple_L_max"] = 197; +// params["purple_a_min"] = 131; +// params["purple_a_max"] = 141; +// params["purple_b_min"] = 108; +// params["purple_b_max"] = 123; +// + + + + #endif //COLOR_RANGE_H diff --git a/Matrox/utils.cpp b/Matrox/utils.cpp new file mode 100644 index 0000000..6db5430 --- /dev/null +++ b/Matrox/utils.cpp @@ -0,0 +1,9 @@ +// +// Created by zjc on 24-11-18. +// + +#include "utils.h" + + + +// 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/Matrox/utils.h b/Matrox/utils.h new file mode 100644 index 0000000..154a12a --- /dev/null +++ b/Matrox/utils.h @@ -0,0 +1,21 @@ +// +// Created by zjc on 24-11-18. +// + +#ifndef UTILS_H +#define UTILS_H + +#include +#include +template +// Time measurement function +void measure_execution_time(Func func) { + std::chrono::time_point start; + start = std::chrono::steady_clock::now(); + func(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + std::cout << "Function execution time: " << duration.count() << " milliseconds" << std::endl; +} + +#endif //UTILS_H From 263e32e9a0916d0d1e2db25cbfa34348dfed2b33 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Mon, 18 Nov 2024 17:25:11 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E7=BB=86=E5=BE=AE=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 8 +- Matrox/color_range.cpp | 253 +++++++++++++++++++++++------------------ Matrox/color_range.h | 58 ++++++++++ Matrox/utils.cpp | 9 ++ Matrox/utils.h | 21 ++++ 5 files changed, 237 insertions(+), 112 deletions(-) create mode 100644 Matrox/utils.cpp create mode 100644 Matrox/utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 299634d..bb94a0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,8 @@ add_executable(cotton_color cotton_color.cpp) target_link_libraries(cotton_color Qt6::Widgets ${OpenCV_LIBS} comdlg32) # 添加可执行文件 cotton_color -add_executable(cotton_range Matrox/color_range.cpp) +add_executable(cotton_range Matrox/color_range.cpp + Matrox/color_range.h Matrox/utils.h Matrox/utils.cpp) # 链接 OpenCV 和 Qt 库 target_link_libraries(cotton_range Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) @@ -52,11 +53,12 @@ add_executable(cotton_color2 cotton_color2.cpp) # 链接 OpenCV 和 Qt 库 target_link_libraries(cotton_color2 Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) -add_executable(color_matching Matrox/template_matching.cpp) +add_executable(color_matching Matrox/template_matching.cpp + Matrox/utils.cpp + Matrox/utils.h) target_link_libraries(color_matching Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) - add_executable(ui Matrox/ui.cpp) target_link_libraries(ui Qt6::Widgets) diff --git a/Matrox/color_range.cpp b/Matrox/color_range.cpp index e4d93ef..a3b1e60 100644 --- a/Matrox/color_range.cpp +++ b/Matrox/color_range.cpp @@ -1,44 +1,22 @@ -// -// Created by zjc on 24-11-12. -// - -#include #include -#include -#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton2.bmp") +#include +#include +#include +#include "utils.h" -// 全局变量,方便在各个函数中使用 +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton_image\\174.bmp") +#define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\diguandai.png") + + +// Global variables MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; - -// 时间测量模板函数 -template -void measureExecutionTime(Func func) { - // 获取当前时间作为起点 - auto start = std::chrono::high_resolution_clock::now(); - - // 执行传入的函数 - func(); - - // 获取当前时间作为结束点 - auto end = std::chrono::high_resolution_clock::now(); - - // 计算时间差并转换为毫秒 - auto duration = std::chrono::duration_cast(end - start); - - std::cout << "Function execution time: " << duration.count() << " milliseconds" << std::endl; -} - -// LabProcess 函数,支持通过参数控制阈值范围,提供默认值 -void LabProcess(MIL_ID& inputImage, MIL_ID& outputImageLab, - MIL_DOUBLE lowerL = 101.0, MIL_DOUBLE upperL = 135.0, - MIL_DOUBLE lowerA = 101.0, MIL_DOUBLE upperA = 120.0, - MIL_DOUBLE lowerB = 95.0, MIL_DOUBLE upperB = 134.0) +// Optimized LabProcess function +void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params) { MIL_ID MilLabImage = M_NULL, MilLChannel = M_NULL, MilAChannel = M_NULL, MilBChannel = M_NULL; - MIL_ID MilBinaryL = M_NULL, MilBinaryA = M_NULL, MilBinaryB = M_NULL; - // 检查输入图像的通道数 + // Check number of bands MIL_INT NumBands = 0; MbufInquire(inputImage, M_SIZE_BAND, &NumBands); if (NumBands != 3) @@ -47,62 +25,84 @@ void LabProcess(MIL_ID& inputImage, MIL_ID& outputImageLab, return; } - // 分配用于存储 Lab 图像的缓冲区 - MbufAllocColor(MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL), 3, - MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), - 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, - &MilLabImage); + // Inquire image properties once + MIL_ID MilSystem = MbufInquire(inputImage, M_OWNER_SYSTEM, M_NULL); + MIL_INT SizeX = MbufInquire(inputImage, M_SIZE_X, M_NULL); + MIL_INT SizeY = MbufInquire(inputImage, M_SIZE_Y, M_NULL); - // 将图像从 sRGB 转换到 Lab + // Allocate buffer for Lab image + MbufAllocColor(MilSystem, 3, SizeX, SizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC, &MilLabImage); + + // Convert image from sRGB to Lab MimConvert(inputImage, MilLabImage, M_SRGB_TO_LAB); - // 创建 Lab 通道的子缓冲区 + // Create child buffers for L, a, b channels MbufChildColor(MilLabImage, 0, &MilLChannel); MbufChildColor(MilLabImage, 1, &MilAChannel); MbufChildColor(MilLabImage, 2, &MilBChannel); - // 分配二值图像缓冲区 - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryL); - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryA); - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilBinaryB); + // Allocate output image as 1-bit image + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &outputImageLab); + MbufClear(outputImageLab, 0); // Initialize to 0 - // 对每个通道进行阈值分割 - MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, lowerL, upperL); - MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, lowerA, upperA); - MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, lowerB, upperB); + // Pre-allocate binary buffers as 1-bit images + MIL_ID MilBinaryL = M_NULL, MilBinaryA = M_NULL, MilBinaryB = M_NULL, MilResultLab = M_NULL; + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryL); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryA); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryB); + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilResultLab); - // 分配输出图像缓冲区 - MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &outputImageLab); + const std::vector colors = {"green", "blue", "orange", "black", "red", "purple"}; - // 将结果合并 - MimArith(MilBinaryL, MilBinaryA, outputImageLab, M_AND); - MimArith(outputImageLab, MilBinaryB, outputImageLab, M_AND); + // Iterate over colors + // 遍历颜色 + for (const auto& color : colors) { + // 构建参数键 + std::string L_min_key = color + "_L_min"; + std::string L_max_key = color + "_L_max"; + std::string a_min_key = color + "_a_min"; + std::string a_max_key = color + "_a_max"; + std::string b_min_key = color + "_b_min"; + std::string b_max_key = color + "_b_max"; - // 释放资源 + // 获取参数值 + int L_min = params.at(L_min_key); + int L_max = params.at(L_max_key); + int a_min = params.at(a_min_key); + int a_max = params.at(a_max_key); + int b_min = params.at(b_min_key); + int b_max = params.at(b_max_key); + + // 对每个通道进行二值化 + MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, L_min, L_max); + MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, a_min, a_max); + MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, b_min, b_max); + + // 合并阈值结果 + MimArith(MilBinaryL, MilBinaryA, MilResultLab, M_AND); + MimArith(MilResultLab, MilBinaryB, MilResultLab, M_AND); + + // 与输出图像合并 + MimArith(outputImageLab, MilResultLab, outputImageLab, M_OR); + } + + // Free binary buffers MbufFree(MilBinaryL); MbufFree(MilBinaryA); MbufFree(MilBinaryB); + MbufFree(MilResultLab); + + // Free resources MbufFree(MilLChannel); MbufFree(MilAChannel); MbufFree(MilBChannel); MbufFree(MilLabImage); } -// HSVProcess 函数,支持通过参数控制饱和度阈值,提供默认值 -void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturationThreshold = 120.0) +void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params) { MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL; - + int saturationThreshold = params.at("saturation_threshold"); // 检查输入图像的通道数 MIL_INT NumBands = 0; MbufInquire(inputImage, M_SIZE_BAND, &NumBands); @@ -134,7 +134,8 @@ void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturatio M_IMAGE + M_PROC + M_DISP, &outputImageHSV); // 对 S 通道进行阈值分割 - MimBinarize(MilSChannel, outputImageHSV, M_GREATER, saturationThreshold, M_NULL); + MimBinarize(MilSChannel, outputImageHSV, M_GREATER, + saturationThreshold, M_NULL); // 释放资源 MbufFree(MilHChannel); @@ -143,62 +144,96 @@ void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturatio MbufFree(MilHSVImage); } -// 综合测试函数,调用 LabProcess 和 HSVProcess 并合并结果 -void test_hsv(MIL_ID& inputImage, - MIL_DOUBLE lowerL = 101.0, MIL_DOUBLE upperL = 135.0, - MIL_DOUBLE lowerA = 101.0, MIL_DOUBLE upperA = 120.0, - MIL_DOUBLE lowerB = 95.0, MIL_DOUBLE upperB = 134.0, - MIL_DOUBLE saturationThreshold = 120.0) -{ - MIL_ID MilResultLab = M_NULL, MilResultHSV = M_NULL, MilCombinedResult = M_NULL; +void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { + MIL_ID output_hsv=M_NULL, output_lab=M_NULL; - // 调用 LabProcess - LabProcess(inputImage, MilResultLab, lowerL, upperL, lowerA, upperA, lowerB, upperB); + hsv_process(inputImage, output_hsv, params); + lab_process(inputImage, output_lab, params); - // 调用 HSVProcess - HSVProcess(inputImage, MilResultHSV, saturationThreshold); - - // 分配合并结果的缓冲区 MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &MilCombinedResult); + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, + M_IMAGE + M_PROC, &outputImage); // 合并 Lab 和 HSV 的结果(取“或”运算) - MimArith(MilResultLab, MilResultHSV, MilCombinedResult, M_OR); + MimArith(output_hsv, output_lab, outputImage, M_OR); - //// 显示合并后的结果图像 - MdispSelect(MilDisplay, MilCombinedResult); - - //// 等待用户查看处理后的图像 - printf("图像已处理并合并,按下 退出程序。\n"); - getchar(); - - // 释放资源 - MbufFree(MilResultLab); - MbufFree(MilResultHSV); - MbufFree(MilCombinedResult); + MbufFree(output_lab); + MbufFree(output_hsv); } - int main() { + // Initialize MIL application + MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, + M_NULL); + + // Load input image MIL_ID MilImage = M_NULL; - - // 初始化 MIL 应用程序 - MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); - - // 加载输入图像 MbufRestore(IMAGE_PATH, MilSystem, &MilImage); - // 使用 lambda 表达式测量 test_hsv() 的执行时间 - measureExecutionTime([&]() { - test_hsv(MilImage); - }); + // Define color ranges + std::map params; + params["green_L_min"] = 68; + params["green_L_max"] = 125; + params["green_a_min"] = 101; + params["green_a_max"] = 120; + params["green_b_min"] = 130; + params["green_b_max"] = 140; + params["blue_L_min"] = 45; + params["blue_L_max"] = 66; + params["blue_a_min"] = 130; + params["blue_a_max"] = 145; + params["blue_b_min"] = 95; + params["blue_b_max"] = 105; - // 释放资源 + params["orange_L_min"] = 166; + params["orange_L_max"] = 191; + params["orange_a_min"] = 135; + params["orange_a_max"] = 142; + params["orange_b_min"] = 160; + params["orange_b_max"] = 174; + + params["black_L_min"] = 0; + params["black_L_max"] = 21; + params["black_a_min"] = 127; + params["black_a_max"] = 133; + params["black_b_min"] = 126; + params["black_b_max"] = 134; + + params["red_L_min"] = 71; + params["red_L_max"] = 97; + params["red_a_min"] = 143; + params["red_a_max"] = 153; + params["red_b_min"] = 33; + params["red_b_max"] = 154; + + params["purple_L_min"] = 171; + params["purple_L_max"] = 197; + params["purple_a_min"] = 131; + params["purple_a_max"] = 141; + params["purple_b_min"] = 108; + params["purple_b_max"] = 123; + + params["saturation_threshold"] = 150; + + // Initialize combined result + MIL_ID detection_result = M_NULL; + + // Measure execution time + measure_execution_time([&]() { + high_sat_detect(MilImage, detection_result, params); + }); + MbufSave(SAVE_PATH, detection_result); + // Display result + + std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; + getchar(); + + // Free resources + MbufFree(detection_result); MbufFree(MilImage); MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); return 0; -} \ No newline at end of file +} diff --git a/Matrox/color_range.h b/Matrox/color_range.h index 8a567e9..0c4cfcc 100644 --- a/Matrox/color_range.h +++ b/Matrox/color_range.h @@ -5,4 +5,62 @@ #ifndef COLOR_RANGE_H #define COLOR_RANGE_H +#include +#include +#include + +void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params); +// 用法 +// std::map params; +// params["saturation_threshold"] = 150; + +void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params); +// 用法 +// std::map params; +// params["green_L_min"] = 68; +// params["green_L_max"] = 125; +// params["green_a_min"] = 101; +// params["green_a_max"] = 120; +// params["green_b_min"] = 130; +// params["green_b_max"] = 140; +// +// params["blue_L_min"] = 45; +// params["blue_L_max"] = 66; +// params["blue_a_min"] = 130; +// params["blue_a_max"] = 145; +// params["blue_b_min"] = 95; +// params["blue_b_max"] = 105; +// +// params["orange_L_min"] = 166; +// params["orange_L_max"] = 191; +// params["orange_a_min"] = 135; +// params["orange_a_max"] = 142; +// params["orange_b_min"] = 160; +// params["orange_b_max"] = 174; +// +// params["black_L_min"] = 0; +// params["black_L_max"] = 21; +// params["black_a_min"] = 127; +// params["black_a_max"] = 133; +// params["black_b_min"] = 126; +// params["black_b_max"] = 134; +// +// params["red_L_min"] = 71; +// params["red_L_max"] = 97; +// params["red_a_min"] = 143; +// params["red_a_max"] = 153; +// params["red_b_min"] = 33; +// params["red_b_max"] = 154; +// +// params["purple_L_min"] = 171; +// params["purple_L_max"] = 197; +// params["purple_a_min"] = 131; +// params["purple_a_max"] = 141; +// params["purple_b_min"] = 108; +// params["purple_b_max"] = 123; +// + + + + #endif //COLOR_RANGE_H diff --git a/Matrox/utils.cpp b/Matrox/utils.cpp new file mode 100644 index 0000000..6db5430 --- /dev/null +++ b/Matrox/utils.cpp @@ -0,0 +1,9 @@ +// +// Created by zjc on 24-11-18. +// + +#include "utils.h" + + + +// 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/Matrox/utils.h b/Matrox/utils.h new file mode 100644 index 0000000..154a12a --- /dev/null +++ b/Matrox/utils.h @@ -0,0 +1,21 @@ +// +// Created by zjc on 24-11-18. +// + +#ifndef UTILS_H +#define UTILS_H + +#include +#include +template +// Time measurement function +void measure_execution_time(Func func) { + std::chrono::time_point start; + start = std::chrono::steady_clock::now(); + func(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + std::cout << "Function execution time: " << duration.count() << " milliseconds" << std::endl; +} + +#endif //UTILS_H From 6a45cf96dcd924dee75d4ad6e2762d5ce7690029 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Mon, 18 Nov 2024 19:34:27 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BC=80=E9=97=AD?= =?UTF-8?q?=E8=BF=90=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Matrox/README.md | 68 +++++++++++++++++++++++++++++++++++++++++- Matrox/color_range.cpp | 33 +++++++++++++++++--- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/Matrox/README.md b/Matrox/README.md index 0932f19..d8335a5 100644 --- a/Matrox/README.md +++ b/Matrox/README.md @@ -5,4 +5,70 @@ include_directories(E:/QTexamble/matrox/Include) # 添加 MIL 库的库文件路径 link_directories(E:/QTexamble/matrox/LIB) file(GLOB MIL_LIBS E:/QTexamble/matrox/LIB/*.lib) -同理 将E:/QTexamble/matrox/LIB部分替换为安装目录下的.../Matrox Imaging/MIL/LIB 即可 \ No newline at end of file +同理 将E:/QTexamble/matrox/LIB部分替换为安装目录下的.../Matrox Imaging/MIL/LIB 即可 + + +## 鲜艳色彩检测功能 + +对应函数: + +```c++ +void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params); +// 用法 +// std::map params; +// params["saturation_threshold"] = 150; +// params["saturation_denoising"] = 2; + +void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params); +// std::map params; +// params["green_L_min"] = 68; +// params["green_L_max"] = 125; +// params["green_a_min"] = 101; +// params["green_a_max"] = 120; +// params["green_b_min"] = 130; +// params["green_b_max"] = 140; +// +// params["blue_L_min"] = 45; +// params["blue_L_max"] = 66; +// params["blue_a_min"] = 130; +// params["blue_a_max"] = 145; +// params["blue_b_min"] = 95; +// params["blue_b_max"] = 105; +// +// params["orange_L_min"] = 166; +// params["orange_L_max"] = 191; +// params["orange_a_min"] = 135; +// params["orange_a_max"] = 142; +// params["orange_b_min"] = 160; +// params["orange_b_max"] = 174; +// +// params["black_L_min"] = 0; +// params["black_L_max"] = 21; +// params["black_a_min"] = 127; +// params["black_a_max"] = 133; +// params["black_b_min"] = 126; +// params["black_b_max"] = 134; +// +// params["red_L_min"] = 71; +// params["red_L_max"] = 97; +// params["red_a_min"] = 143; +// params["red_a_max"] = 153; +// params["red_b_min"] = 33; +// params["red_b_max"] = 154; +// +// params["purple_L_min"] = 171; +// params["purple_L_max"] = 197; +// params["purple_a_min"] = 131; +// params["purple_a_max"] = 141; +// params["purple_b_min"] = 108; +// params["purple_b_max"] = 123; +// params["lab_denoising"] = 1; + +``` + +| | hsv_denoising = 0 | hsv_denoising = 1 | hsv_denoising = 2 | +| ----------------- | ----------------- | ----------------- | ------------------------------------------- | +| lab_denoising = 0 | | | | +| lab_denoising = 1 | | | ![diguandai](./README.assets/diguandai.png) | +| lab_denoising = 2 | | | | + diff --git a/Matrox/color_range.cpp b/Matrox/color_range.cpp index a3b1e60..3295e8b 100644 --- a/Matrox/color_range.cpp +++ b/Matrox/color_range.cpp @@ -15,6 +15,10 @@ MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params) { MIL_ID MilLabImage = M_NULL, MilLChannel = M_NULL, MilAChannel = M_NULL, MilBChannel = M_NULL; + MIL_ID lab_result=M_NULL; + + int denoising = params.at("lab_denoising"); + // Check number of bands MIL_INT NumBands = 0; @@ -51,7 +55,7 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryA); MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryB); MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilResultLab); - + MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &lab_result); const std::vector colors = {"green", "blue", "orange", "black", "red", "purple"}; // Iterate over colors @@ -83,8 +87,11 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma MimArith(MilResultLab, MilBinaryB, MilResultLab, M_AND); // 与输出图像合并 - MimArith(outputImageLab, MilResultLab, outputImageLab, M_OR); + MimArith(lab_result, MilResultLab, lab_result, M_OR); + } + MimClose(lab_result, MilResultLab, denoising, M_BINARY); + MimOpen(MilResultLab, outputImageLab, denoising, M_BINARY); // Free binary buffers MbufFree(MilBinaryL); @@ -97,12 +104,17 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma MbufFree(MilAChannel); MbufFree(MilBChannel); MbufFree(MilLabImage); + MbufFree(lab_result); } void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params) { MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL; + MIL_ID hsv_result = M_NULL; + MIL_ID hsv_denoising = M_NULL; int saturationThreshold = params.at("saturation_threshold"); + int denoising = params.at("saturation_denoising"); + // 检查输入图像的通道数 MIL_INT NumBands = 0; MbufInquire(inputImage, M_SIZE_BAND, &NumBands); @@ -131,17 +143,28 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma // 分配输出图像缓冲区 MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, - M_IMAGE + M_PROC + M_DISP, &outputImageHSV); + M_IMAGE + M_PROC + M_DISP, &hsv_result); + MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, + M_IMAGE + M_PROC + M_DISP, &hsv_denoising); + MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, + M_IMAGE + M_PROC + M_DISP, &outputImageHSV); // 对 S 通道进行阈值分割 - MimBinarize(MilSChannel, outputImageHSV, M_GREATER, + MimBinarize(MilSChannel, hsv_result, M_GREATER, saturationThreshold, M_NULL); + MimClose(hsv_result, hsv_denoising, denoising, M_BINARY); + MimOpen(hsv_denoising, outputImageHSV, denoising, M_BINARY); + // 释放资源 MbufFree(MilHChannel); MbufFree(MilSChannel); MbufFree(MilVChannel); MbufFree(MilHSVImage); + MbufFree(hsv_result); + MbufFree(hsv_denoising); } void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { @@ -214,8 +237,10 @@ int main() params["purple_a_max"] = 141; params["purple_b_min"] = 108; params["purple_b_max"] = 123; + params["lab_denoising"] = 1; params["saturation_threshold"] = 150; + params["saturation_denoising"] = 1; // Initialize combined result MIL_ID detection_result = M_NULL; From dd8bcf284ba47b85b1df7c6a986dde8a1bee58df Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Tue, 19 Nov 2024 09:40:40 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0opencv=E8=B0=83?= =?UTF-8?q?=E7=94=A8onnx=E7=9A=84=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 ++- opencv_onnx.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 opencv_onnx.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bb94a0c..542f20d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,4 +64,8 @@ target_link_libraries(ui Qt6::Widgets) add_executable(onnx Matrox/onnx_running.cpp) -target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) \ No newline at end of file +target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) + +add_executable(opencv_onnx opencv_onnx.cpp) +# 链接 OpenCV 和 Qt 库 +target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) \ No newline at end of file diff --git a/opencv_onnx.cpp b/opencv_onnx.cpp new file mode 100644 index 0000000..db32444 --- /dev/null +++ b/opencv_onnx.cpp @@ -0,0 +1,134 @@ +#include +#include +#include + +// 参数 +const float CONFIDENCE_THRESHOLD = 0.2; // 置信度阈值 +const float NMS_THRESHOLD = 0.2; // 非极大值抑制阈值 +const int INPUT_WIDTH = 640; // 模型输入宽度 +const int INPUT_HEIGHT = 640; // 模型输入高度 + +// 检测结构体 +struct Detection { + cv::Rect box; + float confidence; +}; + +// 在图像上绘制检测框 +void drawDetections(cv::Mat& image, const std::vector& detections) { + for (const auto& detection : detections) { + cv::rectangle(image, detection.box, cv::Scalar(0, 255, 0), 2); + std::string label = "Object: " + cv::format("%.2f", detection.confidence); + int baseLine; + cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); + cv::rectangle(image, cv::Point(detection.box.x, detection.box.y - labelSize.height - baseLine), + cv::Point(detection.box.x + labelSize.width, detection.box.y), cv::Scalar(0, 255, 0), cv::FILLED); + cv::putText(image, label, cv::Point(detection.box.x, detection.box.y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1); + } +} + +int main() { + // 模型路径和图片路径 + std::string modelPath = "C:\\Users\\zjc\\Desktop\\dimo_11.14.onnx"; + std::string imagePath = "C:\\Users\\zjc\\Desktop\\yolo_resized_image_640x640.png"; + + // 加载模型 + cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath); + + // 读取输入图像 + cv::Mat image = cv::imread(imagePath); + if (image.empty()) { + std::cerr << "Could not read the image: " << imagePath << std::endl; + return -1; + } + + // 预处理图像 + cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(0, 0, 0), true, false); + net.setInput(blob); + + + // 推理模型 + cv::Mat output = net.forward(); + + // 处理输出数据 + std::vector detections; + float* data = (float*)output.data; + for (int i = 0; i < 25200; ++i) { + float confidence = data[i * 6 + 4]; // 置信度 + if (confidence >= CONFIDENCE_THRESHOLD) { + // 获取检测框并映射到图像坐标 + // Remove the unnecessary multiplication + float cx = data[i * 6]; + float cy = data[i * 6 + 1]; + float w = data[i * 6 + 2]; + float h = data[i * 6 + 3]; + + // If needed, adjust for differences between input image size and model input size + // Since they are the same in your case, this step can be omitted or kept as is + cx = cx * image.cols / INPUT_WIDTH; + cy = cy * image.rows / INPUT_HEIGHT; + w = w * image.cols / INPUT_WIDTH; + h = h * image.rows / INPUT_HEIGHT; + + // Proceed with the rest of your code + int left = static_cast(cx - w / 2); + int top = static_cast(cy - h / 2); + int width = static_cast(w); + int height = static_cast(h); + + // Ensure coordinates are within image bounds + left = std::max(0, std::min(left, image.cols - 1)); + top = std::max(0, std::min(top, image.rows - 1)); + width = std::min(width, image.cols - left); + height = std::min(height, image.rows - top); + + // Add detection + detections.push_back({cv::Rect(left, top, width, height), confidence}); + + } + } + + + + // 非极大值抑制 + std::vector indices; + std::vector boxes; + std::vector scores; + for (const auto& detection : detections) { + boxes.push_back(detection.box); + + scores.push_back(detection.confidence); + } + cv::dnn::NMSBoxes(boxes, scores, CONFIDENCE_THRESHOLD, NMS_THRESHOLD, indices); + std::cout << "Number of detections after NMS: " << indices.size() << std::endl; + if (indices.empty()) { + std::cout << "No boxes passed NMS." << std::endl; + } + for (int idx : indices) { + Detection detection = detections[idx]; + std::cout << "Drawing box at: (" << detection.box.x << ", " << detection.box.y + << "), width: " << detection.box.width << ", height: " << detection.box.height << std::endl; + drawDetections(image, {detection}); + } + + std::vector finalDetections; + for (int idx : indices) { + finalDetections.push_back(detections[idx]); + } + for (int i = 0; i < 25200; ++i) { + float confidence = data[i * 6 + 4]; + if (confidence >= CONFIDENCE_THRESHOLD) { + std::cout << "Detection " << i << ": confidence=" << confidence << std::endl; + } + } + + // 绘制检测框并显示图像 + drawDetections(image, finalDetections); + cv::imshow("Detections", image); + cv::waitKey(0); + + return 0; +} +// +// Created by zjc on 24-11-19. +// From aea9ab72a072554a849b8eaa319e5b09220bae4c Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Tue, 19 Nov 2024 10:12:30 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E4=BC=98=E5=8C=96opencv=5Fonnx=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=AF=B9=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E5=9B=BE=E7=89=87resize=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opencv_onnx.cpp | 74 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/opencv_onnx.cpp b/opencv_onnx.cpp index db32444..83621ee 100644 --- a/opencv_onnx.cpp +++ b/opencv_onnx.cpp @@ -1,3 +1,6 @@ +// +// Created by zjc on 24-11-19. +// #include #include #include @@ -15,22 +18,48 @@ struct Detection { }; // 在图像上绘制检测框 -void drawDetections(cv::Mat& image, const std::vector& detections) { +void drawDetections(cv::Mat& inputImage, const std::vector& detections) { for (const auto& detection : detections) { - cv::rectangle(image, detection.box, cv::Scalar(0, 255, 0), 2); + cv::rectangle(inputImage, detection.box, cv::Scalar(0, 255, 0), 2); std::string label = "Object: " + cv::format("%.2f", detection.confidence); int baseLine; cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); - cv::rectangle(image, cv::Point(detection.box.x, detection.box.y - labelSize.height - baseLine), + cv::rectangle(inputImage, cv::Point(detection.box.x, detection.box.y - labelSize.height - baseLine), cv::Point(detection.box.x + labelSize.width, detection.box.y), cv::Scalar(0, 255, 0), cv::FILLED); - cv::putText(image, label, cv::Point(detection.box.x, detection.box.y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1); + cv::putText(inputImage, label, cv::Point(detection.box.x, detection.box.y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1); } } +cv::Mat resizeAndPad(const cv::Mat& image, int targetWidth, int targetHeight, int& padTop, int& padLeft, float& scale, const cv::Scalar& padColor) { + int originalWidth = image.cols; + int originalHeight = image.rows; + // 计算缩放比例 + scale = std::min((float)targetWidth / originalWidth, (float)targetHeight / originalHeight); + + // 缩放后的新尺寸 + int newWidth = static_cast(originalWidth * scale); + int newHeight = static_cast(originalHeight * scale); + + // 缩放图像 + cv::Mat resizedImage; + cv::resize(image, resizedImage, cv::Size(newWidth, newHeight)); + + // 计算填充值 + padTop = (targetHeight - newHeight) / 2; + int padBottom = targetHeight - newHeight - padTop; + padLeft = (targetWidth - newWidth) / 2; + int padRight = targetWidth - newWidth - padLeft; + + // 在图像周围添加填充,使用灰色 (128, 128, 128) 填充 + cv::Mat paddedImage; + cv::copyMakeBorder(resizedImage, paddedImage, padTop, padBottom, padLeft, padRight, cv::BORDER_CONSTANT, padColor); + + return paddedImage; +} int main() { // 模型路径和图片路径 std::string modelPath = "C:\\Users\\zjc\\Desktop\\dimo_11.14.onnx"; - std::string imagePath = "C:\\Users\\zjc\\Desktop\\yolo_resized_image_640x640.png"; + std::string imagePath = "C:\\Users\\zjc\\Desktop\\dimo.bmp"; // 加载模型 cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath); @@ -41,9 +70,18 @@ int main() { std::cerr << "Could not read the image: " << imagePath << std::endl; return -1; } + // 设置填充颜色为灰色 + cv::Scalar padColor(128, 128, 128); + // 预处理图像并添加填充 + int padTop, padLeft; + float scale; + cv::Mat inputImage = resizeAndPad(image, INPUT_WIDTH, INPUT_HEIGHT, padTop, padLeft, scale, padColor); + + // 显示调整和填充后的图像 + cv::imshow("Resized and Padded Image", inputImage); // 预处理图像 - cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(0, 0, 0), true, false); + cv::Mat blob = cv::dnn::blobFromImage(inputImage, 1 / 255.0, cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(0, 0, 0), true, false); net.setInput(blob); @@ -65,10 +103,10 @@ int main() { // If needed, adjust for differences between input image size and model input size // Since they are the same in your case, this step can be omitted or kept as is - cx = cx * image.cols / INPUT_WIDTH; - cy = cy * image.rows / INPUT_HEIGHT; - w = w * image.cols / INPUT_WIDTH; - h = h * image.rows / INPUT_HEIGHT; + cx = cx * inputImage.cols / INPUT_WIDTH; + cy = cy * inputImage.rows / INPUT_HEIGHT; + w = w * inputImage.cols / INPUT_WIDTH; + h = h * inputImage.rows / INPUT_HEIGHT; // Proceed with the rest of your code int left = static_cast(cx - w / 2); @@ -77,10 +115,10 @@ int main() { int height = static_cast(h); // Ensure coordinates are within image bounds - left = std::max(0, std::min(left, image.cols - 1)); - top = std::max(0, std::min(top, image.rows - 1)); - width = std::min(width, image.cols - left); - height = std::min(height, image.rows - top); + left = std::max(0, std::min(left, inputImage.cols - 1)); + top = std::max(0, std::min(top, inputImage.rows - 1)); + width = std::min(width, inputImage.cols - left); + height = std::min(height, inputImage.rows - top); // Add detection detections.push_back({cv::Rect(left, top, width, height), confidence}); @@ -108,7 +146,7 @@ int main() { Detection detection = detections[idx]; std::cout << "Drawing box at: (" << detection.box.x << ", " << detection.box.y << "), width: " << detection.box.width << ", height: " << detection.box.height << std::endl; - drawDetections(image, {detection}); + drawDetections(inputImage, {detection}); } std::vector finalDetections; @@ -124,11 +162,9 @@ int main() { // 绘制检测框并显示图像 drawDetections(image, finalDetections); - cv::imshow("Detections", image); + cv::imshow("Detections", inputImage); cv::waitKey(0); return 0; } -// -// Created by zjc on 24-11-19. -// +// \ No newline at end of file From 684848ea84869503dc4ef38ac0f1f14b025d8597 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Tue, 19 Nov 2024 10:35:05 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=84=E7=90=86?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=B5=8B=E9=87=8F=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8Agpu=E5=8A=A0=E9=80=9F=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=EF=BC=88=E4=BD=86=E8=AF=A5=E7=89=88=E6=9C=AC=E7=9A=84dnn?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E4=B8=8D=E6=94=AF=E6=8C=81gpu=E5=8A=A0?= =?UTF-8?q?=E9=80=9F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opencv_onnx.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/opencv_onnx.cpp b/opencv_onnx.cpp index 83621ee..10484d5 100644 --- a/opencv_onnx.cpp +++ b/opencv_onnx.cpp @@ -16,6 +16,28 @@ struct Detection { cv::Rect box; float confidence; }; +class Timer { +public: + Timer() : start_time(std::chrono::high_resolution_clock::now()) {} + + // 重新启动定时器 + void restart() { + start_time = std::chrono::high_resolution_clock::now(); + } + + // 获取并打印从上次启动到当前的时间差 + void printElapsedTime(const std::string& message) { + auto end_time = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = end_time - start_time; + std::cout << message << ": " << elapsed.count() << " seconds" << std::endl; + // 重新启动定时器以供下次测量 + start_time = end_time; + } + +private: + std::chrono::high_resolution_clock::time_point start_time; +}; + // 在图像上绘制检测框 void drawDetections(cv::Mat& inputImage, const std::vector& detections) { @@ -60,11 +82,15 @@ int main() { // 模型路径和图片路径 std::string modelPath = "C:\\Users\\zjc\\Desktop\\dimo_11.14.onnx"; std::string imagePath = "C:\\Users\\zjc\\Desktop\\dimo.bmp"; - + Timer timer1; // 加载模型 cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath); - + // net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // 设置为使用 CUDA 后端 + // net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // 设置为在 GPU 上运行 + timer1.printElapsedTime("Time to load the model"); // 读取输入图像 + + timer1.restart(); cv::Mat image = cv::imread(imagePath); if (image.empty()) { std::cerr << "Could not read the image: " << imagePath << std::endl; @@ -79,12 +105,13 @@ int main() { cv::Mat inputImage = resizeAndPad(image, INPUT_WIDTH, INPUT_HEIGHT, padTop, padLeft, scale, padColor); // 显示调整和填充后的图像 - cv::imshow("Resized and Padded Image", inputImage); + // cv::imshow("Resized and Padded Image", inputImage); // 预处理图像 cv::Mat blob = cv::dnn::blobFromImage(inputImage, 1 / 255.0, cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(0, 0, 0), true, false); net.setInput(blob); - + timer1.printElapsedTime("Time to preprocessing"); + timer1.restart(); // 推理模型 cv::Mat output = net.forward(); @@ -162,6 +189,8 @@ int main() { // 绘制检测框并显示图像 drawDetections(image, finalDetections); + timer1.printElapsedTime("Time to run inference"); + cv::imshow("Detections", inputImage); cv::waitKey(0); From 4cc10387b0a0037bb2d8b907230ca58d7c2e90d7 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Tue, 19 Nov 2024 16:08:54 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=94=9F=E6=88=90mask=E7=9A=84=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 +++- Matrox/mask.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 Matrox/mask.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 542f20d..8e3cb76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,4 +68,8 @@ target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) add_executable(opencv_onnx opencv_onnx.cpp) # 链接 OpenCV 和 Qt 库 -target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) \ No newline at end of file +target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) + + +add_executable(create_mask Matrox/mask.cpp) +target_link_libraries(create_mask Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) \ No newline at end of file diff --git a/Matrox/mask.cpp b/Matrox/mask.cpp new file mode 100644 index 0000000..cf0ae1b --- /dev/null +++ b/Matrox/mask.cpp @@ -0,0 +1,76 @@ +#include +#include +#include + +// 读取二值化的单通道一位图片并生成掩膜 +std::vector> generateMaskFromImage(const std::string& imagePath, int widthBlocks, int heightBlocks, int threshold = 10) { + // 读取图像 + cv::Mat image = cv::imread(imagePath, cv::IMREAD_GRAYSCALE); + + // 检查图像是否成功读取 + if (image.empty()) { + std::cerr << "无法加载图像,请检查路径是否正确: " << imagePath << std::endl; + exit(EXIT_FAILURE); + } + + // 确保图像是二值化的 + cv::threshold(image, image, 128, 255, cv::THRESH_BINARY); + + // 获取图像的宽度和高度 + int imageWidth = image.cols; + int imageHeight = image.rows; + + // 计算每个块的宽度和高度 + int blockWidth = imageWidth / widthBlocks; + int blockHeight = imageHeight / heightBlocks; + + // 创建掩膜矩阵 + std::vector> mask(heightBlocks, std::vector(widthBlocks, false)); + + // 遍历每个块并统计白色像素点的数量 + for (int i = 0; i < heightBlocks; ++i) { + for (int j = 0; j < widthBlocks; ++j) { + // 计算块的起始和结束位置 + int x_start = j * blockWidth; + int y_start = i * blockHeight; + int x_end = (j == widthBlocks - 1) ? imageWidth : (j + 1) * blockWidth; + int y_end = (i == heightBlocks - 1) ? imageHeight : (i + 1) * blockHeight; + + // 提取当前块 + cv::Mat block = image(cv::Rect(x_start, y_start, x_end - x_start, y_end - y_start)); + + // 统计块中白色像素的数量 + int whitePixelCount = cv::countNonZero(block); + + // 如果白色像素数大于阈值,将该块标记为 true + if (whitePixelCount > threshold) { + mask[i][j] = true; + } + } + } + + return mask; +} + +int main() { + // 指定图像路径 + std::string imagePath = "C:\\Users\\zjc\\Desktop\\diguandai.png"; + + // 设置分块数量和白色像素点阈值 + int widthBlocks = 24; + int heightBlocks = 24; + int threshold = 20; + + // 生成掩膜 + std::vector> mask = generateMaskFromImage(imagePath, widthBlocks, heightBlocks, threshold); + + // 打印掩膜结果 + for (int i = 0; i < heightBlocks; ++i) { + for (int j = 0; j < widthBlocks; ++j) { + std::cout << (mask[i][j] ? "1 " : "0 "); + } + std::cout << std::endl; + } + + return 0; +} From a2f24318edd9086b563d5174f54e39f9194c42df Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Wed, 20 Nov 2024 15:56:19 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 74 ++++---- Matrox/template_matching.cpp | 222 ------------------------ Matrox/template_matching.h | 8 - Matrox/utils.cpp | 9 - src/CMakeLists.txt | 12 ++ {Matrox => src/Matrox}/README.md | 12 ++ {Matrox => src/Matrox}/color_range.cpp | 116 +++---------- {Matrox => src/Matrox}/color_range.h | 5 +- {Matrox => src/Matrox}/mask.cpp | 0 {Matrox => src/Matrox}/onnx_running.cpp | 17 +- {Matrox => src/Matrox}/onnx_running.h | 0 src/Matrox/template_matching.cpp | 219 +++++++++++++++++++++++ src/Matrox/template_matching.h | 10 ++ {Matrox => src/Matrox}/ui.cpp | 0 {Matrox => src/Matrox}/ui.h | 0 src/Matrox/utils.cpp | 63 +++++++ {Matrox => src/Matrox}/utils.h | 14 ++ tests/CMakeLists.txt | 16 ++ tests/test_color_range.cpp | 91 ++++++++++ tests/test_template_matching.cpp | 64 +++++++ 20 files changed, 576 insertions(+), 376 deletions(-) delete mode 100644 Matrox/template_matching.cpp delete mode 100644 Matrox/template_matching.h delete mode 100644 Matrox/utils.cpp create mode 100644 src/CMakeLists.txt rename {Matrox => src/Matrox}/README.md (83%) rename {Matrox => src/Matrox}/color_range.cpp (70%) rename {Matrox => src/Matrox}/color_range.h (84%) rename {Matrox => src/Matrox}/mask.cpp (100%) rename {Matrox => src/Matrox}/onnx_running.cpp (82%) rename {Matrox => src/Matrox}/onnx_running.h (100%) create mode 100644 src/Matrox/template_matching.cpp create mode 100644 src/Matrox/template_matching.h rename {Matrox => src/Matrox}/ui.cpp (100%) rename {Matrox => src/Matrox}/ui.h (100%) create mode 100644 src/Matrox/utils.cpp rename {Matrox => src/Matrox}/utils.h (60%) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/test_color_range.cpp create mode 100644 tests/test_template_matching.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e3cb76..df8239d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,39 +37,45 @@ include_directories(E:/QTexamble/matrox/Include) link_directories(E:/QTexamble/matrox/LIB) file(GLOB MIL_LIBS E:/QTexamble/matrox/LIB/*.lib) -# 添加可执行文件 cotton_color -add_executable(cotton_color cotton_color.cpp) -# 链接 OpenCV 和 Qt 库 -target_link_libraries(cotton_color Qt6::Widgets ${OpenCV_LIBS} comdlg32) -# 添加可执行文件 cotton_color -add_executable(cotton_range Matrox/color_range.cpp - Matrox/color_range.h Matrox/utils.h Matrox/utils.cpp) -# 链接 OpenCV 和 Qt 库 -target_link_libraries(cotton_range Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) +# 添加子目录 +add_subdirectory(src) +add_subdirectory(tests) -# 添加可执行文件 cotton_color2 -add_executable(cotton_color2 cotton_color2.cpp) -# 链接 OpenCV 和 Qt 库 -target_link_libraries(cotton_color2 Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) - -add_executable(color_matching Matrox/template_matching.cpp - Matrox/utils.cpp - Matrox/utils.h) -target_link_libraries(color_matching Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) - - -add_executable(ui Matrox/ui.cpp) -target_link_libraries(ui Qt6::Widgets) - - -add_executable(onnx Matrox/onnx_running.cpp) -target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) - -add_executable(opencv_onnx opencv_onnx.cpp) -# 链接 OpenCV 和 Qt 库 -target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) - - -add_executable(create_mask Matrox/mask.cpp) -target_link_libraries(create_mask Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) \ No newline at end of file +## 添加可执行文件 cotton_color +#add_executable(cotton_color cotton_color.cpp) +## 链接 OpenCV 和 Qt 库 +#target_link_libraries(cotton_color Qt6::Widgets ${OpenCV_LIBS} comdlg32) +# +## 添加可执行文件 cotton_color +#add_executable(cotton_range src/Matrox/color_range.cpp +# src/Matrox/color_range.h src/Matrox/utils.h src/Matrox/utils.cpp) +## 链接 OpenCV 和 Qt 库 +#target_link_libraries(cotton_range Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) +# +## 添加可执行文件 cotton_color2 +#add_executable(cotton_color2 cotton_color2.cpp) +## 链接 OpenCV 和 Qt 库 +#target_link_libraries(cotton_color2 Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) +# +#add_executable(template_matching src/Matrox/template_matching.cpp +# src/Matrox/color_range.cpp src/Matrox/color_range.h +# src/Matrox/utils.cpp src/Matrox/utils.h) +#target_link_libraries(template_matching Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) +# +# +#add_executable(ui src/Matrox/ui.cpp) +#target_link_libraries(ui Qt6::Widgets) +# +# +#add_executable(onnx src/Matrox/onnx_running.cpp) +#target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) +# +#add_executable(opencv_onnx opencv_onnx.cpp) +## 链接 OpenCV 和 Qt 库 +#target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) +# +# +#add_executable(create_mask src/Matrox/mask.cpp) +#target_link_libraries(create_mask Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) +#add_executable(test_color_range tests/test_color_range.cpp) diff --git a/Matrox/template_matching.cpp b/Matrox/template_matching.cpp deleted file mode 100644 index ededb56..0000000 --- a/Matrox/template_matching.cpp +++ /dev/null @@ -1,222 +0,0 @@ - - -#include -//#include // 添加此行 -#include - -/* Example functions declarations. */ -void SingleModelExample(MIL_ID MilSystem, MIL_ID MilDisplay); - -/*****************************************************************************/ -/* Main. -******************************************************************************/ -int MosMain(void) -{ - MIL_ID MilApplication, /* Application identifier. */ - MilSystem, /* System Identifier. */ - MilDisplay; /* Display identifier. */ - - /* Allocate defaults. */ - MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); - - /* Run single model example. */ - SingleModelExample(MilSystem, MilDisplay); - - /* Free defaults. */ - MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); - - return 0; -} - -/*****************************************************************************/ -/* Single model example. */ - -/* Source MIL image file specifications. */ -#define SINGLE_MODEL_IMAGE MIL_TEXT("C:\\Users\\zjc\\Desktop\\diguandai2.png") // 替换为您的模板RGB图像文件路径 - -/* Target MIL image file specifications. */ -#define SINGLE_MODEL_TARGET_IMAGE MIL_TEXT ("C:\\Users\\zjc\\Desktop\\diguandai.png") // 替换为您的待检测RGB图像文件路径 - -/* Search speed: M_VERY_HIGH for faster search, M_MEDIUM for precision and robustness. */ -#define SINGLE_MODEL_SEARCH_SPEED M_LOW - -/* Model specifications. */ -#define MODEL_OFFSETX 3200L // 根据您的模板图像调整 -#define MODEL_OFFSETY 550L // 根据您的模板图像调整 -#define MODEL_SIZEX 200L // 根据您的模板图像调整 -#define MODEL_SIZEY 200L // 根据您的模板图像调整 -#define MODEL_MAX_OCCURRENCES 6L - -void SingleModelExample(MIL_ID MilSystem, MIL_ID MilDisplay) -{ - clock_t start_time = clock(); - - MIL_ID MilColorImage, /* 彩色图像缓冲区标识符。*/ - MilImage, /* 灰度图像缓冲区标识符。*/ - GraphicList; /* 图形列表标识符。*/ - MIL_ID MilSearchContext, /* 搜索上下文。*/ - MilResult; /* 结果标识符。*/ - MIL_DOUBLE ModelDrawColor = M_COLOR_RED; /* 模板绘制颜色。*/ - MIL_INT Model[MODEL_MAX_OCCURRENCES], /* 模板索引。*/ - NumResults = 0L; /* 找到的结果数量。*/ - MIL_DOUBLE Score[MODEL_MAX_OCCURRENCES], /* 模板匹配得分。*/ - XPosition[MODEL_MAX_OCCURRENCES], /* 模板X位置。*/ - YPosition[MODEL_MAX_OCCURRENCES], /* 模板Y位置。*/ - Angle[MODEL_MAX_OCCURRENCES], /* 模板角度。*/ - Scale[MODEL_MAX_OCCURRENCES], /* 模板缩放。*/ - Time = 0.0; /* 计时变量。*/ - int i; /* 循环变量。*/ - - - /* 加载RGB模板图像。 */ - MbufRestore(SINGLE_MODEL_IMAGE, MilSystem, &MilColorImage); - - /* 获取图像尺寸。 */ - MIL_INT Width = MbufInquire(MilColorImage, M_SIZE_X, M_NULL); - MIL_INT Height = MbufInquire(MilColorImage, M_SIZE_Y, M_NULL); - - /* 分配灰度图像缓冲区。 */ - MbufAlloc2d(MilSystem, Width, Height, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &MilImage); - - /* 将RGB图像转换为灰度图像。 */ - MimConvert(MilColorImage, MilImage, M_RGB_TO_L); - - /* 选择灰度图像进行显示。 */ - MdispSelect(MilDisplay, MilImage); - - /* 释放彩色图像缓冲区。 */ - MbufFree(MilColorImage); - - /* Allocate a graphic list to hold the subpixel annotations to draw. */ - MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); - - /* Associate the graphic list to the display for annotations. */ - MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); - - /* Allocate a Geometric Model Finder context. */ - MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); - - /* Allocate a result buffer. */ - MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); - - /* Define the model. */ - MmodDefine(MilSearchContext, M_IMAGE, MilImage, - MODEL_OFFSETX, MODEL_OFFSETY, MODEL_SIZEX, MODEL_SIZEY); - - /* Set the search speed. */ - MmodControl(MilSearchContext, M_CONTEXT, M_SPEED, SINGLE_MODEL_SEARCH_SPEED); - - /* Preprocess the search context. */ - MmodPreprocess(MilSearchContext, M_DEFAULT); - - /* Draw box and position it in the source image to show the model. */ - MgraColor(M_DEFAULT, ModelDrawColor); - MmodDraw(M_DEFAULT, MilSearchContext, GraphicList, - M_DRAW_BOX + M_DRAW_POSITION, 0, M_ORIGINAL); - clock_t end_time = clock(); - std::cout << "The run time is: " << (double)(end_time - start_time) / CLOCKS_PER_SEC << "s"; - /* Pause to show the model. */ - MosPrintf(MIL_TEXT("\nGEOMETRIC MODEL FINDER:\n")); - MosPrintf(MIL_TEXT("-----------------------\n\n")); - MosPrintf(MIL_TEXT("A model context was defined with ")); - MosPrintf(MIL_TEXT("the model in the displayed image.\n")); - MosPrintf(MIL_TEXT("Press to continue.\n\n")); - MosGetch(); - - /* Clear annotations. */ - MgraClear(M_DEFAULT, GraphicList); - - /* 加载RGB待检测图像。 */ - MbufRestore(SINGLE_MODEL_TARGET_IMAGE, MilSystem, &MilColorImage); - - /* 确保待检测图像的尺寸与模板图像一致。 */ - MIL_INT TargetWidth = MbufInquire(MilColorImage, M_SIZE_X, M_NULL); - MIL_INT TargetHeight = MbufInquire(MilColorImage, M_SIZE_Y, M_NULL); - - /* 如果尺寸不同,需要重新分配灰度图像缓冲区。 */ - if (TargetWidth != Width || TargetHeight != Height) - { - /* 释放之前的灰度图像缓冲区。 */ - MbufFree(MilImage); - - /* 分配新的灰度图像缓冲区。 */ - MbufAlloc2d(MilSystem, TargetWidth, TargetHeight, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &MilImage); - - /* 更新宽度和高度。 */ - Width = TargetWidth; - Height = TargetHeight; - } - - /* 将RGB待检测图像转换为灰度图像。 */ - MimConvert(MilColorImage, MilImage, M_RGB_TO_L); - - /* 释放彩色图像缓冲区。 */ - MbufFree(MilColorImage); - - /* 显示灰度待检测图像。 */ - MdispSelect(MilDisplay, MilImage); - - /* Dummy first call for bench measure purpose only (bench stabilization, - cache effect, etc...). This first call is NOT required by the application. */ - MmodFind(MilSearchContext, MilImage, MilResult); - - /* Reset the timer. */ - MappTimer(M_DEFAULT, M_TIMER_RESET + M_SYNCHRONOUS, M_NULL); - - /* Find the model. */ - MmodFind(MilSearchContext, MilImage, MilResult); - - /* Read the find time. */ - MappTimer(M_DEFAULT, M_TIMER_READ + M_SYNCHRONOUS, &Time); - - /* Get the number of models found. */ - MmodGetResult(MilResult, M_DEFAULT, M_NUMBER + M_TYPE_MIL_INT, &NumResults); - - /* If a model was found above the acceptance threshold. */ - if ((NumResults >= 1) && (NumResults <= MODEL_MAX_OCCURRENCES)) - { - /* Get the results of the single model. */ - MmodGetResult(MilResult, M_DEFAULT, M_INDEX + M_TYPE_MIL_INT, Model); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition); - MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle); - MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale); - MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score); - - /* Print the results for each model found. */ - MosPrintf(MIL_TEXT("The model was found in the target image:\n\n")); - MosPrintf(MIL_TEXT("Result Model X Position Y Position ") - MIL_TEXT("Angle Scale Score\n\n")); - for (i = 0; i < NumResults; i++) - { - MosPrintf(MIL_TEXT("%-9d%-8d%-13.2f%-13.2f%-8.2f%-8.2f%-5.2f%%\n"), - i, (int)Model[i], XPosition[i], YPosition[i], - Angle[i], Scale[i], Score[i]); - } - MosPrintf(MIL_TEXT("\nThe search time is %.1f ms\n\n"), Time * 1000.0); - - /* Draw edges, position and box over the occurrences that were found. */ - for (i = 0; i < NumResults; i++) - { - MgraColor(M_DEFAULT, ModelDrawColor); - MmodDraw(M_DEFAULT, MilResult, GraphicList, - M_DRAW_EDGES + M_DRAW_BOX + M_DRAW_POSITION, i, M_DEFAULT); - } - } - else - { - MosPrintf(MIL_TEXT("The model was not found or the number of models ") - MIL_TEXT("found is greater than\n")); - MosPrintf(MIL_TEXT("the specified maximum number of occurrence !\n\n")); - } - - /* Wait for a key to be pressed. */ - MosPrintf(MIL_TEXT("Press to continue.\n\n")); - MosGetch(); - - /* Free MIL objects. */ - MgraFree(GraphicList); - MbufFree(MilImage); - MmodFree(MilSearchContext); - MmodFree(MilResult); -} \ No newline at end of file diff --git a/Matrox/template_matching.h b/Matrox/template_matching.h deleted file mode 100644 index bcbca12..0000000 --- a/Matrox/template_matching.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by zjc on 24-11-12. -// - -#ifndef TEMPLATE_MATCHING_H -#define TEMPLATE_MATCHING_H - -#endif //TEMPLATE_MATCHING_H diff --git a/Matrox/utils.cpp b/Matrox/utils.cpp deleted file mode 100644 index 6db5430..0000000 --- a/Matrox/utils.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by zjc on 24-11-18. -// - -#include "utils.h" - - - -// 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8859a18 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,12 @@ +# 定义 Matrox 模块的库 +add_library(Matrox + Matrox/color_range.cpp + Matrox/utils.cpp + Matrox/template_matching.cpp +) + +# 头文件路径 +target_include_directories(Matrox PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# 链接依赖库 +target_link_libraries(Matrox PUBLIC Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) diff --git a/Matrox/README.md b/src/Matrox/README.md similarity index 83% rename from Matrox/README.md rename to src/Matrox/README.md index d8335a5..36a4653 100644 --- a/Matrox/README.md +++ b/src/Matrox/README.md @@ -72,3 +72,15 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma | lab_denoising = 1 | | | ![diguandai](./README.assets/diguandai.png) | | lab_denoising = 2 | | | | + +这些是经过实验后的推荐参数: + +| | L_min | L_max | a_min | a_max | b_min | b_max | +| ------ | ----- | ----- | ----- | ----- | ----- | ----- | +| green | 27 | 49 | -27 | -8 | 2 | 12 | +| blue | 18 | 26 | 2 | 17 | -33 | -23 | +| orange | 65 | 75 | 7 | 14 | 32 | 46 | +| black | 0 | 8 | -1 | 5 | -2 | 6 | +| red | 28 | 38 | 15 | 25 | -95 | 26 | +| purple | 67 | 77 | 3 | 13 | -20 | -5 | + diff --git a/Matrox/color_range.cpp b/src/Matrox/color_range.cpp similarity index 70% rename from Matrox/color_range.cpp rename to src/Matrox/color_range.cpp index 3295e8b..10674cd 100644 --- a/Matrox/color_range.cpp +++ b/src/Matrox/color_range.cpp @@ -4,15 +4,10 @@ #include #include "utils.h" -#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton_image\\174.bmp") -#define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\diguandai.png") - - -// Global variables -MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; // Optimized LabProcess function -void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params) +void lab_process_raw(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params, + const std::vector& color_vector) { MIL_ID MilLabImage = M_NULL, MilLChannel = M_NULL, MilAChannel = M_NULL, MilBChannel = M_NULL; MIL_ID lab_result=M_NULL; @@ -56,11 +51,11 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilBinaryB); MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &MilResultLab); MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + M_UNSIGNED, M_IMAGE + M_PROC, &lab_result); - const std::vector colors = {"green", "blue", "orange", "black", "red", "purple"}; + // Iterate over colors // 遍历颜色 - for (const auto& color : colors) { + for (const auto& color : color_vector) { // 构建参数键 std::string L_min_key = color + "_L_min"; std::string L_max_key = color + "_L_max"; @@ -76,6 +71,18 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma int a_max = params.at(a_max_key); int b_min = params.at(b_min_key); int b_max = params.at(b_max_key); + std::vector lab_min_ps = {L_min, a_min, b_min}; + std::vector lab_max_ps = {L_max, a_max, b_max}; + + std::vector lab_min_cv = psLabToOpenCVLab(lab_min_ps); + std::vector lab_max_cv = psLabToOpenCVLab(lab_max_ps); + + L_min = lab_min_cv[0]; + L_max = lab_max_cv[0]; + a_min = lab_min_cv[1]; + a_max = lab_max_cv[1]; + b_min = lab_min_cv[2]; + b_max = lab_max_cv[2]; // 对每个通道进行二值化 MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, L_min, L_max); @@ -107,6 +114,13 @@ void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::ma MbufFree(lab_result); } + +void lab_process(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params) { + const std::vector colors = {"green", "blue", "orange", "black", "red", "purple"}; + lab_process_raw(inputImage, outputImageLab, params, colors); +} + + void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::map& params) { MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL; @@ -142,13 +156,13 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma // 分配输出图像缓冲区 MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &hsv_result); MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &hsv_denoising); MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), - MbufInquire(inputImage, M_SIZE_Y, M_NULL), 8 + M_UNSIGNED, + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &outputImageHSV); // 对 S 通道进行阈值分割 @@ -167,6 +181,7 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma MbufFree(hsv_denoising); } + void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { MIL_ID output_hsv=M_NULL, output_lab=M_NULL; @@ -184,81 +199,4 @@ void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::m MbufFree(output_hsv); } -int main() -{ - // Initialize MIL application - MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, - M_NULL); - // Load input image - MIL_ID MilImage = M_NULL; - MbufRestore(IMAGE_PATH, MilSystem, &MilImage); - - // Define color ranges - std::map params; - params["green_L_min"] = 68; - params["green_L_max"] = 125; - params["green_a_min"] = 101; - params["green_a_max"] = 120; - params["green_b_min"] = 130; - params["green_b_max"] = 140; - - params["blue_L_min"] = 45; - params["blue_L_max"] = 66; - params["blue_a_min"] = 130; - params["blue_a_max"] = 145; - params["blue_b_min"] = 95; - params["blue_b_max"] = 105; - - params["orange_L_min"] = 166; - params["orange_L_max"] = 191; - params["orange_a_min"] = 135; - params["orange_a_max"] = 142; - params["orange_b_min"] = 160; - params["orange_b_max"] = 174; - - params["black_L_min"] = 0; - params["black_L_max"] = 21; - params["black_a_min"] = 127; - params["black_a_max"] = 133; - params["black_b_min"] = 126; - params["black_b_max"] = 134; - - params["red_L_min"] = 71; - params["red_L_max"] = 97; - params["red_a_min"] = 143; - params["red_a_max"] = 153; - params["red_b_min"] = 33; - params["red_b_max"] = 154; - - params["purple_L_min"] = 171; - params["purple_L_max"] = 197; - params["purple_a_min"] = 131; - params["purple_a_max"] = 141; - params["purple_b_min"] = 108; - params["purple_b_max"] = 123; - params["lab_denoising"] = 1; - - params["saturation_threshold"] = 150; - params["saturation_denoising"] = 1; - - // Initialize combined result - MIL_ID detection_result = M_NULL; - - // Measure execution time - measure_execution_time([&]() { - high_sat_detect(MilImage, detection_result, params); - }); - MbufSave(SAVE_PATH, detection_result); - // Display result - - std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; - getchar(); - - // Free resources - MbufFree(detection_result); - MbufFree(MilImage); - MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); - - return 0; -} diff --git a/Matrox/color_range.h b/src/Matrox/color_range.h similarity index 84% rename from Matrox/color_range.h rename to src/Matrox/color_range.h index 0c4cfcc..d959163 100644 --- a/Matrox/color_range.h +++ b/src/Matrox/color_range.h @@ -60,7 +60,10 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma // params["purple_b_max"] = 123; // +void lab_process_raw(const MIL_ID& inputImage, MIL_ID& outputImageLab, const std::map& params, + const std::vector& color_vector); +// 新增了可自定义的色彩矩阵 - +void high_sat_detect(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params); #endif //COLOR_RANGE_H diff --git a/Matrox/mask.cpp b/src/Matrox/mask.cpp similarity index 100% rename from Matrox/mask.cpp rename to src/Matrox/mask.cpp diff --git a/Matrox/onnx_running.cpp b/src/Matrox/onnx_running.cpp similarity index 82% rename from Matrox/onnx_running.cpp rename to src/Matrox/onnx_running.cpp index c5e6892..bbcee7a 100644 --- a/Matrox/onnx_running.cpp +++ b/src/Matrox/onnx_running.cpp @@ -13,9 +13,9 @@ #include // Path definitions. -#define EXAMPLE_ONNX_MODEL_PATH MIL_TEXT("C:\\Users\\zjc\\source\\repos\\cotton_color\\Matrox\\models\\2024_11_12_imgsz640_batch1.onnx") -#define TARGET_IMAGE_DIR_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\dimo2.mim") -#define IMAGE_FILE MIL_TEXT("C:\\Users\\zjc\\Desktop\\dimo2.bmp") +#define EXAMPLE_ONNX_MODEL_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\WeChat Files\\wxid_ipl8u0ctajtn22\\FileStorage\\File\\2024-11\\2024_11_12_imgsz640_batch1(1).onnx") +#define TARGET_IMAGE_DIR_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\dimo4.mim") + int MosMain(void) { @@ -31,14 +31,6 @@ int MosMain(void) MsysAlloc(M_DEFAULT, M_SYSTEM_DEFAULT, M_DEFAULT, M_DEFAULT, &MilSystem); MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay); - MIL_UNIQUE_BUF_ID dimo2; - MbufImport(IMAGE_FILE, M_DEFAULT, M_RESTORE+M_NO_GRAB+M_NO_COMPRESS, MilSystem, &dimo2); - //MIL_UNIQUE_BUF_ID MimArithdestination = MbufClone(dimo2, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_UNIQUE_ID); - MIL_UNIQUE_BUF_ID MimArithDestination = MbufAllocColor(MilSystem, 3, 640, 640, 32 + M_FLOAT, M_IMAGE + M_PROC, M_UNIQUE_ID); - // Post-Alloc Block for MimArith's destination - MbufClear(MimArithDestination, M_COLOR_BLACK); - - MimArith(dimo2, 255.0, MimArithDestination, M_DIV_CONST); // Load the image into memory. if (MbufRestore(TARGET_IMAGE_DIR_PATH, MilSystem, &MilImage) != M_NULL) @@ -51,7 +43,6 @@ int MosMain(void) return 1; // Exit if the image loading failed } - MdispSelect(MilDisplay, MimArithDestination); // MbufInquire(MilImage, , NULL); @@ -70,7 +61,7 @@ int MosMain(void) // Perform object detection on the image using MclassPredict. - MclassPredict(DetectCtx, MimArithDestination, DetectRes, M_DEFAULT); + MclassPredict(DetectCtx, MilImage, DetectRes, M_DEFAULT); MosPrintf(MIL_TEXT("Object detection completed.\n")); diff --git a/Matrox/onnx_running.h b/src/Matrox/onnx_running.h similarity index 100% rename from Matrox/onnx_running.h rename to src/Matrox/onnx_running.h diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp new file mode 100644 index 0000000..850c94c --- /dev/null +++ b/src/Matrox/template_matching.cpp @@ -0,0 +1,219 @@ +#include +#include +#include +#include "color_range.h" +#include "utils.h" + + +void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params) { + // 异色检测, 检测出不同与棉花颜色的物体作为模板匹配的对象 + const std::vector colors = {"cotton", "background"}; + std::map param_temp = params; + param_temp["lab_denoising"] = param_temp["cotton_denoising"]; + param_temp["saturation_threshold"] = param_temp["cotton_saturation_threshold"]; + param_temp["saturation_denoising"] = param_temp["cotton_saturation_denoising"]; + lab_process_raw(inputImage, outputImageSuspect, param_temp, colors); + MimArith(outputImageSuspect, M_NULL, outputImageSuspect, M_NOT); +} + +/* Number of models. */ +#define NUMBER_OF_MODELS 3L +#define MODELS_MAX_OCCURRENCES 16L + +/* Model 1 specifications. */ +#define MODEL0_OFFSETX 34L +#define MODEL0_OFFSETY 93L +#define MODEL0_SIZEX 214L +#define MODEL0_SIZEY 76L +#define MODEL0_DRAW_COLOR M_COLOR_RED + +/* Model 2 specifications. */ +#define MODEL1_OFFSETX 73L +#define MODEL1_OFFSETY 232L +#define MODEL1_SIZEX 150L +#define MODEL1_SIZEY 154L +#define MODEL1_REFERENCEX 23L +#define MODEL1_REFERENCEY 127L +#define MODEL1_DRAW_COLOR M_COLOR_GREEN + +/* Model 3 specifications. */ +#define MODEL2_OFFSETX 308L +#define MODEL2_OFFSETY 39L +#define MODEL2_SIZEX 175L +#define MODEL2_SIZEY 357L +#define MODEL2_REFERENCEX 62L +#define MODEL2_REFERENCEY 150L +#define MODEL2_DRAW_COLOR M_COLOR_BLUE +/* Search speed: M_VERY_HIGH for faster search, M_MEDIUM for precision and robustness.*/ +#define MULTI_MODELS_SEARCH_SPEED M_VERY_HIGH + +/* Models array specifications. */ +#define MODELS_ARRAY_SIZE 3L +#define MODELS_OFFSETX {MODEL0_OFFSETX, MODEL1_OFFSETX, MODEL2_OFFSETX} +#define MODELS_OFFSETY {MODEL0_OFFSETY, MODEL1_OFFSETY, MODEL2_OFFSETY} +#define MODELS_SIZEX {MODEL0_SIZEX, MODEL1_SIZEX, MODEL2_SIZEX} +#define MODELS_SIZEY {MODEL0_SIZEY, MODEL1_SIZEY, MODEL2_SIZEY} +#define MODELS_DRAW_COLOR {MODEL0_DRAW_COLOR, MODEL1_DRAW_COLOR, MODEL2_DRAW_COLOR} + + +void template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { + MIL_ID MilImage, /* Image buffer identifier. */ + GraphicList; /* Graphic list identifier. */ + MIL_ID MilSearchContext, /* Search context */ + MilResult; /* Result identifier. */ + MIL_INT Models[MODELS_MAX_OCCURRENCES], /* Model indices. */ + ModelsOffsetX[MODELS_ARRAY_SIZE] = MODELS_OFFSETX,/* Model X offsets array. */ + ModelsOffsetY[MODELS_ARRAY_SIZE] = MODELS_OFFSETY,/* Model Y offsets array. */ + ModelsSizeX[MODELS_ARRAY_SIZE] = MODELS_SIZEX, /* Model X sizes array. */ + ModelsSizeY[MODELS_ARRAY_SIZE] = MODELS_SIZEY; /* Model Y sizes array. */ + MIL_DOUBLE ModelsDrawColor[MODELS_ARRAY_SIZE]=MODELS_DRAW_COLOR; /* Model drawing colors.*/ + MIL_INT NumResults = 0L; /* Number of results found. */ + MIL_DOUBLE Score[MODELS_MAX_OCCURRENCES], /* Model correlation scores.*/ + XPosition[MODELS_MAX_OCCURRENCES], /* Model X positions. */ + YPosition[MODELS_MAX_OCCURRENCES], /* Model Y positions. */ + Angle[MODELS_MAX_OCCURRENCES], /* Model occurrence angles. */ + Scale[MODELS_MAX_OCCURRENCES], /* Model occurrence scales. */ + Time = 0.0; /* Time variable. */ + int i; /* Loop variable */ + MIL_ID inputImageSuspect = convert_to_uint8(inputImage); + /* Restore the model image and display it. */ + MdispSelect(MilDisplay, inputImageSuspect); + + // 用于显示的部分 + /* Allocate a graphic list to hold the subpixel annotations to draw. */ + MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); + /* Associate the graphic list to the display for annotations. */ + MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); + + + /* Allocate a geometric model finder. */ + MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); + // 取出一个buffer用来存储结果 + /* Allocate a result buffer. */ + MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); + + /* Define the models. */ + for (i=0; i1) + /* Change the reference point of the second model. */ + MmodControl(MilSearchContext, 1, M_REFERENCE_X, MODEL1_REFERENCEX); + MmodControl(MilSearchContext, 1, M_REFERENCE_Y, MODEL1_REFERENCEY); + + #if (NUMBER_OF_MODELS>2) + /* Change the reference point of the third model. */ + MmodControl(MilSearchContext, 2, M_REFERENCE_X, MODEL2_REFERENCEX); + MmodControl(MilSearchContext, 2, M_REFERENCE_Y, MODEL2_REFERENCEY); + #endif + #endif + + /* Preprocess the search context. */ + MmodPreprocess(MilSearchContext, M_DEFAULT); + + /* Draw boxes and positions in the source image to identify the models. */ + for (i=0; i to continue.\n\n")); + MosGetch(); + + /* Clear annotations. */ + MgraClear(M_DEFAULT, GraphicList); + + + /* Dummy first call for bench measure purpose only (bench stabilization, + cache effect, etc...). This first call is NOT required by the application. */ + // MmodFind(MilSearchContext, inputImageSuspect, MilResult); + /* Reset the timer. */ + MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL); + + /* Find the models. */ + MmodFind(MilSearchContext, inputImageSuspect, MilResult); + + /* Read the find time. */ + MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time); + + /* Get the number of models found. */ + MmodGetResult(MilResult, M_DEFAULT, M_NUMBER+M_TYPE_MIL_INT, &NumResults); + + /* If the models were found above the acceptance threshold. */ + if( (NumResults >= 1) && (NumResults <= MODELS_MAX_OCCURRENCES) ) + { + /* Get the results for each model. */ + MmodGetResult(MilResult, M_DEFAULT, M_INDEX+M_TYPE_MIL_INT, Models); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition); + MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle); + MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale); + MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score); + + /* Print information about the target image. */ + MosPrintf(MIL_TEXT("The models were found in the target ")); + MosPrintf(MIL_TEXT("image although there is:\n ")); + MosPrintf(MIL_TEXT("Full rotation\n Small scale change\n ")); + MosPrintf(MIL_TEXT("Contrast variation\n Specular reflection\n ")); + MosPrintf(MIL_TEXT("Occlusion\n Multiple models\n")); + MosPrintf(MIL_TEXT(" Multiple occurrences\n\n")); + + /* Print the results for the found models. */ + MosPrintf(MIL_TEXT("Result Model X Position Y Position ") + MIL_TEXT("Angle Scale Score\n\n")); + for (i=0; i to end.\n\n")); + MosGetch(); + + /* Free MIL objects. */ + MgraFree(GraphicList); + // MbufFree(MilImage); + MmodFree(MilSearchContext); + MmodFree(MilResult); +} diff --git a/src/Matrox/template_matching.h b/src/Matrox/template_matching.h new file mode 100644 index 0000000..0e0ec60 --- /dev/null +++ b/src/Matrox/template_matching.h @@ -0,0 +1,10 @@ +// +// Created by zjc on 24-11-12. +// + +#ifndef TEMPLATE_MATCHING_H +#define TEMPLATE_MATCHING_H +void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params); + +void template_matching(const MIL_ID& inputImageSuspect, MIL_ID& outputImage, const std::map& params); +#endif //TEMPLATE_MATCHING_H diff --git a/Matrox/ui.cpp b/src/Matrox/ui.cpp similarity index 100% rename from Matrox/ui.cpp rename to src/Matrox/ui.cpp diff --git a/Matrox/ui.h b/src/Matrox/ui.h similarity index 100% rename from Matrox/ui.h rename to src/Matrox/ui.h diff --git a/src/Matrox/utils.cpp b/src/Matrox/utils.cpp new file mode 100644 index 0000000..951f0e9 --- /dev/null +++ b/src/Matrox/utils.cpp @@ -0,0 +1,63 @@ +// +// Created by zjc on 24-11-18. +// + +#include "utils.h" + + +#include +#include +#include + +using namespace std; + +/** + * Convert Lab values from Photoshop range to OpenCV range. + * + * @param lab_ps A vector of Lab values in Photoshop range [L (0-100), a (-128 to 127), b (-128 to 127)]. + * @return A vector of Lab values in OpenCV range [L (0-255), a (0-255), b (0-255)]. + */ +vector psLabToOpenCVLab(const vector& lab_ps) { + int l_ps = lab_ps[0]; + int a_ps = lab_ps[1]; + int b_ps = lab_ps[2]; + + // Conversion formulas + int l_cv = round((l_ps / 100.0) * 255.0); // Scale L from 0-100 to 0-255 + int a_cv = round(((a_ps + 128.0) / 255.0) * 255.0); // Shift and scale a + int b_cv = round(((b_ps + 128.0) / 255.0) * 255.0); // Shift and scale b + + return {l_cv, a_cv, b_cv}; +} + +/** + * Convert Lab values from OpenCV range to Photoshop range. + * + * @param lab_cv A vector of Lab values in OpenCV range [L (0-255), a (0-255), b (0-255)]. + * @return A vector of Lab values in Photoshop range [L (0-100), a (-128 to 127), b (-128 to 127)]. + */ +vector opencvLabToPsLab(const vector& lab_cv) { + int l_cv = lab_cv[0]; + int a_cv = lab_cv[1]; + int b_cv = lab_cv[2]; + + // Conversion formulas + int l_ps = round((l_cv / 255.0) * 100.0); // Scale L from 0-255 to 0-100 + int a_ps = round((a_cv / 255.0) * 255.0 - 128.0); // Scale and shift a + int b_ps = round((b_cv / 255.0) * 255.0 - 128.0); // Scale and shift b + + return {l_ps, a_ps, b_ps}; +} + +MIL_ID convert_to_uint8(MIL_ID input_img) { + MIL_ID output_img; + MIL_ID MilSystem = MbufInquire(input_img, M_OWNER_SYSTEM, M_NULL); + MIL_INT size_x = MbufInquire(input_img, M_SIZE_X, M_NULL); + MIL_INT size_y = MbufInquire(input_img, M_SIZE_Y, M_NULL); + MbufAlloc2d(MilSystem, size_x, size_y, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &output_img); + MimArith(output_img, input_img, output_img, M_ADD); + MimArith(output_img, 255.0, output_img, M_MULT_CONST); + return output_img; +} + +// 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/Matrox/utils.h b/src/Matrox/utils.h similarity index 60% rename from Matrox/utils.h rename to src/Matrox/utils.h index 154a12a..b194df1 100644 --- a/Matrox/utils.h +++ b/src/Matrox/utils.h @@ -7,6 +7,14 @@ #include #include +#include +#include + +// 声明全局变量(注意:这里只是声明,不是定义) +extern __int64 MilApplication; +extern __int64 MilSystem; +extern __int64 MilDisplay; + template // Time measurement function void measure_execution_time(Func func) { @@ -18,4 +26,10 @@ void measure_execution_time(Func func) { std::cout << "Function execution time: " << duration.count() << " milliseconds" << std::endl; } +std::vector psLabToOpenCVLab(const std::vector& lab_ps); + +std::vector opencvLabToPsLab(const std::vector& lab_cv); + +MIL_ID convert_to_uint8(MIL_ID input_img); + #endif //UTILS_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..981cb19 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,16 @@ + +# 测试用例 1: template_color_range +add_executable(test_color_range + ${CMAKE_CURRENT_SOURCE_DIR}/test_color_range.cpp +) + +# 链接 Matrox 模块和依赖库 +target_link_libraries(test_color_range Matrox ${OpenCV_LIBS} ${MIL_LIBS}) + +# 测试用例 2: template_template_matching +add_executable(test_template_matching + ${CMAKE_CURRENT_SOURCE_DIR}/test_template_matching.cpp +) + +# 链接 Matrox 模块和依赖库 +target_link_libraries(test_template_matching Matrox ${OpenCV_LIBS} ${MIL_LIBS}) \ No newline at end of file diff --git a/tests/test_color_range.cpp b/tests/test_color_range.cpp new file mode 100644 index 0000000..dd0c6af --- /dev/null +++ b/tests/test_color_range.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include "Matrox/utils.h" +#include "Matrox/color_range.h" + +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton_image\\174.bmp") +#define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\diguandai.png") + +// Global variables +MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; + +int main() +{ + // Initialize MIL application + MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, + M_NULL); + + // Load input image + MIL_ID MilImage = M_NULL; + MbufRestore(IMAGE_PATH, MilSystem, &MilImage); + + // Define color ranges + std::map params; + params["green_L_min"] = 27; + params["green_L_max"] = 49; + params["green_a_min"] = -27; + params["green_a_max"] = -8; + params["green_b_min"] = 2; + params["green_b_max"] = 12; + + params["blue_L_min"] = 18; + params["blue_L_max"] = 26; + params["blue_a_min"] = 2; + params["blue_a_max"] = 17; + params["blue_b_min"] = -33; + params["blue_b_max"] = -23; + + params["orange_L_min"] = 65; + params["orange_L_max"] = 75; + params["orange_a_min"] = 7; + params["orange_a_max"] = 14; + params["orange_b_min"] = 32; + params["orange_b_max"] = 46; + + params["black_L_min"] = 0; + params["black_L_max"] = 8; + params["black_a_min"] = -1; + params["black_a_max"] = 5; + params["black_b_min"] = -2; + params["black_b_max"] = 6; + + params["red_L_min"] = 28; + params["red_L_max"] = 38; + params["red_a_min"] = 15; + params["red_a_max"] = 25; + params["red_b_min"] = -95; + params["red_b_max"] = 26; + + params["purple_L_min"] = 67; + params["purple_L_max"] = 77; + params["purple_a_min"] = 3; + params["purple_a_max"] = 13; + params["purple_b_min"] = -20; + params["purple_b_max"] = -5; + params["lab_denoising"] = 1; + + params["saturation_threshold"] = 150; + params["saturation_denoising"] = 1; + + // Initialize combined result + MIL_ID detection_result = M_NULL; + + // Measure execution time + measure_execution_time([&]() { + high_sat_detect(MilImage, detection_result, params); + }); + MbufSave(SAVE_PATH, detection_result); + // Display result + + std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; + getchar(); + + // Free resources + MbufFree(detection_result); + MbufFree(MilImage); + MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); + + return 0; +} \ No newline at end of file diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp new file mode 100644 index 0000000..36caf62 --- /dev/null +++ b/tests/test_template_matching.cpp @@ -0,0 +1,64 @@ +// +// Created by zjc on 24-11-20. +// +#include +#include +#include +#include +#include "Matrox/utils.h" +#include "Matrox/template_matching.h" + +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton2.bmp") +#define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\suspect.png") + +// Global variables +MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; + + +int main() { + using namespace std; + map params; + params["cotton_L_min"] = 40; + params["cotton_L_max"] = 90; + params["cotton_a_min"] = -5; + params["cotton_a_max"] = 6; + params["cotton_b_min"] = -5; + params["cotton_b_max"] = 30; + + params["background_L_min"] = 95; + params["background_L_max"] = 100; + params["background_a_min"] = -3; + params["background_a_max"] = 3; + params["background_b_min"] = -3; + params["background_b_max"] = 3; + + params["cotton_denoising"] = 1; + + // Initialize MIL application + MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, + M_NULL); + + // Load input image + MIL_ID MilImage = M_NULL; + MbufRestore(IMAGE_PATH, MilSystem, &MilImage); + + // Initialize combined result + MIL_ID detection_result = M_NULL; + + // Measure execution time + measure_execution_time([&]() { + pre_process(MilImage, detection_result, params); + template_matching(detection_result, detection_result, params); + }); + MbufSave(SAVE_PATH, detection_result); + // Display result + + std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; + getchar(); + + // Free resources + MbufFree(detection_result); + MbufFree(MilImage); + MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); + return 0; +} \ No newline at end of file From 920f92850fd94896b4dfe1bfbf1392e4d57e5261 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Wed, 20 Nov 2024 17:56:09 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=8F=AF=E4=BB=A5=E6=98=BE=E7=A4=BA=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=B9=B6=E5=AE=9E=E7=8E=B0=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 349 +++++++++++++++---------------- src/Matrox/utils.cpp | 18 +- src/Matrox/utils.h | 2 + tests/test_template_matching.cpp | 2 +- 4 files changed, 187 insertions(+), 184 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index 850c94c..e959513 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -3,12 +3,12 @@ #include #include "color_range.h" #include "utils.h" +using namespace std; - -void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params) { +void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const map& params) { // 异色检测, 检测出不同与棉花颜色的物体作为模板匹配的对象 - const std::vector colors = {"cotton", "background"}; - std::map param_temp = params; + const vector colors = {"cotton", "background"}; + map param_temp = params; param_temp["lab_denoising"] = param_temp["cotton_denoising"]; param_temp["saturation_threshold"] = param_temp["cotton_saturation_threshold"]; param_temp["saturation_denoising"] = param_temp["cotton_saturation_denoising"]; @@ -16,204 +16,191 @@ void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std MimArith(outputImageSuspect, M_NULL, outputImageSuspect, M_NOT); } -/* Number of models. */ -#define NUMBER_OF_MODELS 3L -#define MODELS_MAX_OCCURRENCES 16L -/* Model 1 specifications. */ -#define MODEL0_OFFSETX 34L -#define MODEL0_OFFSETY 93L -#define MODEL0_SIZEX 214L -#define MODEL0_SIZEY 76L -#define MODEL0_DRAW_COLOR M_COLOR_RED +class TemplateMatcher { + private: + MIL_ID MilSearchContext; + MIL_ID MilResult; + MIL_ID GraphicList; -/* Model 2 specifications. */ -#define MODEL1_OFFSETX 73L -#define MODEL1_OFFSETY 232L -#define MODEL1_SIZEX 150L -#define MODEL1_SIZEY 154L -#define MODEL1_REFERENCEX 23L -#define MODEL1_REFERENCEY 127L -#define MODEL1_DRAW_COLOR M_COLOR_GREEN + vector ModelImgPaths; + vector ModelsOffsetX; + vector ModelsOffsetY; + vector ModelsSizeX; + vector ModelsSizeY; + vector ModelsDrawColor; -/* Model 3 specifications. */ -#define MODEL2_OFFSETX 308L -#define MODEL2_OFFSETY 39L -#define MODEL2_SIZEX 175L -#define MODEL2_SIZEY 357L -#define MODEL2_REFERENCEX 62L -#define MODEL2_REFERENCEY 150L -#define MODEL2_DRAW_COLOR M_COLOR_BLUE -/* Search speed: M_VERY_HIGH for faster search, M_MEDIUM for precision and robustness.*/ -#define MULTI_MODELS_SEARCH_SPEED M_VERY_HIGH + bool isInitialized; -/* Models array specifications. */ -#define MODELS_ARRAY_SIZE 3L -#define MODELS_OFFSETX {MODEL0_OFFSETX, MODEL1_OFFSETX, MODEL2_OFFSETX} -#define MODELS_OFFSETY {MODEL0_OFFSETY, MODEL1_OFFSETY, MODEL2_OFFSETY} -#define MODELS_SIZEX {MODEL0_SIZEX, MODEL1_SIZEX, MODEL2_SIZEX} -#define MODELS_SIZEY {MODEL0_SIZEY, MODEL1_SIZEY, MODEL2_SIZEY} -#define MODELS_DRAW_COLOR {MODEL0_DRAW_COLOR, MODEL1_DRAW_COLOR, MODEL2_DRAW_COLOR} + public: + // Constructor + TemplateMatcher(MIL_ID system, MIL_ID display): + isInitialized(false) {} - -void template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const std::map& params) { - MIL_ID MilImage, /* Image buffer identifier. */ - GraphicList; /* Graphic list identifier. */ - MIL_ID MilSearchContext, /* Search context */ - MilResult; /* Result identifier. */ - MIL_INT Models[MODELS_MAX_OCCURRENCES], /* Model indices. */ - ModelsOffsetX[MODELS_ARRAY_SIZE] = MODELS_OFFSETX,/* Model X offsets array. */ - ModelsOffsetY[MODELS_ARRAY_SIZE] = MODELS_OFFSETY,/* Model Y offsets array. */ - ModelsSizeX[MODELS_ARRAY_SIZE] = MODELS_SIZEX, /* Model X sizes array. */ - ModelsSizeY[MODELS_ARRAY_SIZE] = MODELS_SIZEY; /* Model Y sizes array. */ - MIL_DOUBLE ModelsDrawColor[MODELS_ARRAY_SIZE]=MODELS_DRAW_COLOR; /* Model drawing colors.*/ - MIL_INT NumResults = 0L; /* Number of results found. */ - MIL_DOUBLE Score[MODELS_MAX_OCCURRENCES], /* Model correlation scores.*/ - XPosition[MODELS_MAX_OCCURRENCES], /* Model X positions. */ - YPosition[MODELS_MAX_OCCURRENCES], /* Model Y positions. */ - Angle[MODELS_MAX_OCCURRENCES], /* Model occurrence angles. */ - Scale[MODELS_MAX_OCCURRENCES], /* Model occurrence scales. */ - Time = 0.0; /* Time variable. */ - int i; /* Loop variable */ - MIL_ID inputImageSuspect = convert_to_uint8(inputImage); - /* Restore the model image and display it. */ - MdispSelect(MilDisplay, inputImageSuspect); - - // 用于显示的部分 - /* Allocate a graphic list to hold the subpixel annotations to draw. */ - MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); - /* Associate the graphic list to the display for annotations. */ - MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); - - - /* Allocate a geometric model finder. */ - MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); - // 取出一个buffer用来存储结果 - /* Allocate a result buffer. */ - MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); - - /* Define the models. */ - for (i=0; i& template_paths, + const vector& offsetX, const vector& offsetY, + const vector& sizeX, const vector& sizeY, + const vector& drawColor) { - // 设置一些参数 - /* Set the desired search speed. */ - MmodControl(MilSearchContext, M_CONTEXT, M_SPEED, MULTI_MODELS_SEARCH_SPEED); + if (isInitialized) { + cerr << "Templates are already loaded. Reinitializing...\n"; + MgraFree(GraphicList); + MmodFree(MilSearchContext); + MmodFree(MilResult); + } - /* Increase the smoothness for the edge extraction in the search context. */ - MmodControl(MilSearchContext, M_CONTEXT, M_SMOOTHNESS, 75); + ModelsOffsetX = offsetX; + ModelsOffsetY = offsetY; + ModelsSizeX = sizeX; + ModelsSizeY = sizeY; + ModelsDrawColor = drawColor; + ModelImgPaths = template_paths; - /* Modify the acceptance and the certainty for all the models that were defined. */ - MmodControl(MilSearchContext, M_DEFAULT, M_ACCEPTANCE, 40); - MmodControl(MilSearchContext, M_DEFAULT, M_CERTAINTY, 60); + // 搜索上下文和搜索结果的buffer + MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); + MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); - /* Set the number of occurrences to 2 for all the models that were defined. */ - MmodControl(MilSearchContext, M_DEFAULT, M_NUMBER, 2); + // Define templates + for (size_t i = 0; i < template_paths.size(); ++i) { + MIL_ID template_temporary; + MbufRestore(convert_to_wstring(ModelImgPaths[i]), MilSystem, &template_temporary); + MIL_ID template_temporary_uint8 = convert_to_uint8(template_temporary); + MdispSelect(MilDisplay, template_temporary_uint8); + /* Allocate a graphic list to hold the subpixel annotations to draw. */ + MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); + /* Associate the graphic list to the display for annotations. */ + MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); - #if (NUMBER_OF_MODELS>1) - /* Change the reference point of the second model. */ - MmodControl(MilSearchContext, 1, M_REFERENCE_X, MODEL1_REFERENCEX); - MmodControl(MilSearchContext, 1, M_REFERENCE_Y, MODEL1_REFERENCEY); - #if (NUMBER_OF_MODELS>2) - /* Change the reference point of the third model. */ - MmodControl(MilSearchContext, 2, M_REFERENCE_X, MODEL2_REFERENCEX); - MmodControl(MilSearchContext, 2, M_REFERENCE_Y, MODEL2_REFERENCEY); - #endif - #endif - /* Preprocess the search context. */ - MmodPreprocess(MilSearchContext, M_DEFAULT); + MmodDefine(MilSearchContext, M_IMAGE, template_temporary_uint8, + static_cast(ModelsOffsetX[i]), + static_cast(ModelsOffsetY[i]), + static_cast(ModelsSizeX[i]), + static_cast(ModelsSizeY[i])); + } + + // 设置一些参数 + /* Set the desired search speed. */ + MmodControl(MilSearchContext, M_CONTEXT, M_SPEED, M_VERY_HIGH); + + /* Increase the smoothness for the edge extraction in the search context. */ + MmodControl(MilSearchContext, M_CONTEXT, M_SMOOTHNESS, 75); + + /* Modify the acceptance and the certainty for all the models that were defined. */ + MmodControl(MilSearchContext, M_DEFAULT, M_ACCEPTANCE, 40); + MmodControl(MilSearchContext, M_DEFAULT, M_CERTAINTY, 60); + + /* Set the number of occurrences to 2 for all the models that were defined. */ + MmodControl(MilSearchContext, M_DEFAULT, M_NUMBER, 2); + + // Preprocess templates + MmodPreprocess(MilSearchContext, M_DEFAULT); + + isInitialized = true; + cout << "Templates loaded and preprocessed successfully.\n"; + + /* Draw boxes and positions in the source image to identify the models. */ + for (int i=0; i to continue.\n\n")); + MosGetch(); - /* Draw boxes and positions in the source image to identify the models. */ - for (i=0; i to continue.\n\n")); - MosGetch(); + // Search for models in the input image + void findModels(const MIL_ID& inputImage) { + if (!isInitialized) { + cerr << "Templates are not loaded. Please load templates before searching.\n"; + return; + } + MIL_ID input_image_uint8 = convert_to_uint8(inputImage); - /* Clear annotations. */ - MgraClear(M_DEFAULT, GraphicList); + MdispSelect(MilDisplay, input_image_uint8); + + // Clear previous annotations + MgraClear(M_DEFAULT, GraphicList); + + // Find models + MIL_DOUBLE Time = 0.0; + MappTimer(M_DEFAULT, M_TIMER_RESET + M_SYNCHRONOUS, M_NULL); + MmodFind(MilSearchContext, input_image_uint8, MilResult); + MappTimer(M_DEFAULT, M_TIMER_READ + M_SYNCHRONOUS, &Time); + + // Get results + MIL_INT NumResults = 0; + MmodGetResult(MilResult, M_DEFAULT, M_NUMBER + M_TYPE_MIL_INT, &NumResults); + + if (NumResults >= 1) { + vector Models(NumResults); + vector XPosition(NumResults), YPosition(NumResults), Angle(NumResults), + Scale(NumResults), Score(NumResults); + + MmodGetResult(MilResult, M_DEFAULT, M_INDEX + M_TYPE_MIL_INT, Models.data()); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition.data()); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition.data()); + MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle.data()); + MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale.data()); + MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score.data()); + + // Display results + cout << "Found " << NumResults << " model(s) in " << Time * 1000.0 << " ms:\n"; + cout << "Result Model X Position Y Position Angle Scale Score\n"; + for (MIL_INT i = 0; i < NumResults; ++i) { + cout << i << " " << Models[i] << " " << XPosition[i] << " " + << YPosition[i] << " " << Angle[i] << " " << Scale[i] + << " " << Score[i] << "%\n"; + + // Draw results + MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); + MmodDraw(M_DEFAULT, MilResult, GraphicList, + M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); + } + } else { + cout << "No models found.\n"; + } + } +}; - /* Dummy first call for bench measure purpose only (bench stabilization, - cache effect, etc...). This first call is NOT required by the application. */ - // MmodFind(MilSearchContext, inputImageSuspect, MilResult); - /* Reset the timer. */ - MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL); +void template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const map& params) { + // Create a TemplateMatcher instance + TemplateMatcher matcher(MilSystem, MilDisplay); - /* Find the models. */ - MmodFind(MilSearchContext, inputImageSuspect, MilResult); + // Load template models + vector template_paths = {"C:\\Users\\zjc\\Desktop\\template1.png", + "C:\\Users\\zjc\\Desktop\\template1.png", + "C:\\Users\\zjc\\Desktop\\template1.png", + }; + vector offsetX = {0, 20, 30}; + vector offsetY = {0, 20, 30}; + vector sizeX = {100, 60, 40}; + vector sizeY = {100, 60, 40}; + vector drawColor = {M_COLOR_RED, M_COLOR_GREEN, M_COLOR_BLUE}; + matcher.loadTemplates(template_paths, offsetX, offsetY, sizeX, sizeY, drawColor); - /* Read the find time. */ - MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time); + // Find models + matcher.findModels(inputImage); - /* Get the number of models found. */ - MmodGetResult(MilResult, M_DEFAULT, M_NUMBER+M_TYPE_MIL_INT, &NumResults); - - /* If the models were found above the acceptance threshold. */ - if( (NumResults >= 1) && (NumResults <= MODELS_MAX_OCCURRENCES) ) - { - /* Get the results for each model. */ - MmodGetResult(MilResult, M_DEFAULT, M_INDEX+M_TYPE_MIL_INT, Models); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition); - MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle); - MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale); - MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score); - - /* Print information about the target image. */ - MosPrintf(MIL_TEXT("The models were found in the target ")); - MosPrintf(MIL_TEXT("image although there is:\n ")); - MosPrintf(MIL_TEXT("Full rotation\n Small scale change\n ")); - MosPrintf(MIL_TEXT("Contrast variation\n Specular reflection\n ")); - MosPrintf(MIL_TEXT("Occlusion\n Multiple models\n")); - MosPrintf(MIL_TEXT(" Multiple occurrences\n\n")); - - /* Print the results for the found models. */ - MosPrintf(MIL_TEXT("Result Model X Position Y Position ") - MIL_TEXT("Angle Scale Score\n\n")); - for (i=0; i to end.\n\n")); - MosGetch(); - - /* Free MIL objects. */ - MgraFree(GraphicList); - // MbufFree(MilImage); - MmodFree(MilSearchContext); - MmodFree(MilResult); + // Free resources + MappFreeDefault(MilApplication, MilSystem, M_NULL, M_NULL, MilDisplay); } + diff --git a/src/Matrox/utils.cpp b/src/Matrox/utils.cpp index 951f0e9..6ab2987 100644 --- a/src/Matrox/utils.cpp +++ b/src/Matrox/utils.cpp @@ -54,10 +54,24 @@ MIL_ID convert_to_uint8(MIL_ID input_img) { MIL_ID MilSystem = MbufInquire(input_img, M_OWNER_SYSTEM, M_NULL); MIL_INT size_x = MbufInquire(input_img, M_SIZE_X, M_NULL); MIL_INT size_y = MbufInquire(input_img, M_SIZE_Y, M_NULL); + MIL_INT channel_num = MbufInquire(input_img, M_SIZE_BAND, M_NULL); + MbufAlloc2d(MilSystem, size_x, size_y, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, &output_img); - MimArith(output_img, input_img, output_img, M_ADD); - MimArith(output_img, 255.0, output_img, M_MULT_CONST); + if(channel_num == 1) { + MimArith(output_img, input_img, output_img, M_ADD); + MimArith(output_img, 255.0, output_img, M_MULT_CONST); + } else if(channel_num == 3) { + MimConvert(input_img, output_img, M_RGB_TO_L); + MimArith(output_img, M_NULL, output_img, M_NOT); + } else { + cout << "Unsupported channel number!" << endl; + } return output_img; } + +wstring convert_to_wstring(const string& str) { + return wstring(str.begin(), str.end()); +} + // 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/src/Matrox/utils.h b/src/Matrox/utils.h index b194df1..09fb061 100644 --- a/src/Matrox/utils.h +++ b/src/Matrox/utils.h @@ -32,4 +32,6 @@ std::vector opencvLabToPsLab(const std::vector& lab_cv); MIL_ID convert_to_uint8(MIL_ID input_img); +std::wstring convert_to_wstring(const std::string& str); + #endif //UTILS_H diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 36caf62..c8d6725 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -22,7 +22,7 @@ int main() { params["cotton_L_max"] = 90; params["cotton_a_min"] = -5; params["cotton_a_max"] = 6; - params["cotton_b_min"] = -5; + params["cotton_b_min"] = 0; params["cotton_b_max"] = 30; params["background_L_min"] = 95; From a7c5f4fec511028b6d231534c91d5e87392725f1 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Wed, 20 Nov 2024 19:54:19 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=8611=E6=9C=8821?= =?UTF-8?q?=E6=97=A5=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 11 ++++++++++- tests/test_template_matching.cpp | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index e959513..8d24a69 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -181,10 +181,19 @@ class TemplateMatcher { }; -void template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const map& params) { +void test_template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const map& params) { // Create a TemplateMatcher instance TemplateMatcher matcher(MilSystem, MilDisplay); + //TODO: 1加入加载多个模板的功能 + //TODO: 2加入配置文件解析功能,解析后的文件与当前的para map兼容 + // 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。 + //TODO: 3修改当前的代码使模板匹配不出错 + //TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 + //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); + //TODO: 6完善相应部分的手册 + + // Load template models vector template_paths = {"C:\\Users\\zjc\\Desktop\\template1.png", "C:\\Users\\zjc\\Desktop\\template1.png", diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index c8d6725..792c152 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -48,7 +48,7 @@ int main() { // Measure execution time measure_execution_time([&]() { pre_process(MilImage, detection_result, params); - template_matching(detection_result, detection_result, params); + test_template_matching(detection_result, detection_result, params); }); MbufSave(SAVE_PATH, detection_result); // Display result From 96c55d89c005bb326a90128eb928d3a7a4f8517b Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Thu, 21 Nov 2024 12:38:37 +0800 Subject: [PATCH 11/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E7=9A=84=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 66 +++++++++++++++++++++++--------- src/Matrox/template_matching.h | 1 + src/Matrox/utils.cpp | 45 ++++++++++++++++++++++ src/Matrox/utils.h | 5 +++ tests/test_color_range.cpp | 46 +--------------------- tests/test_template_matching.cpp | 26 ++++--------- 6 files changed, 106 insertions(+), 83 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index 8d24a69..deba732 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -32,10 +32,12 @@ class TemplateMatcher { bool isInitialized; + map param; + public: // Constructor - TemplateMatcher(MIL_ID system, MIL_ID display): - isInitialized(false) {} + TemplateMatcher(MIL_ID system, MIL_ID display, map& param): + isInitialized(false) {this->param = param;} // Destructor: Free MIL objects ~TemplateMatcher() { @@ -75,7 +77,10 @@ class TemplateMatcher { MIL_ID template_temporary; MbufRestore(convert_to_wstring(ModelImgPaths[i]), MilSystem, &template_temporary); MIL_ID template_temporary_uint8 = convert_to_uint8(template_temporary); - MdispSelect(MilDisplay, template_temporary_uint8); + if (this->param["isdisplay"] == 1) + { + MdispSelect(MilDisplay, template_temporary_uint8); + } /* Allocate a graphic list to hold the subpixel annotations to draw. */ MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); /* Associate the graphic list to the display for annotations. */ @@ -83,11 +88,22 @@ class TemplateMatcher { + MmodDefine(MilSearchContext, M_IMAGE, template_temporary_uint8, static_cast(ModelsOffsetX[i]), static_cast(ModelsOffsetY[i]), static_cast(ModelsSizeX[i]), static_cast(ModelsSizeY[i])); + + MgraColor(M_DEFAULT, ModelsDrawColor[i]); + MmodDraw( M_DEFAULT, MilSearchContext, GraphicList, + M_DRAW_BOX+M_DRAW_POSITION, i, M_ORIGINAL); + if (this->param["isdisplay"] == 1) + { + MosGetch(); + } + MbufFree(template_temporary); + MbufFree(template_temporary_uint8); } // 设置一些参数 @@ -111,19 +127,20 @@ class TemplateMatcher { cout << "Templates loaded and preprocessed successfully.\n"; /* Draw boxes and positions in the source image to identify the models. */ - for (int i=0; i to continue.\n\n")); - MosGetch(); - + if (this->param["debug_mode"] == 1) { + MosGetch(); + } } // Search for models in the input image @@ -173,22 +190,30 @@ class TemplateMatcher { MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); MmodDraw(M_DEFAULT, MilResult, GraphicList, M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); + } } else { cout << "No models found.\n"; } + MosPrintf(MIL_TEXT("Press to EXIT.\n\n")); + MosGetch(); + + + MbufFree(input_image_uint8); } + }; -void test_template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const map& params) { +void test_template_matching(const MIL_ID &inputImage, MIL_ID &outputImage, map ¶ms) +{ // Create a TemplateMatcher instance - TemplateMatcher matcher(MilSystem, MilDisplay); + TemplateMatcher matcher(MilSystem, MilDisplay, params); - //TODO: 1加入加载多个模板的功能 + //TODO: 1加入加载多个模板的功能 已 //TODO: 2加入配置文件解析功能,解析后的文件与当前的para map兼容 - // 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。 - //TODO: 3修改当前的代码使模板匹配不出错 + // 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。已 + //TODO: 3修改当前的代码使模板匹配不出错 已 //TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); //TODO: 6完善相应部分的手册 @@ -196,8 +221,8 @@ void test_template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const // Load template models vector template_paths = {"C:\\Users\\zjc\\Desktop\\template1.png", - "C:\\Users\\zjc\\Desktop\\template1.png", - "C:\\Users\\zjc\\Desktop\\template1.png", + "C:\\Users\\zjc\\Desktop\\template2.png", + "C:\\Users\\zjc\\Desktop\\template3.png", }; vector offsetX = {0, 20, 30}; vector offsetY = {0, 20, 30}; @@ -209,7 +234,10 @@ void test_template_matching(const MIL_ID& inputImage, MIL_ID& outputImage, const // Find models matcher.findModels(inputImage); + // Free resources - MappFreeDefault(MilApplication, MilSystem, M_NULL, M_NULL, MilDisplay); + // } + + diff --git a/src/Matrox/template_matching.h b/src/Matrox/template_matching.h index 0e0ec60..6225c96 100644 --- a/src/Matrox/template_matching.h +++ b/src/Matrox/template_matching.h @@ -7,4 +7,5 @@ void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params); void template_matching(const MIL_ID& inputImageSuspect, MIL_ID& outputImage, const std::map& params); +void test_template_matching(const MIL_ID &inputImage, MIL_ID &outputImage, std::map ¶ms) ; #endif //TEMPLATE_MATCHING_H diff --git a/src/Matrox/utils.cpp b/src/Matrox/utils.cpp index 6ab2987..31b3f0e 100644 --- a/src/Matrox/utils.cpp +++ b/src/Matrox/utils.cpp @@ -74,4 +74,49 @@ wstring convert_to_wstring(const string& str) { return wstring(str.begin(), str.end()); } + + +void read_params_from_file(const std::string& filename, std::map& params) { + std::ifstream infile(filename); + if (!infile) { + std::cerr << "无法打开文件: " << filename << std::endl; + return; + } + + std::string line; + while (std::getline(infile, line)) { + // 去除行首和行尾的空白字符 + line.erase(0, line.find_first_not_of(" \t\r\n")); + line.erase(line.find_last_not_of(" \t\r\n") + 1); + + // 跳过空行和注释行 + if (line.empty() || line[0] == '#') + continue; + + // 查找等号的位置 + size_t pos = line.find('='); + if (pos == std::string::npos) + continue; // 如果没有等号,跳过该行 + + // 分割键和值,并去除空白字符 + std::string key = line.substr(0, pos); + std::string value_str = line.substr(pos + 1); + key.erase(0, key.find_first_not_of(" \t")); + key.erase(key.find_last_not_of(" \t") + 1); + value_str.erase(0, value_str.find_first_not_of(" \t")); + value_str.erase(value_str.find_last_not_of(" \t") + 1); + + // 将字符串转换为整数 + int value; + std::istringstream iss(value_str); + if (!(iss >> value)) { + std::cerr << "键 " << key << " 的值无效: " << value_str << std::endl; + continue; + } + + // 将键值对添加到参数映射中 + params[key] = value; + } +} + // 图片转换函数,输入4096*1024*3的图片,输出为(4096 / n_valves) * (1024 / n_merge_vertical) * 1 diff --git a/src/Matrox/utils.h b/src/Matrox/utils.h index 09fb061..08f505e 100644 --- a/src/Matrox/utils.h +++ b/src/Matrox/utils.h @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include // 声明全局变量(注意:这里只是声明,不是定义) extern __int64 MilApplication; @@ -33,5 +37,6 @@ std::vector opencvLabToPsLab(const std::vector& lab_cv); MIL_ID convert_to_uint8(MIL_ID input_img); std::wstring convert_to_wstring(const std::string& str); +void read_params_from_file(const std::string& filename, std::map& params) ; #endif //UTILS_H diff --git a/tests/test_color_range.cpp b/tests/test_color_range.cpp index dd0c6af..c57a590 100644 --- a/tests/test_color_range.cpp +++ b/tests/test_color_range.cpp @@ -23,51 +23,7 @@ int main() // Define color ranges std::map params; - params["green_L_min"] = 27; - params["green_L_max"] = 49; - params["green_a_min"] = -27; - params["green_a_max"] = -8; - params["green_b_min"] = 2; - params["green_b_max"] = 12; - - params["blue_L_min"] = 18; - params["blue_L_max"] = 26; - params["blue_a_min"] = 2; - params["blue_a_max"] = 17; - params["blue_b_min"] = -33; - params["blue_b_max"] = -23; - - params["orange_L_min"] = 65; - params["orange_L_max"] = 75; - params["orange_a_min"] = 7; - params["orange_a_max"] = 14; - params["orange_b_min"] = 32; - params["orange_b_max"] = 46; - - params["black_L_min"] = 0; - params["black_L_max"] = 8; - params["black_a_min"] = -1; - params["black_a_max"] = 5; - params["black_b_min"] = -2; - params["black_b_max"] = 6; - - params["red_L_min"] = 28; - params["red_L_max"] = 38; - params["red_a_min"] = 15; - params["red_a_max"] = 25; - params["red_b_min"] = -95; - params["red_b_max"] = 26; - - params["purple_L_min"] = 67; - params["purple_L_max"] = 77; - params["purple_a_min"] = 3; - params["purple_a_max"] = 13; - params["purple_b_min"] = -20; - params["purple_b_max"] = -5; - params["lab_denoising"] = 1; - - params["saturation_threshold"] = 150; - params["saturation_denoising"] = 1; + read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\color_range_config.txt", params); // Initialize combined result MIL_ID detection_result = M_NULL; diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 792c152..6c6b8b3 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -17,23 +17,9 @@ MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; int main() { using namespace std; - map params; - params["cotton_L_min"] = 40; - params["cotton_L_max"] = 90; - params["cotton_a_min"] = -5; - params["cotton_a_max"] = 6; - params["cotton_b_min"] = 0; - params["cotton_b_max"] = 30; - - params["background_L_min"] = 95; - params["background_L_max"] = 100; - params["background_a_min"] = -3; - params["background_a_max"] = 3; - params["background_b_min"] = -3; - params["background_b_max"] = 3; - - params["cotton_denoising"] = 1; + std::map params; + read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\config.txt", params); // Initialize MIL application MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); @@ -46,7 +32,8 @@ int main() { MIL_ID detection_result = M_NULL; // Measure execution time - measure_execution_time([&]() { + measure_execution_time([&]() + { pre_process(MilImage, detection_result, params); test_template_matching(detection_result, detection_result, params); }); @@ -56,9 +43,10 @@ int main() { std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; getchar(); - // Free resources + + MbufFree(detection_result); MbufFree(MilImage); - MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); + return 0; } \ No newline at end of file From 38202919e6ee682fec37100b17afdffb579a0803 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Thu, 21 Nov 2024 14:46:37 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=E6=9B=B4=E6=96=B0readme=EF=BC=8C?= =?UTF-8?q?=E5=B0=86=E5=8A=A0=E8=BD=BD=E6=A8=A1=E5=9E=8B=E5=92=8C=E5=AF=BB?= =?UTF-8?q?=E6=89=BE=E6=A8=A1=E5=9E=8B=E5=88=86=E7=A6=BB=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E4=B8=80=E6=AC=A1=E5=8A=A0=E8=BD=BD=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=8D=B3=E5=8F=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/README.md | 7 + src/Matrox/template_matching.cpp | 402 ++++++++++++++----------------- src/Matrox/template_matching.h | 55 ++++- tests/test_template_matching.cpp | 8 +- 4 files changed, 247 insertions(+), 225 deletions(-) diff --git a/src/Matrox/README.md b/src/Matrox/README.md index 36a4653..c45ed5d 100644 --- a/src/Matrox/README.md +++ b/src/Matrox/README.md @@ -84,3 +84,10 @@ void hsv_process(const MIL_ID& inputImage, MIL_ID& outputImageHSV, const std::ma | red | 28 | 38 | 15 | 25 | -95 | 26 | | purple | 67 | 77 | 3 | 13 | -20 | -5 | + +### utils模块包含的工具函数 +1.模型图片路径格式转换 +2.uint1转uint8图片函数 +3.ps和opencv阈值相互转换函数 +4.读取配置文件函数 + diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index deba732..a75e9d1 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -3,6 +3,7 @@ #include #include "color_range.h" #include "utils.h" +#include"template_matching.h" using namespace std; void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const map& params) { @@ -16,228 +17,189 @@ void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const map MimArith(outputImageSuspect, M_NULL, outputImageSuspect, M_NOT); } - -class TemplateMatcher { - private: - MIL_ID MilSearchContext; - MIL_ID MilResult; - MIL_ID GraphicList; - - vector ModelImgPaths; - vector ModelsOffsetX; - vector ModelsOffsetY; - vector ModelsSizeX; - vector ModelsSizeY; - vector ModelsDrawColor; - - bool isInitialized; - - map param; - - public: - // Constructor - TemplateMatcher(MIL_ID system, MIL_ID display, map& param): - isInitialized(false) {this->param = param;} - - // Destructor: Free MIL objects - ~TemplateMatcher() { - if (isInitialized) { - MgraFree(GraphicList); - MmodFree(MilSearchContext); - MmodFree(MilResult); - } - } - - // Load template models - void loadTemplates(const vector& template_paths, - const vector& offsetX, const vector& offsetY, - const vector& sizeX, const vector& sizeY, - const vector& drawColor) { - - if (isInitialized) { - cerr << "Templates are already loaded. Reinitializing...\n"; - MgraFree(GraphicList); - MmodFree(MilSearchContext); - MmodFree(MilResult); - } - - ModelsOffsetX = offsetX; - ModelsOffsetY = offsetY; - ModelsSizeX = sizeX; - ModelsSizeY = sizeY; - ModelsDrawColor = drawColor; - ModelImgPaths = template_paths; - - // 搜索上下文和搜索结果的buffer - MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); - MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); - - // Define templates - for (size_t i = 0; i < template_paths.size(); ++i) { - MIL_ID template_temporary; - MbufRestore(convert_to_wstring(ModelImgPaths[i]), MilSystem, &template_temporary); - MIL_ID template_temporary_uint8 = convert_to_uint8(template_temporary); - if (this->param["isdisplay"] == 1) - { - MdispSelect(MilDisplay, template_temporary_uint8); - } - /* Allocate a graphic list to hold the subpixel annotations to draw. */ - MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); - /* Associate the graphic list to the display for annotations. */ - MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); - - - - - MmodDefine(MilSearchContext, M_IMAGE, template_temporary_uint8, - static_cast(ModelsOffsetX[i]), - static_cast(ModelsOffsetY[i]), - static_cast(ModelsSizeX[i]), - static_cast(ModelsSizeY[i])); - - MgraColor(M_DEFAULT, ModelsDrawColor[i]); - MmodDraw( M_DEFAULT, MilSearchContext, GraphicList, - M_DRAW_BOX+M_DRAW_POSITION, i, M_ORIGINAL); - if (this->param["isdisplay"] == 1) - { - MosGetch(); - } - MbufFree(template_temporary); - MbufFree(template_temporary_uint8); - } - - // 设置一些参数 - /* Set the desired search speed. */ - MmodControl(MilSearchContext, M_CONTEXT, M_SPEED, M_VERY_HIGH); - - /* Increase the smoothness for the edge extraction in the search context. */ - MmodControl(MilSearchContext, M_CONTEXT, M_SMOOTHNESS, 75); - - /* Modify the acceptance and the certainty for all the models that were defined. */ - MmodControl(MilSearchContext, M_DEFAULT, M_ACCEPTANCE, 40); - MmodControl(MilSearchContext, M_DEFAULT, M_CERTAINTY, 60); - - /* Set the number of occurrences to 2 for all the models that were defined. */ - MmodControl(MilSearchContext, M_DEFAULT, M_NUMBER, 2); - - // Preprocess templates - MmodPreprocess(MilSearchContext, M_DEFAULT); - - isInitialized = true; - cout << "Templates loaded and preprocessed successfully.\n"; - - /* Draw boxes and positions in the source image to identify the models. */ - // for (int i=0; i to continue.\n\n")); - if (this->param["debug_mode"] == 1) { - MosGetch(); - } - } - - // Search for models in the input image - void findModels(const MIL_ID& inputImage) { - if (!isInitialized) { - cerr << "Templates are not loaded. Please load templates before searching.\n"; - return; - } - MIL_ID input_image_uint8 = convert_to_uint8(inputImage); - - MdispSelect(MilDisplay, input_image_uint8); - - // Clear previous annotations - MgraClear(M_DEFAULT, GraphicList); - - // Find models - MIL_DOUBLE Time = 0.0; - MappTimer(M_DEFAULT, M_TIMER_RESET + M_SYNCHRONOUS, M_NULL); - MmodFind(MilSearchContext, input_image_uint8, MilResult); - MappTimer(M_DEFAULT, M_TIMER_READ + M_SYNCHRONOUS, &Time); - - // Get results - MIL_INT NumResults = 0; - MmodGetResult(MilResult, M_DEFAULT, M_NUMBER + M_TYPE_MIL_INT, &NumResults); - - if (NumResults >= 1) { - vector Models(NumResults); - vector XPosition(NumResults), YPosition(NumResults), Angle(NumResults), - Scale(NumResults), Score(NumResults); - - MmodGetResult(MilResult, M_DEFAULT, M_INDEX + M_TYPE_MIL_INT, Models.data()); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition.data()); - MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition.data()); - MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle.data()); - MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale.data()); - MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score.data()); - - // Display results - cout << "Found " << NumResults << " model(s) in " << Time * 1000.0 << " ms:\n"; - cout << "Result Model X Position Y Position Angle Scale Score\n"; - for (MIL_INT i = 0; i < NumResults; ++i) { - cout << i << " " << Models[i] << " " << XPosition[i] << " " - << YPosition[i] << " " << Angle[i] << " " << Scale[i] - << " " << Score[i] << "%\n"; - - // Draw results - MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); - MmodDraw(M_DEFAULT, MilResult, GraphicList, - M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); - - } - } else { - cout << "No models found.\n"; - } - MosPrintf(MIL_TEXT("Press to EXIT.\n\n")); - MosGetch(); - - - MbufFree(input_image_uint8); - } - -}; - - -void test_template_matching(const MIL_ID &inputImage, MIL_ID &outputImage, map ¶ms) +TemplateMatcher::TemplateMatcher(MIL_ID system, MIL_ID display, std::map& param) + : MilSystem(system), MilDisplay(display), isInitialized(false), param(param) { - // Create a TemplateMatcher instance - TemplateMatcher matcher(MilSystem, MilDisplay, params); - - //TODO: 1加入加载多个模板的功能 已 - //TODO: 2加入配置文件解析功能,解析后的文件与当前的para map兼容 - // 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。已 - //TODO: 3修改当前的代码使模板匹配不出错 已 - //TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 - //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); - //TODO: 6完善相应部分的手册 - - - // Load template models - vector template_paths = {"C:\\Users\\zjc\\Desktop\\template1.png", - "C:\\Users\\zjc\\Desktop\\template2.png", - "C:\\Users\\zjc\\Desktop\\template3.png", - }; - vector offsetX = {0, 20, 30}; - vector offsetY = {0, 20, 30}; - vector sizeX = {100, 60, 40}; - vector sizeY = {100, 60, 40}; - vector drawColor = {M_COLOR_RED, M_COLOR_GREEN, M_COLOR_BLUE}; - matcher.loadTemplates(template_paths, offsetX, offsetY, sizeX, sizeY, drawColor); - - // Find models - matcher.findModels(inputImage); - - - // Free resources - // } +// Destructor +TemplateMatcher::~TemplateMatcher() +{ + if (isInitialized) { + MgraFree(GraphicList); + MmodFree(MilSearchContext); + MmodFree(MilResult); + } +} +// Load template models +void TemplateMatcher::loadTemplates(const std::vector& template_paths, + const std::vector& offsetX, + const std::vector& offsetY, + const std::vector& sizeX, + const std::vector& sizeY, + const std::vector& drawColor) +{ + if (isInitialized) { + std::cerr << "Templates are already loaded. Skipping reloading.\n"; + return; + } + + ModelsOffsetX = offsetX; + ModelsOffsetY = offsetY; + ModelsSizeX = sizeX; + ModelsSizeY = sizeY; + ModelsDrawColor = drawColor; + ModelImgPaths = template_paths; + + // Allocate search context and result buffers + MmodAlloc(MilSystem, M_GEOMETRIC, M_DEFAULT, &MilSearchContext); + MmodAllocResult(MilSystem, M_DEFAULT, &MilResult); + + // Allocate a graphic list to hold the annotations + MgraAllocList(MilSystem, M_DEFAULT, &GraphicList); + MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList); + + // Define templates + for (size_t i = 0; i < template_paths.size(); ++i) { + MIL_ID template_temporary; + MbufRestore(convert_to_wstring(ModelImgPaths[i]).c_str(), MilSystem, &template_temporary); + MIL_ID template_temporary_uint8 = convert_to_uint8(template_temporary); + if (this->param["isdisplay"] == 1) + { + MdispSelect(MilDisplay, template_temporary_uint8); + } + + MmodDefine(MilSearchContext, M_IMAGE, template_temporary_uint8, + static_cast(ModelsOffsetX[i]), + static_cast(ModelsOffsetY[i]), + static_cast(ModelsSizeX[i]), + static_cast(ModelsSizeY[i])); + + MgraColor(M_DEFAULT, ModelsDrawColor[i]); + MmodDraw(M_DEFAULT, MilSearchContext, GraphicList, + M_DRAW_BOX + M_DRAW_POSITION, i, M_ORIGINAL); + + if (this->param["isdisplay"] == 1) + { + MosGetch(); + } + MbufFree(template_temporary); + MbufFree(template_temporary_uint8); + } + + // Set parameters + MmodControl(MilSearchContext, M_CONTEXT, M_SPEED, M_VERY_HIGH); + MmodControl(MilSearchContext, M_CONTEXT, M_SMOOTHNESS, 75); + MmodControl(MilSearchContext, M_DEFAULT, M_ACCEPTANCE, 40); + MmodControl(MilSearchContext, M_DEFAULT, M_CERTAINTY, 60); + MmodControl(MilSearchContext, M_DEFAULT, M_NUMBER, 2); + + // Preprocess templates + MmodPreprocess(MilSearchContext, M_DEFAULT); + + isInitialized = true; + std::cout << "Templates loaded and preprocessed successfully.\n"; + + // Pause to show the models + MosPrintf(MIL_TEXT("A model context was defined with the ") + MIL_TEXT("models in the displayed image.\n")); + MosPrintf(MIL_TEXT("Press to continue.\n\n")); + if (this->param["debug_mode"] == 1) { + MosGetch(); + } +} + +// Search for models in the input image +void TemplateMatcher::findModels(const MIL_ID& inputImage) +{ + if (!isInitialized) { + std::cerr << "Templates are not loaded. Please load templates before searching.\n"; + return; + } + MIL_ID input_image_uint8 = convert_to_uint8(inputImage); + + MdispSelect(MilDisplay, input_image_uint8); + + // Clear previous annotations + MgraClear(M_DEFAULT, GraphicList); + + // Find models + MIL_DOUBLE Time = 0.0; + MappTimer(M_DEFAULT, M_TIMER_RESET + M_SYNCHRONOUS, M_NULL); + MmodFind(MilSearchContext, input_image_uint8, MilResult); + MappTimer(M_DEFAULT, M_TIMER_READ + M_SYNCHRONOUS, &Time); + + // Get results + MIL_INT NumResults = 0; + MmodGetResult(MilResult, M_DEFAULT, M_NUMBER + M_TYPE_MIL_INT, &NumResults); + + if (NumResults >= 1) { + std::vector Models(NumResults); + std::vector XPosition(NumResults), YPosition(NumResults), Angle(NumResults), + Scale(NumResults), Score(NumResults); + + MmodGetResult(MilResult, M_DEFAULT, M_INDEX + M_TYPE_MIL_INT, Models.data()); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_X, XPosition.data()); + MmodGetResult(MilResult, M_DEFAULT, M_POSITION_Y, YPosition.data()); + MmodGetResult(MilResult, M_DEFAULT, M_ANGLE, Angle.data()); + MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale.data()); + MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score.data()); + + // Display results + std::cout << "Found " << NumResults << " model(s) in " << Time * 1000.0 << " ms:\n"; + std::cout << "Result Model X Position Y Position Angle Scale Score\n"; + for (MIL_INT i = 0; i < NumResults; ++i) { + std::cout << i << " " << Models[i] << " " << XPosition[i] << " " + << YPosition[i] << " " << Angle[i] << " " << Scale[i] + << " " << Score[i] << "%\n"; + + // Draw results + MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); + MmodDraw(M_DEFAULT, MilResult, GraphicList, + M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); + } + } else { + std::cout << "No models found.\n"; + } + MosPrintf(MIL_TEXT("Press to EXIT.\n\n")); + MosGetch(); + MbufFree(input_image_uint8); +} +void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ¶ms) +{ + // Create a TemplateMatcher instance (consider making it static if you want to retain it between calls) + + // Load template models only once + matcher.loadTemplates( + { + "C:\\Users\\zjc\\Desktop\\templates\\template1.png", + "C:\\Users\\zjc\\Desktop\\templates\\template2.png", + "C:\\Users\\zjc\\Desktop\\templates\\template3.png", + "C:\\Users\\zjc\\Desktop\\templates\\template2.png", + }, + {0, 20, 30, 33}, // offsetX + {0, 20, 30, 33}, // offsetY + {100, 60, 40, 33}, // sizeX + {100, 60, 40, 33}, // sizeY + {M_COLOR_RED, M_COLOR_GREEN, M_COLOR_BLUE, M_COLOR_GREEN} // drawColor + ); +} + +void TemplateMatcher::FindTemplates( const MIL_ID& inputImage,const MIL_ID& outputImage,TemplateMatcher& matcher) +{ + // Perform template matching + matcher.findModels(inputImage); + + // Notify user that matching is complete + cout << "Template matching completed.\n"; +} + +//TODO: 1加入加载多个模板的功能 已 +//TODO: 2加入配置文件解析功能,解析后的文件与当前的para map兼容 +// 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。已 +//TODO: 3修改当前的代码使模板匹配不出错 已 +//TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 +//TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); +//TODO: 6完善相应部分的手册 diff --git a/src/Matrox/template_matching.h b/src/Matrox/template_matching.h index 6225c96..8230ab6 100644 --- a/src/Matrox/template_matching.h +++ b/src/Matrox/template_matching.h @@ -4,8 +4,57 @@ #ifndef TEMPLATE_MATCHING_H #define TEMPLATE_MATCHING_H -void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params); -void template_matching(const MIL_ID& inputImageSuspect, MIL_ID& outputImage, const std::map& params); -void test_template_matching(const MIL_ID &inputImage, MIL_ID &outputImage, std::map ¶ms) ; + +void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params); +// void LoadTemplate(const MIL_ID &inputImage, MIL_ID &outputImage, std::map ¶ms); + + + +class TemplateMatcher { +private: + MIL_ID MilSystem; + MIL_ID MilDisplay; + MIL_ID MilSearchContext; + MIL_ID MilResult; + MIL_ID GraphicList; + + std::vector ModelImgPaths; + std::vector ModelsOffsetX; + std::vector ModelsOffsetY; + std::vector ModelsSizeX; + std::vector ModelsSizeY; + std::vector ModelsDrawColor; + + bool isInitialized; + + std::map param; + +public: + // Constructor + TemplateMatcher(MIL_ID system, MIL_ID display, std::map& param); + + + + // Load template models + void loadTemplates(const std::vector& template_paths, + const std::vector& offsetX, const std::vector& offsetY, + const std::vector& sizeX, const std::vector& sizeY, + const std::vector& drawColor); + + // Search for models in the input image + void findModels(const MIL_ID& inputImage); + + void LoadTemplate(TemplateMatcher &matcher, std::map ¶ms); + + void FindTemplates(const MIL_ID &inputImage, const MIL_ID &outputImage, TemplateMatcher &matcher); + + + // Destructor + ~TemplateMatcher(); + +}; +// void FindTemplates( const MIL_ID& inputImage,const MIL_ID& outputImage,TemplateMatcher& matcher); +// void LoadTemplate(TemplateMatcher& matcher, std::map ¶ms); + #endif //TEMPLATE_MATCHING_H diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 6c6b8b3..a719b21 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -19,7 +19,7 @@ int main() { using namespace std; std::map params; - read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\config.txt", params); + read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\template_config.txt", params); // Initialize MIL application MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); @@ -30,12 +30,16 @@ int main() { // Initialize combined result MIL_ID detection_result = M_NULL; + MIL_ID output_Image= M_NULL; + TemplateMatcher matcher(MilSystem, MilDisplay, params); // Measure execution time measure_execution_time([&]() { pre_process(MilImage, detection_result, params); - test_template_matching(detection_result, detection_result, params); + matcher.LoadTemplate(matcher,params); + matcher.FindTemplates(detection_result,output_Image,matcher); + //最后的释放问题应该出在寻找模板里面 }); MbufSave(SAVE_PATH, detection_result); // Display result From 445d6fc37cc8e82a1228ba41030ed0bc89df0d6b Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Thu, 21 Nov 2024 21:17:27 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E6=A8=A1=E6=9D=BF=E6=97=B6=E7=9A=84bug?= =?UTF-8?q?=EF=BC=88=E5=89=8D=E9=9D=A2=E5=9B=BE=E7=89=87=E7=BB=98=E5=88=B6?= =?UTF-8?q?=E7=9A=84=E6=A8=A1=E6=9D=BF=E5=8C=BA=E5=9F=9F=E4=BC=9A=E4=BF=9D?= =?UTF-8?q?=E7=95=99=E5=9C=A8=E5=90=8E=E9=9D=A2=E7=9A=84=E5=9B=BE=E7=89=87?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index a75e9d1..dd3077b 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -63,6 +63,7 @@ void TemplateMatcher::loadTemplates(const std::vector& template_pat // Define templates for (size_t i = 0; i < template_paths.size(); ++i) { MIL_ID template_temporary; + MgraClear(M_DEFAULT, GraphicList); MbufRestore(convert_to_wstring(ModelImgPaths[i]).c_str(), MilSystem, &template_temporary); MIL_ID template_temporary_uint8 = convert_to_uint8(template_temporary); if (this->param["isdisplay"] == 1) @@ -176,13 +177,15 @@ void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map兼容 // 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。已 //TODO: 3修改当前的代码使模板匹配不出错 已 -//TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 +//TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 已 //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); -//TODO: 6完善相应部分的手册 +////未实现,因为加载和寻找分开后,要对加载和寻找函数传入类成员,无法统一,其余可用到的参数统一,加一个类成员即可。 +//TODO: 6完善相应部分的手册 已 From 526bb6c2db7987ffb4e7e35652b7c5d331cc6ced Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Sat, 23 Nov 2024 14:46:20 +0800 Subject: [PATCH 14/19] =?UTF-8?q?=E5=B0=86=E6=A8=A1=E6=9D=BF=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=87=BA=E7=9A=84=E7=BB=93=E6=9E=9C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E4=B8=BA=E7=99=BD=E8=89=B2=EF=BC=8C=E5=85=B6=E4=BD=99=E4=B8=BA?= =?UTF-8?q?=E9=BB=91=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 25 +++++++++++++++++++++---- src/Matrox/template_matching.h | 5 +++-- tests/test_template_matching.cpp | 2 -- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index dd3077b..7b16eef 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -112,7 +112,7 @@ void TemplateMatcher::loadTemplates(const std::vector& template_pat } // Search for models in the input image -void TemplateMatcher::findModels(const MIL_ID& inputImage) +void TemplateMatcher::findModels(const MIL_ID& inputImage,MIL_ID& outputImage) { if (!isInitialized) { std::cerr << "Templates are not loaded. Please load templates before searching.\n"; @@ -147,6 +147,13 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale.data()); MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score.data()); + // Create a binary image buffer + MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, + M_IMAGE + M_PROC, &outputImage); + // Initialize the binary image to black + MbufClear(outputImage, 0); + // Display results std::cout << "Found " << NumResults << " model(s) in " << Time * 1000.0 << " ms:\n"; std::cout << "Result Model X Position Y Position Angle Scale Score\n"; @@ -155,11 +162,20 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) << YPosition[i] << " " << Angle[i] << " " << Scale[i] << " " << Score[i] << "%\n"; - // Draw results + // Draw results onto the binary image + MgraColor(M_DEFAULT, 255); // White color for binary image + MmodDraw(M_DEFAULT, MilResult, outputImage, M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); + + // Draw results on the graphical list for display MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); MmodDraw(M_DEFAULT, MilResult, GraphicList, M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); } + + // Display or save the binary image + + MbufSave(SAVE_PATH2, outputImage); + } else { std::cout << "No models found.\n"; } @@ -167,6 +183,7 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) MosGetch(); MbufFree(input_image_uint8); } + void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ¶ms) { // Create a TemplateMatcher instance (consider making it static if you want to retain it between calls) @@ -189,10 +206,10 @@ void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ModelImgPaths; std::vector ModelsOffsetX; @@ -43,11 +44,11 @@ public: const std::vector& drawColor); // Search for models in the input image - void findModels(const MIL_ID& inputImage); +void findModels(const MIL_ID& inputImage,MIL_ID& outputImage); void LoadTemplate(TemplateMatcher &matcher, std::map ¶ms); - void FindTemplates(const MIL_ID &inputImage, const MIL_ID &outputImage, TemplateMatcher &matcher); + void FindTemplates(const MIL_ID &inputImage, MIL_ID &outputImage, TemplateMatcher &matcher); // Destructor diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index a719b21..856f331 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -47,8 +47,6 @@ int main() { std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; getchar(); - - MbufFree(detection_result); MbufFree(MilImage); From 171376aaa1a010f22387f64fd252690a39d76caf Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Sat, 23 Nov 2024 14:46:20 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E5=B0=86=E6=A8=A1=E6=9D=BF=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=87=BA=E7=9A=84=E7=BB=93=E6=9E=9C=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E4=B8=BA=E7=99=BD=E8=89=B2=EF=BC=8C=E5=85=B6=E4=BD=99=E4=B8=BA?= =?UTF-8?q?=E9=BB=91=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 25 +++++++++++++++++++++---- src/Matrox/template_matching.h | 5 +++-- tests/test_template_matching.cpp | 13 ++++++++++--- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index dd3077b..7b16eef 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -112,7 +112,7 @@ void TemplateMatcher::loadTemplates(const std::vector& template_pat } // Search for models in the input image -void TemplateMatcher::findModels(const MIL_ID& inputImage) +void TemplateMatcher::findModels(const MIL_ID& inputImage,MIL_ID& outputImage) { if (!isInitialized) { std::cerr << "Templates are not loaded. Please load templates before searching.\n"; @@ -147,6 +147,13 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) MmodGetResult(MilResult, M_DEFAULT, M_SCALE, Scale.data()); MmodGetResult(MilResult, M_DEFAULT, M_SCORE, Score.data()); + // Create a binary image buffer + MbufAlloc2d(MilSystem, MbufInquire(inputImage, M_SIZE_X, M_NULL), + MbufInquire(inputImage, M_SIZE_Y, M_NULL), 1 + M_UNSIGNED, + M_IMAGE + M_PROC, &outputImage); + // Initialize the binary image to black + MbufClear(outputImage, 0); + // Display results std::cout << "Found " << NumResults << " model(s) in " << Time * 1000.0 << " ms:\n"; std::cout << "Result Model X Position Y Position Angle Scale Score\n"; @@ -155,11 +162,20 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) << YPosition[i] << " " << Angle[i] << " " << Scale[i] << " " << Score[i] << "%\n"; - // Draw results + // Draw results onto the binary image + MgraColor(M_DEFAULT, 255); // White color for binary image + MmodDraw(M_DEFAULT, MilResult, outputImage, M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); + + // Draw results on the graphical list for display MgraColor(M_DEFAULT, ModelsDrawColor[Models[i]]); MmodDraw(M_DEFAULT, MilResult, GraphicList, M_DRAW_EDGES + M_DRAW_POSITION, i, M_DEFAULT); } + + // Display or save the binary image + + MbufSave(SAVE_PATH2, outputImage); + } else { std::cout << "No models found.\n"; } @@ -167,6 +183,7 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage) MosGetch(); MbufFree(input_image_uint8); } + void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ¶ms) { // Create a TemplateMatcher instance (consider making it static if you want to retain it between calls) @@ -189,10 +206,10 @@ void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ModelImgPaths; std::vector ModelsOffsetX; @@ -43,11 +44,11 @@ public: const std::vector& drawColor); // Search for models in the input image - void findModels(const MIL_ID& inputImage); +void findModels(const MIL_ID& inputImage,MIL_ID& outputImage); void LoadTemplate(TemplateMatcher &matcher, std::map ¶ms); - void FindTemplates(const MIL_ID &inputImage, const MIL_ID &outputImage, TemplateMatcher &matcher); + void FindTemplates(const MIL_ID &inputImage, MIL_ID &outputImage, TemplateMatcher &matcher); // Destructor diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index a719b21..7a788f1 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -8,9 +8,10 @@ #include "Matrox/utils.h" #include "Matrox/template_matching.h" -#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton2.bmp") +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\8.bmp") #define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\suspect.png") + // Global variables MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; @@ -18,6 +19,8 @@ MIL_ID MilApplication = M_NULL, MilSystem = M_NULL, MilDisplay = M_NULL; int main() { using namespace std; + + std::map params; read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\template_config.txt", params); // Initialize MIL application @@ -30,6 +33,7 @@ int main() { // Initialize combined result MIL_ID detection_result = M_NULL; + MIL_ID detection_resize = M_NULL; MIL_ID output_Image= M_NULL; TemplateMatcher matcher(MilSystem, MilDisplay, params); @@ -37,6 +41,11 @@ int main() { measure_execution_time([&]() { pre_process(MilImage, detection_result, params); + MbufAlloc2d(MilSystem, MbufInquire(detection_result, M_SIZE_X, M_NULL)/2, + MbufInquire(detection_result, M_SIZE_Y, M_NULL)/2, 1 + M_UNSIGNED, + M_IMAGE + M_PROC, &detection_resize); + MimResize(detection_result,detection_resize,0.5,0.5,M_DEFAULT); + matcher.LoadTemplate(matcher,params); matcher.FindTemplates(detection_result,output_Image,matcher); //最后的释放问题应该出在寻找模板里面 @@ -47,8 +56,6 @@ int main() { std::cout << "所有颜色检测已完成并合并。按 退出。" << std::endl; getchar(); - - MbufFree(detection_result); MbufFree(MilImage); From c500926db178b6a0d685542a3796d5d383518794 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Sun, 24 Nov 2024 13:52:23 +0800 Subject: [PATCH 16/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0resize=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_template_matching.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 7a788f1..b7653ca 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -34,6 +34,8 @@ int main() { // Initialize combined result MIL_ID detection_result = M_NULL; MIL_ID detection_resize = M_NULL; + + MIL_ID output_Image= M_NULL; TemplateMatcher matcher(MilSystem, MilDisplay, params); @@ -47,7 +49,7 @@ int main() { MimResize(detection_result,detection_resize,0.5,0.5,M_DEFAULT); matcher.LoadTemplate(matcher,params); - matcher.FindTemplates(detection_result,output_Image,matcher); + matcher.FindTemplates(detection_resize,output_Image,matcher); //最后的释放问题应该出在寻找模板里面 }); MbufSave(SAVE_PATH, detection_result); From 119f01ae888ac5a0623ebb088fde292592aa9ba5 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Mon, 25 Nov 2024 12:25:43 +0800 Subject: [PATCH 17/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0opencv=E6=8E=89onnx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 +- opencv_onnx.cpp | 137 ++++++++++++++++--------------- src/Matrox/template_matching.cpp | 15 ++-- tests/test_template_matching.cpp | 2 +- 4 files changed, 79 insertions(+), 81 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df8239d..389c023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,9 +71,9 @@ add_subdirectory(tests) #add_executable(onnx src/Matrox/onnx_running.cpp) #target_link_libraries(onnx Qt6::Widgets ${MIL_LIBS}) # -#add_executable(opencv_onnx opencv_onnx.cpp) -## 链接 OpenCV 和 Qt 库 -#target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) +add_executable(opencv_onnx opencv_onnx.cpp) +# 链接 OpenCV 和 Qt 库 +target_link_libraries(opencv_onnx Qt6::Widgets ${OpenCV_LIBS} comdlg32) # # #add_executable(create_mask src/Matrox/mask.cpp) diff --git a/opencv_onnx.cpp b/opencv_onnx.cpp index 10484d5..d82fe57 100644 --- a/opencv_onnx.cpp +++ b/opencv_onnx.cpp @@ -85,8 +85,8 @@ int main() { Timer timer1; // 加载模型 cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath); - // net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // 设置为使用 CUDA 后端 - // net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // 设置为在 GPU 上运行 + net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // 设置为使用 CUDA 后端 + net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // 设置为在 GPU 上运行 timer1.printElapsedTime("Time to load the model"); // 读取输入图像 @@ -112,85 +112,86 @@ int main() { timer1.printElapsedTime("Time to preprocessing"); timer1.restart(); - // 推理模型 - cv::Mat output = net.forward(); + for(int j = 0; j <30; j++) { + // 推理模型 + cv::Mat output = net.forward(); - // 处理输出数据 - std::vector detections; - float* data = (float*)output.data; - for (int i = 0; i < 25200; ++i) { - float confidence = data[i * 6 + 4]; // 置信度 - if (confidence >= CONFIDENCE_THRESHOLD) { - // 获取检测框并映射到图像坐标 - // Remove the unnecessary multiplication - float cx = data[i * 6]; - float cy = data[i * 6 + 1]; - float w = data[i * 6 + 2]; - float h = data[i * 6 + 3]; + // 处理输出数据 + std::vector detections; + float* data = (float*)output.data; + for (int i = 0; i < 25200; ++i) { + float confidence = data[i * 6 + 4]; // 置信度 + if (confidence >= CONFIDENCE_THRESHOLD) { + // 获取检测框并映射到图像坐标 + // Remove the unnecessary multiplication + float cx = data[i * 6]; + float cy = data[i * 6 + 1]; + float w = data[i * 6 + 2]; + float h = data[i * 6 + 3]; - // If needed, adjust for differences between input image size and model input size - // Since they are the same in your case, this step can be omitted or kept as is - cx = cx * inputImage.cols / INPUT_WIDTH; - cy = cy * inputImage.rows / INPUT_HEIGHT; - w = w * inputImage.cols / INPUT_WIDTH; - h = h * inputImage.rows / INPUT_HEIGHT; + // If needed, adjust for differences between input image size and model input size + // Since they are the same in your case, this step can be omitted or kept as is + cx = cx * inputImage.cols / INPUT_WIDTH; + cy = cy * inputImage.rows / INPUT_HEIGHT; + w = w * inputImage.cols / INPUT_WIDTH; + h = h * inputImage.rows / INPUT_HEIGHT; - // Proceed with the rest of your code - int left = static_cast(cx - w / 2); - int top = static_cast(cy - h / 2); - int width = static_cast(w); - int height = static_cast(h); + // Proceed with the rest of your code + int left = static_cast(cx - w / 2); + int top = static_cast(cy - h / 2); + int width = static_cast(w); + int height = static_cast(h); - // Ensure coordinates are within image bounds - left = std::max(0, std::min(left, inputImage.cols - 1)); - top = std::max(0, std::min(top, inputImage.rows - 1)); - width = std::min(width, inputImage.cols - left); - height = std::min(height, inputImage.rows - top); + // Ensure coordinates are within image bounds + left = std::max(0, std::min(left, inputImage.cols - 1)); + top = std::max(0, std::min(top, inputImage.rows - 1)); + width = std::min(width, inputImage.cols - left); + height = std::min(height, inputImage.rows - top); - // Add detection - detections.push_back({cv::Rect(left, top, width, height), confidence}); + // Add detection + detections.push_back({cv::Rect(left, top, width, height), confidence}); + } } - } - // 非极大值抑制 - std::vector indices; - std::vector boxes; - std::vector scores; - for (const auto& detection : detections) { - boxes.push_back(detection.box); + // 非极大值抑制 + std::vector indices; + std::vector boxes; + std::vector scores; + for (const auto& detection : detections) { + boxes.push_back(detection.box); - scores.push_back(detection.confidence); - } - cv::dnn::NMSBoxes(boxes, scores, CONFIDENCE_THRESHOLD, NMS_THRESHOLD, indices); - std::cout << "Number of detections after NMS: " << indices.size() << std::endl; - if (indices.empty()) { - std::cout << "No boxes passed NMS." << std::endl; - } - for (int idx : indices) { - Detection detection = detections[idx]; - std::cout << "Drawing box at: (" << detection.box.x << ", " << detection.box.y - << "), width: " << detection.box.width << ", height: " << detection.box.height << std::endl; - drawDetections(inputImage, {detection}); - } - - std::vector finalDetections; - for (int idx : indices) { - finalDetections.push_back(detections[idx]); - } - for (int i = 0; i < 25200; ++i) { - float confidence = data[i * 6 + 4]; - if (confidence >= CONFIDENCE_THRESHOLD) { - std::cout << "Detection " << i << ": confidence=" << confidence << std::endl; + scores.push_back(detection.confidence); } + cv::dnn::NMSBoxes(boxes, scores, CONFIDENCE_THRESHOLD, NMS_THRESHOLD, indices); + std::cout << "Number of detections after NMS: " << indices.size() << std::endl; + if (indices.empty()) { + std::cout << "No boxes passed NMS." << std::endl; + } + for (int idx : indices) { + Detection detection = detections[idx]; + std::cout << "Drawing box at: (" << detection.box.x << ", " << detection.box.y + << "), width: " << detection.box.width << ", height: " << detection.box.height << std::endl; + drawDetections(inputImage, {detection}); + } + + std::vector finalDetections; + for (int idx : indices) { + finalDetections.push_back(detections[idx]); + } + for (int i = 0; i < 25200; ++i) { + float confidence = data[i * 6 + 4]; + if (confidence >= CONFIDENCE_THRESHOLD) { + // std::cout << "Detection " << i << ": confidence=" << confidence << std::endl; + } + } + + // 绘制检测框并显示图像 + drawDetections(image, finalDetections); + timer1.printElapsedTime("Time to run inference"); } - - // 绘制检测框并显示图像 - drawDetections(image, finalDetections); - timer1.printElapsedTime("Time to run inference"); - cv::imshow("Detections", inputImage); cv::waitKey(0); diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index 7b16eef..c1b2d13 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -198,10 +198,10 @@ void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map兼容 -// 配置文件当中加入是否显示参数,能调控加载模板的过程是否显示。已 -//TODO: 3修改当前的代码使模板匹配不出错 已 -//TODO: 4成立模板文件夹,能够加载文件夹下的全部模板并实现检测 已 +//TODO: 1加入加载多个模板的功能 已 + 加入配置文件 + //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); ////未实现,因为加载和寻找分开后,要对加载和寻找函数传入类成员,无法统一,其余可用到的参数统一,加一个类成员即可。 //TODO: 6完善相应部分的手册 已 diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index b7653ca..61f39a4 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -8,7 +8,7 @@ #include "Matrox/utils.h" #include "Matrox/template_matching.h" -#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\8.bmp") +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton_image_new\\357.bmp") #define SAVE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\suspect.png") From fc50c3b440f96a7f087689878a4b1cc0ff9b50cb Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Mon, 25 Nov 2024 13:32:40 +0800 Subject: [PATCH 18/19] =?UTF-8?q?=E5=B0=86=E5=8A=A0=E8=BD=BD=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E7=9A=84=E6=96=B9=E5=BC=8F=E4=BF=AE=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Matrox/template_matching.cpp | 89 ++++++++++++++++++++++++-------- src/Matrox/template_matching.h | 11 +++- tests/test_template_matching.cpp | 3 +- 3 files changed, 80 insertions(+), 23 deletions(-) diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index c1b2d13..b39bff9 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -184,28 +184,74 @@ void TemplateMatcher::findModels(const MIL_ID& inputImage,MIL_ID& outputImage) MbufFree(input_image_uint8); } -void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map ¶ms) -{ - // Create a TemplateMatcher instance (consider making it static if you want to retain it between calls) - - // Load template models only once - matcher.loadTemplates( - { - "C:\\Users\\zjc\\Desktop\\templates\\template1.png", - "C:\\Users\\zjc\\Desktop\\templates\\template2.png", - "C:\\Users\\zjc\\Desktop\\templates\\template3.png", - "C:\\Users\\zjc\\Desktop\\templates\\template4.png", - "C:\\Users\\zjc\\Desktop\\templates\\template5.png", - "C:\\Users\\zjc\\Desktop\\templates\\template6.png", - }, - {0, 0, 0, 0,0,0}, // offsetX - {0, 0, 0, 0,0,0}, // offsetY - {100, 80, 200, 96,96,96}, // sizeX - {100, 80, 86, 96,96,96}, // sizeY - {M_COLOR_RED, M_COLOR_GREEN, M_COLOR_BLUE, M_COLOR_GREEN,M_COLOR_BLUE,M_COLOR_BLUE} // drawColor - ); +std::vector splitString(const std::string& str, char delimiter) { + std::vector tokens; + std::stringstream ss(str); + std::string item; + while (std::getline(ss, item, delimiter)) { + tokens.push_back(item); + } + return tokens; } +void TemplateMatcher::loadConfig(const std::string& filename, + std::vector& template_paths, + std::vector& offsetX, + std::vector& offsetY, + std::vector& sizeX, + std::vector& sizeY, + std::vector& drawColor) { + std::ifstream file(filename); + if (!file.is_open()) { + std::cerr << "Unable to open configuration file: " << filename << std::endl; + return; + } + + std::string line; + while (std::getline(file, line)) { + auto pos = line.find('='); + if (pos == std::string::npos) continue; + + std::string key = line.substr(0, pos); + std::string value = line.substr(pos + 1); + auto values = splitString(value, ','); + + if (key == "template_paths") { + template_paths = values; + } else if (key == "offsetX") { + for (const auto& v : values) offsetX.push_back(std::stoi(v)); + } else if (key == "offsetY") { + for (const auto& v : values) offsetY.push_back(std::stoi(v)); + } else if (key == "sizeX") { + for (const auto& v : values) sizeX.push_back(std::stoi(v)); + } else if (key == "sizeY") { + for (const auto& v : values) sizeY.push_back(std::stoi(v)); + } else if (key == "drawColor") { + for (const auto& v : values) { + if (v == "M_COLOR_RED") drawColor.push_back(M_COLOR_RED); + else if (v == "M_COLOR_GREEN") drawColor.push_back(M_COLOR_GREEN); + else if (v == "M_COLOR_BLUE") drawColor.push_back(M_COLOR_BLUE); + } + } + } + file.close(); +} + +void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map& params) +{ + std::vector template_paths; + std::vector offsetX, offsetY, sizeX, sizeY; + std::vector drawColor; + + // 调用 loadConfig 并加载配置 + loadConfig("C:\\Users\\zjc\\Desktop\\config\\template_config.txt", + template_paths, offsetX, offsetY, sizeX, sizeY, drawColor); + + // 调用 matcher 的 loadTemplates 方法 + matcher.loadTemplates(template_paths, offsetX, offsetY, sizeX, sizeY, drawColor); +} + + void TemplateMatcher::FindTemplates( const MIL_ID& inputImage, MIL_ID& outputImage,TemplateMatcher& matcher) { // Perform template matching @@ -215,7 +261,8 @@ void TemplateMatcher::FindTemplates( const MIL_ID& inputImage, MIL_ID& outputIma cout << "Template matching completed.\n"; } -//TODO: 1加入加载多个模板的功能 已 + 加入配置文件 +//TODO: 1加入加载多个模板的功能 已 + 加入配置文件 已 + //TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); ////未实现,因为加载和寻找分开后,要对加载和寻找函数传入类成员,无法统一,其余可用到的参数统一,加一个类成员即可。 diff --git a/src/Matrox/template_matching.h b/src/Matrox/template_matching.h index 59b92ed..83a6dc5 100644 --- a/src/Matrox/template_matching.h +++ b/src/Matrox/template_matching.h @@ -9,6 +9,9 @@ void pre_process(const MIL_ID& inputImage, MIL_ID& outputImageSuspect, const std::map& params); // void LoadTemplate(const MIL_ID &inputImage, MIL_ID &outputImage, std::map ¶ms); +extern std::vector template_paths; +extern std::vector offsetX, offsetY, sizeX, sizeY; +extern std::vector drawColor; class TemplateMatcher { @@ -50,7 +53,13 @@ void findModels(const MIL_ID& inputImage,MIL_ID& outputImage); void FindTemplates(const MIL_ID &inputImage, MIL_ID &outputImage, TemplateMatcher &matcher); - +void loadConfig(const std::string& filename, + std::vector& template_paths, + std::vector& offsetX, + std::vector& offsetY, + std::vector& sizeX, + std::vector& sizeY, + std::vector& drawColor); // Destructor ~TemplateMatcher(); diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 61f39a4..4ab409e 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -22,7 +22,7 @@ int main() { std::map params; - read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\template_config.txt", params); + read_params_from_file("C:\\Users\\zjc\\Desktop\\config\\template_color_config.txt", params); // Initialize MIL application MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); @@ -36,6 +36,7 @@ int main() { MIL_ID detection_resize = M_NULL; + MIL_ID output_Image= M_NULL; TemplateMatcher matcher(MilSystem, MilDisplay, params); From f83d435ddcfcaddcaaff0e402b0be83523143a58 Mon Sep 17 00:00:00 2001 From: zjc-zjc-123 <1714105370@qq.com> Date: Tue, 26 Nov 2024 11:09:14 +0800 Subject: [PATCH 19/19] =?UTF-8?q?=E7=BB=9F=E4=B8=80template=E2=80=94?= =?UTF-8?q?=E2=80=94matching=E7=9A=84=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0mask=E7=9A=84=E6=B5=8B=E8=AF=95=E5=87=BD=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E5=9C=A8src=E4=B8=AD=E6=96=B0=E5=BB=BACVDL=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- opencv_onnx.cpp | 40 ++++++++++++++++++++++++++++---- src/CMakeLists.txt | 1 + src/CVDL/OnnxRunner.cpp | 5 ++++ src/CVDL/OnnxRunner.h | 16 +++++++++++++ src/Matrox/mask.cpp | 25 +------------------- src/Matrox/mask.h | 16 +++++++++++++ src/Matrox/template_matching.cpp | 31 ++++++++++++++++++------- src/Matrox/template_matching.h | 8 +++---- src/Matrox/utils.cpp | 2 ++ tests/CMakeLists.txt | 10 +++++++- tests/test_mask.cpp | 30 ++++++++++++++++++++++++ tests/test_template_matching.cpp | 6 ++--- 12 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 src/CVDL/OnnxRunner.cpp create mode 100644 src/CVDL/OnnxRunner.h create mode 100644 src/Matrox/mask.h create mode 100644 tests/test_mask.cpp diff --git a/opencv_onnx.cpp b/opencv_onnx.cpp index d82fe57..fd7769c 100644 --- a/opencv_onnx.cpp +++ b/opencv_onnx.cpp @@ -112,7 +112,7 @@ int main() { timer1.printElapsedTime("Time to preprocessing"); timer1.restart(); - for(int j = 0; j <30; j++) { + for(int j = 0; j <1; j++) { // 推理模型 cv::Mat output = net.forward(); @@ -153,9 +153,6 @@ int main() { } } - - - // 非极大值抑制 std::vector indices; std::vector boxes; @@ -192,6 +189,41 @@ int main() { drawDetections(image, finalDetections); timer1.printElapsedTime("Time to run inference"); } + int depth = inputImage.depth(); // 图像数据类型 + int channels = inputImage.channels(); // 通道数 + + // 判断图像深度和通道数,打印类型 + std::string depthStr; + switch (depth) { + case CV_8U: + depthStr = "8-bit unsigned integer"; + break; + case CV_8S: + depthStr = "8-bit signed integer"; + break; + case CV_16U: + depthStr = "16-bit unsigned integer"; + break; + case CV_16S: + depthStr = "16-bit signed integer"; + break; + case CV_32S: + depthStr = "32-bit signed integer"; + break; + case CV_32F: + depthStr = "32-bit floating point"; + break; + case CV_64F: + depthStr = "64-bit floating point"; + break; + default: + depthStr = "Unknown depth"; + break; + } + + std::cout << "Image Depth: " << depthStr << std::endl; + std::cout << "Number of Channels: " << channels << std::endl; + cv::imshow("Detections", inputImage); cv::waitKey(0); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8859a18..1d252e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(Matrox Matrox/color_range.cpp Matrox/utils.cpp Matrox/template_matching.cpp + Matrox/mask.cpp ) # 头文件路径 diff --git a/src/CVDL/OnnxRunner.cpp b/src/CVDL/OnnxRunner.cpp new file mode 100644 index 0000000..fa89f0f --- /dev/null +++ b/src/CVDL/OnnxRunner.cpp @@ -0,0 +1,5 @@ +// +// Created by zjc on 24-11-26. +// + +#include "OnnxRunner.h" diff --git a/src/CVDL/OnnxRunner.h b/src/CVDL/OnnxRunner.h new file mode 100644 index 0000000..57b2534 --- /dev/null +++ b/src/CVDL/OnnxRunner.h @@ -0,0 +1,16 @@ +// +// Created by zjc on 24-11-26. +// + +#ifndef ONNXRUNNER_H +#define ONNXRUNNER_H + + + +class OnnxRunner { + +}; + + + +#endif //ONNXRUNNER_H diff --git a/src/Matrox/mask.cpp b/src/Matrox/mask.cpp index cf0ae1b..e564bfa 100644 --- a/src/Matrox/mask.cpp +++ b/src/Matrox/mask.cpp @@ -1,7 +1,5 @@ -#include -#include -#include +#include "mask.h" // 读取二值化的单通道一位图片并生成掩膜 std::vector> generateMaskFromImage(const std::string& imagePath, int widthBlocks, int heightBlocks, int threshold = 10) { // 读取图像 @@ -52,25 +50,4 @@ std::vector> generateMaskFromImage(const std::string& imagePat return mask; } -int main() { - // 指定图像路径 - std::string imagePath = "C:\\Users\\zjc\\Desktop\\diguandai.png"; - // 设置分块数量和白色像素点阈值 - int widthBlocks = 24; - int heightBlocks = 24; - int threshold = 20; - - // 生成掩膜 - std::vector> mask = generateMaskFromImage(imagePath, widthBlocks, heightBlocks, threshold); - - // 打印掩膜结果 - for (int i = 0; i < heightBlocks; ++i) { - for (int j = 0; j < widthBlocks; ++j) { - std::cout << (mask[i][j] ? "1 " : "0 "); - } - std::cout << std::endl; - } - - return 0; -} diff --git a/src/Matrox/mask.h b/src/Matrox/mask.h new file mode 100644 index 0000000..fee2b3e --- /dev/null +++ b/src/Matrox/mask.h @@ -0,0 +1,16 @@ +// +// Created by zjc on 24-11-26. +// + + +#ifndef MASK_H +#define MASK_H + +#include +#include +#include + +std::vector> generateMaskFromImage(const std::string& imagePath, int widthBlocks, int heightBlocks, int threshold); + + +#endif //MASK_H diff --git a/src/Matrox/template_matching.cpp b/src/Matrox/template_matching.cpp index b39bff9..bf6132b 100644 --- a/src/Matrox/template_matching.cpp +++ b/src/Matrox/template_matching.cpp @@ -237,7 +237,7 @@ void TemplateMatcher::loadConfig(const std::string& filename, file.close(); } -void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::map& params) +void TemplateMatcher::LoadTemplate(std::map& params) { std::vector template_paths; std::vector offsetX, offsetY, sizeX, sizeY; @@ -245,26 +245,39 @@ void TemplateMatcher::LoadTemplate(TemplateMatcher& matcher, std::maploadTemplates(template_paths, offsetX, offsetY, sizeX, sizeY, drawColor); } -void TemplateMatcher::FindTemplates( const MIL_ID& inputImage, MIL_ID& outputImage,TemplateMatcher& matcher) +void TemplateMatcher::FindTemplates( const MIL_ID& inputImage, MIL_ID& outputImage,const std::map ¶ms) { // Perform template matching - matcher.findModels(inputImage,outputImage); + this -> findModels(inputImage,outputImage); // Notify user that matching is complete cout << "Template matching completed.\n"; } -//TODO: 1加入加载多个模板的功能 已 + 加入配置文件 已 -//TODO: 5制作标准结构的函数,例如:matcher.findModels(MIL_ID inputImage, MIL_ID output_image, map); -////未实现,因为加载和寻找分开后,要对加载和寻找函数传入类成员,无法统一,其余可用到的参数统一,加一个类成员即可。 -//TODO: 6完善相应部分的手册 已 + +// TODO: Opencv ONNX runner, +// 1. 构建相应的模型加载和模型运行函数 +// 2. 在src里头添加另一个cvdl库,专用于视觉深度学习 +// 3. 添加一个类OnnxRunner + +// TODO: 完善config文件,确保能够读取mask转换的相关参数 + +// TODO: Opencv和matrox图像的转换函数,添加到Matrox/utils.cpp + +// TODO:构建统一的图像检测器类,可以一键加载,一键开启多进程快速预测 + +// TODO:计算统一预测框架的预测时间 + +// TODO: 完善模板和参数,添加陈棉模块,陈棉模块可通过配置进行启用和关闭。 + +//TODO: 完善相应部分的手册 已 diff --git a/src/Matrox/template_matching.h b/src/Matrox/template_matching.h index 83a6dc5..00f8e88 100644 --- a/src/Matrox/template_matching.h +++ b/src/Matrox/template_matching.h @@ -47,13 +47,13 @@ public: const std::vector& drawColor); // Search for models in the input image -void findModels(const MIL_ID& inputImage,MIL_ID& outputImage); + void findModels(const MIL_ID& inputImage,MIL_ID& outputImage); - void LoadTemplate(TemplateMatcher &matcher, std::map ¶ms); + void LoadTemplate(std::map ¶ms); - void FindTemplates(const MIL_ID &inputImage, MIL_ID &outputImage, TemplateMatcher &matcher); + void FindTemplates(const MIL_ID &inputImage, MIL_ID &outputImage,const std::map ¶ms); -void loadConfig(const std::string& filename, + void loadConfig(const std::string& filename, std::vector& template_paths, std::vector& offsetX, std::vector& offsetY, diff --git a/src/Matrox/utils.cpp b/src/Matrox/utils.cpp index 31b3f0e..fdde47a 100644 --- a/src/Matrox/utils.cpp +++ b/src/Matrox/utils.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace std; @@ -120,3 +121,4 @@ void read_params_from_file(const std::string& filename, std::map> mask = generateMaskFromImage(imagePath, widthBlocks, heightBlocks, threshold); + + // 打印掩膜结果 + for (int i = 0; i < heightBlocks; ++i) { + for (int j = 0; j < widthBlocks; ++j) + { + std::cout << (mask[i][j] ? "1 " : "0 "); + } + std::cout << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/tests/test_template_matching.cpp b/tests/test_template_matching.cpp index 4ab409e..fb2e568 100644 --- a/tests/test_template_matching.cpp +++ b/tests/test_template_matching.cpp @@ -49,9 +49,9 @@ int main() { M_IMAGE + M_PROC, &detection_resize); MimResize(detection_result,detection_resize,0.5,0.5,M_DEFAULT); - matcher.LoadTemplate(matcher,params); - matcher.FindTemplates(detection_resize,output_Image,matcher); - //最后的释放问题应该出在寻找模板里面 + matcher.LoadTemplate(params); + matcher.FindTemplates(detection_resize,output_Image,params); + }); MbufSave(SAVE_PATH, detection_result); // Display result