diff --git a/.gitignore b/.gitignore index 8bf2fea..8700afa 100644 --- a/.gitignore +++ b/.gitignore @@ -364,3 +364,5 @@ FodyWeavers.xsd .idea cmake-build-* + +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index a468303..299634d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,13 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.29) project(cotton_color) set(CMAKE_CXX_STANDARD 17) +add_definitions(-DUNICODE -D_UNICODE) + # 设置 OpenCV 路径 if(DEFINED ENV{OpenCV_DIR}) - set(OpenCV_DIR $ENV{OpenCV_DIR}) + set(OpenCV_DIR ENV{OpenCV_DIR}) message(STATUS "OpenCV_DIR set from environment variable: ${OpenCV_DIR}") else() message(FATAL_ERROR "OpenCV_DIR is not set. Please set the OpenCV_DIR environment variable.") @@ -17,7 +19,7 @@ include_directories(${OpenCV_INCLUDE_DIRS}) # 设置 Qt 路径 if(DEFINED ENV{Qt6_DIR}) - set(Qt6_DIR $ENV{Qt6_DIR}) + set(Qt6_DIR ENV{Qt6_DIR}) message(STATUS "Qt6_DIR set from environment variable: ${Qt6_DIR}") else() message(FATAL_ERROR "Qt6_DIR is not set. Please set the Qt6_DIR environment variable.") @@ -29,21 +31,35 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) +#配置mil库 +include_directories(E:/QTexamble/matrox/Include) +# 添加 MIL 库的库文件路径 +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}) +target_link_libraries(cotton_color Qt6::Widgets ${OpenCV_LIBS} comdlg32) # 添加可执行文件 cotton_color add_executable(cotton_range Matrox/color_range.cpp) # 链接 OpenCV 和 Qt 库 -target_link_libraries(cotton_range Qt6::Widgets ${OpenCV_LIBS}) +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}) -add_executable(color_matching Matrox/template_matching.cpp - Matrox/onnx_running.cpp - Matrox/onnx_running.h) +target_link_libraries(cotton_color2 Qt6::Widgets ${OpenCV_LIBS} ${MIL_LIBS}) + +add_executable(color_matching Matrox/template_matching.cpp) +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}) \ No newline at end of file diff --git a/Matrox/README.md b/Matrox/README.md new file mode 100644 index 0000000..0932f19 --- /dev/null +++ b/Matrox/README.md @@ -0,0 +1,8 @@ +# MIL库环境配置 + +include_directories(E:/QTexamble/matrox/Include) +将路径修改为你的安装目录 .../Matrox Imaging/MIL/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 diff --git a/Matrox/color_range.cpp b/Matrox/color_range.cpp index 9eee56e..e4d93ef 100644 --- a/Matrox/color_range.cpp +++ b/Matrox/color_range.cpp @@ -1,3 +1,204 @@ // // Created by zjc on 24-11-12. // + +#include +#include +#include +#define IMAGE_PATH MIL_TEXT("C:\\Users\\zjc\\Desktop\\cotton2.bmp") + +// 全局变量,方便在各个函数中使用 +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) +{ + 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; + + // 检查输入图像的通道数 + MIL_INT NumBands = 0; + MbufInquire(inputImage, M_SIZE_BAND, &NumBands); + if (NumBands != 3) + { + printf("输入图像不是 3 通道图像,请提供彩色图像。\n"); + 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); + + // 将图像从 sRGB 转换到 Lab + MimConvert(inputImage, MilLabImage, M_SRGB_TO_LAB); + + // 创建 Lab 通道的子缓冲区 + 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); + + // 对每个通道进行阈值分割 + MimBinarize(MilLChannel, MilBinaryL, M_IN_RANGE, lowerL, upperL); + MimBinarize(MilAChannel, MilBinaryA, M_IN_RANGE, lowerA, upperA); + MimBinarize(MilBChannel, MilBinaryB, M_IN_RANGE, lowerB, upperB); + + // 分配输出图像缓冲区 + 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); + + // 将结果合并 + MimArith(MilBinaryL, MilBinaryA, outputImageLab, M_AND); + MimArith(outputImageLab, MilBinaryB, outputImageLab, M_AND); + + // 释放资源 + MbufFree(MilBinaryL); + MbufFree(MilBinaryA); + MbufFree(MilBinaryB); + MbufFree(MilLChannel); + MbufFree(MilAChannel); + MbufFree(MilBChannel); + MbufFree(MilLabImage); +} + +// HSVProcess 函数,支持通过参数控制饱和度阈值,提供默认值 +void HSVProcess(MIL_ID& inputImage, MIL_ID& outputImageHSV, MIL_DOUBLE saturationThreshold = 120.0) +{ + MIL_ID MilHSVImage = M_NULL, MilHChannel = M_NULL, MilSChannel = M_NULL, MilVChannel = M_NULL; + + // 检查输入图像的通道数 + MIL_INT NumBands = 0; + MbufInquire(inputImage, M_SIZE_BAND, &NumBands); + if (NumBands != 3) + { + printf("输入图像不是 3 通道图像,请提供彩色图像。\n"); + return; + } + + // 分配用于存储 HSV 图像的缓冲区 + 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, + &MilHSVImage); + + // 将图像从 sRGB 转换到 HSV + MimConvert(inputImage, MilHSVImage, M_RGB_TO_HSV); + + // 创建 HSV 通道的子缓冲区 + MbufChildColor(MilHSVImage, 0, &MilHChannel); + MbufChildColor(MilHSVImage, 1, &MilSChannel); + MbufChildColor(MilHSVImage, 2, &MilVChannel); + + // 分配输出图像缓冲区 + 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, saturationThreshold, M_NULL); + + // 释放资源 + MbufFree(MilHChannel); + MbufFree(MilSChannel); + MbufFree(MilVChannel); + 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; + + // 调用 LabProcess + LabProcess(inputImage, MilResultLab, lowerL, upperL, lowerA, upperA, lowerB, upperB); + + // 调用 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); + + // 合并 Lab 和 HSV 的结果(取“或”运算) + MimArith(MilResultLab, MilResultHSV, MilCombinedResult, M_OR); + + //// 显示合并后的结果图像 + MdispSelect(MilDisplay, MilCombinedResult); + + //// 等待用户查看处理后的图像 + printf("图像已处理并合并,按下 退出程序。\n"); + getchar(); + + // 释放资源 + MbufFree(MilResultLab); + MbufFree(MilResultHSV); + MbufFree(MilCombinedResult); +} + + +int main() +{ + 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); + }); + + + // 释放资源 + MbufFree(MilImage); + MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); + + return 0; +} \ No newline at end of file diff --git a/Matrox/onnx_running.cpp b/Matrox/onnx_running.cpp index b545f1f..c5e6892 100644 --- a/Matrox/onnx_running.cpp +++ b/Matrox/onnx_running.cpp @@ -1,5 +1,139 @@ // -// Created by zjc on 24-11-12. +// Created by zjc on 24-11-13. // #include "onnx_running.h" + + +#include +//#include // 添加此行 +#include +#include +#include +#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") + +int MosMain(void) +{ + MIL_ID MilApplication = M_NULL, // MIL application identifier + MilSystem = M_NULL, // MIL system identifier + MilDisplay = M_NULL, // MIL display identifier + MilImage = M_NULL, // MIL image identifier + MilDetectedImage = M_NULL, // MIL image with detections + DetectCtx = M_NULL, // MIL ONNX detection context + DetectRes = M_NULL; // MIL detection result + // Allocate MIL objects. + MappAlloc(M_NULL, M_DEFAULT, &MilApplication); + 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) + { + MosPrintf(MIL_TEXT("Image loaded successfully.\n")); + } + else + { + MosPrintf(MIL_TEXT("Failed to load image.\n")); + return 1; // Exit if the image loading failed + } + + MdispSelect(MilDisplay, MimArithDestination); + + // MbufInquire(MilImage, , NULL); + + // Import the YOLOv5 ONNX model into the detection context. + MosPrintf(MIL_TEXT("Importing the YOLOv5 ONNX model into the detection context...\n")); + MclassAlloc(MilSystem, M_CLASSIFIER_ONNX, M_DEFAULT, &DetectCtx); + MclassImport(EXAMPLE_ONNX_MODEL_PATH, M_ONNX_FILE, DetectCtx, M_DEFAULT, M_DEFAULT, M_DEFAULT); + MosPrintf(MIL_TEXT("Model imported successfully.\n")); + + // Preprocess the detection context. + MclassPreprocess(DetectCtx, M_DEFAULT); // Ensure the context is preprocessed. + + // Allocate a detection result buffer. + MclassAllocResult(MilSystem, M_PREDICT_ONNX_RESULT, M_DEFAULT, &DetectRes); + + + + // Perform object detection on the image using MclassPredict. + MclassPredict(DetectCtx, MimArithDestination, DetectRes, M_DEFAULT); + + + MosPrintf(MIL_TEXT("Object detection completed.\n")); + + // Allocate a buffer for displaying the detection results. + MbufAlloc2d(MilSystem, 640, 640, 32 + M_FLOAT, M_IMAGE + M_PROC+M_DISP, &MilDetectedImage); + + + MosPrintf(MIL_TEXT("Detected object detection completed.\n")); + + // Retrieve and draw the detection results manually. + MIL_FLOAT NumDetections = 0; + + MclassGetResult(DetectRes, M_GENERAL, M_NUMBER_OF_OUTPUTS, &NumDetections); + + if (NumDetections > 0) + { + for (MIL_INT i = 0; i < NumDetections; i++) + { + MIL_DOUBLE Score; + MIL_INT ClassIndex; + MIL_DOUBLE BBoxX, BBoxY, BBoxWidth, BBoxHeight; + + // Retrieve detection results for each object. + MclassGetResult(DetectRes, i, M_SCORE + M_TYPE_MIL_DOUBLE, &Score); + MclassGetResult(DetectRes, i, M_INDEX + M_TYPE_MIL_INT, &ClassIndex); + MclassGetResult(DetectRes, i, M_SEED_VALUE + M_TYPE_MIL_DOUBLE, &BBoxX); + MclassGetResult(DetectRes, i, M_SEED_VALUE + M_TYPE_MIL_DOUBLE, &BBoxY); + MclassGetResult(DetectRes, i, M_SEED_VALUE + M_TYPE_MIL_DOUBLE, &BBoxWidth); + MclassGetResult(DetectRes, i, M_SEED_VALUE + M_TYPE_MIL_DOUBLE, &BBoxHeight); + + // Draw bounding box. + MgraColor(M_DEFAULT, M_COLOR_GREEN); + MgraRect(M_DEFAULT, MilDetectedImage, BBoxX, BBoxY, BBoxX + BBoxWidth, BBoxY + BBoxHeight); + + // Optionally, display detection score or class name (if needed). + MIL_TEXT_CHAR Label[256]; + MosSprintf(Label, 256, MIL_TEXT("Class %d: %.2lf%%"), ClassIndex, Score * 100); + MgraFont(M_DEFAULT, M_FONT_DEFAULT_SMALL); + MgraText(M_DEFAULT, MilDetectedImage, BBoxX, BBoxY - 10, Label); + } + } + else + { + MosPrintf(MIL_TEXT("No detections found.\n")); + } + + // Display the image with detection results. + // MdispSelect(MilDisplay, MilDetectedImage); + + // Wait for the user to close the window. + MosPrintf(MIL_TEXT("Press to exit.\n")); + MosGetch(); + + // Free all allocated resources. + MbufFree(MilImage); + MbufFree(MilDetectedImage); + MclassFree(DetectRes); + MclassFree(DetectCtx); + MdispFree(MilDisplay); + MsysFree(MilSystem); + MappFree(MilApplication); + + return 0; +} + diff --git a/Matrox/onnx_running.h b/Matrox/onnx_running.h index 3b81150..e6bf470 100644 --- a/Matrox/onnx_running.h +++ b/Matrox/onnx_running.h @@ -1,8 +1,16 @@ // -// Created by zjc on 24-11-12. +// Created by zjc on 24-11-13. // #ifndef ONNX_RUNNING_H #define ONNX_RUNNING_H + + +class onnx_running { + +}; + + + #endif //ONNX_RUNNING_H diff --git a/Matrox/template_matching.cpp b/Matrox/template_matching.cpp index 9eee56e..ededb56 100644 --- a/Matrox/template_matching.cpp +++ b/Matrox/template_matching.cpp @@ -1,3 +1,222 @@ -// -// Created by zjc on 24-11-12. -// + + +#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/ui.cpp b/Matrox/ui.cpp new file mode 100644 index 0000000..39d3a66 --- /dev/null +++ b/Matrox/ui.cpp @@ -0,0 +1,14 @@ +// +// Created by zjc on 24-11-12. +// + +#include "ui.h" +#include +#include + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + QPushButton button("Hello, Qt!"); + button.show(); + return app.exec(); +} \ No newline at end of file diff --git a/Matrox/ui.h b/Matrox/ui.h new file mode 100644 index 0000000..f7b9caa --- /dev/null +++ b/Matrox/ui.h @@ -0,0 +1,8 @@ +// +// Created by zjc on 24-11-12. +// + +#ifndef UI_H +#define UI_H + +#endif //UI_H diff --git a/README.md b/README.md index e4f166e..dcb2f73 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,41 @@ -# Cotton Color +# Cotton Color -## 颜色检测 +[TOC] -### 艳丽色彩检测 +## 算法整体框架 + +### 颜色检测 + +#### 艳丽色彩检测 纯色彩检测就可以。饱和度检测。 思路:rgb -> HSV -> s -> threshold -> 杂质 -### 黑色检测/滴灌带检测 +#### 黑色检测/滴灌带检测 L a* b* 色彩空间检测,纯黑色就是杂质,但是容易有噪声。 思路:rgb -> La*b* -> threshold -> 黑色 -> 模板匹配 -> 物体的大小 -> 阈值判断 -> 杂质 -### 暗黄色检测/油棉 +#### 暗黄色检测/油棉 L a* b* 色彩空间检测,检测暗黄色。 思路:rgb -> La*b* -> threshold -> 暗黄色 -> 模板匹配 -> 物体的大小 -> 阈值判断 -> 杂质 -### 带土地膜检测 +#### 带土地膜检测 L a* b* 色彩空间检测,检测明黄色、白色。 思路:rgb -> La*b* -> threshold -> 白色、明黄色 -> 模板匹配 -> 物体的大小 -> 阈值判断 -> 杂质 -## 深度学习检测 +### 深度学习检测 需求:模板匹配缺少对于纹理的判断,所以要加上深度学习对于各个杂质进行确认。 -### 方案1:端到端式的方案 +#### 方案1:端到端式的方案 传统思路:rgb -> La*b* -> threshold -> 白色、明黄色 -> 模板匹配 -> 物体的大小 -> 阈值判断 -> 杂质 @@ -40,7 +44,7 @@ L a* b* 色彩空间检测,检测明黄色、白色。 -> YOLO -> 杂质 -### 方案2:验证形式的方案 +#### 方案2:验证形式的方案 传统思路:rgb -> La*b* -> threshold -> 白色、明黄色 -> 模板匹配 -> 物体的大小 -> 阈值判断 -> 杂质 @@ -50,7 +54,7 @@ L a* b* 色彩空间检测,检测明黄色、白色。 | 保守方案 -> 深度学习确认 -> 杂质 -#### 讨论记录: +##### 讨论记录: 暗红色(棉叶) @@ -60,43 +64,50 @@ L a* b* 色彩空间检测,检测明黄色、白色。 土黄 -### 安装记录 +## 安装记录 -1. OpenCV安装 +### OpenCV安装 下载OpenCV并设置OpenCV_DIR到环境变量,例如: -在 Windows 上 -打开“控制面板” > “系统和安全” > “系统”。 -点击左侧的“高级系统设置”。 -在“系统属性”窗口中,点击“环境变量”。 -在“系统变量”或“用户变量”中,点击“新建”。 -输入变量名 OpenCV_DIR,在变量值中输入 OpenCV 安装的路径,例如 C:\opencv\build。 -点击“确定”保存更改。 +**在 Windows 上** -在 macOS 或 Linux 上 -打开终端。 +1. 打开“控制面板” > “系统和安全” > “系统”。 +2. 点击左侧的“高级系统设置”。 +3. 在“系统属性”窗口中,点击“环境变量”。 +4. 在“系统变量”或“用户变量”中,点击“新建”。 +5. 输入变量名 OpenCV_DIR,在变量值中输入 OpenCV 安装的路径,例如 C:\opencv\build。 +6. 点击“确定”保存更改。 -编辑您的 shell 配置文件(例如 ~/.bashrc, ~/.zshrc 或 ~/.bash_profile): +**在 macOS 或 Linux 上** -bash -复制代码 +1. 打开终端。 +2. 编辑您的 shell 配置文件(例如 `~/.bashrc`, `~/.zshrc` 或 `~/.bash_profile`): + +```bash export OpenCV_DIR=/path/to/opencv/build -将 /path/to/opencv/build 替换为 OpenCV 安装路径。 +``` + +将 `/path/to/opencv/build` 替换为 OpenCV 安装路径。 保存文件后,运行以下命令使更改生效: -bash -复制代码 +```bash source ~/.bashrc # 或者使用 `source ~/.zshrc` 根据您的 shell 类型 +``` + 完成这些步骤后,CMake 应该可以在运行时读取 OpenCV_DIR 变量,确保您的路径正确指向 OpenCV 安装目录的 build 文件夹。 -2. Qt安装 +### Qt安装 -将 DLL 添加到环境变量 PATH -为了让应用程序运行时找到 Qt6Widgets.dll,需要将 Qt 的 bin 目录添加到 PATH 环境变量中: +**让机器能够访问dll:** -打开“开始”菜单,搜索“环境变量”并打开“编辑系统环境变量”。 -在“系统变量”中找到 PATH,选择并点击“编辑”。 -点击“新建”,将 Qt 的 bin 目录路径(例如 E:\QT\6.8.0\msvc2019_64\bin)添加进去。 -点击“确定”并保存更改。 \ No newline at end of file +1. 将 DLL 添加到环境变量 PATH +2. 为了让应用程序运行时找到 Qt6Widgets.dll,需要将 Qt 的 bin 目录添加到 PATH 环境变量中: + +**让编译器能够找到编译路径:** + +1. 打开“开始”菜单,搜索“环境变量”并打开“编辑系统环境变量”。 +2. 在“系统变量”中找到 PATH,选择并点击“编辑”。 +3. 点击“新建”,将 Qt 的 bin 目录路径(例如 `E:\QT\6.8.0\msvc2019_64\bin`)添加进去。 +4. 点击“确定”并保存更改。 \ No newline at end of file diff --git a/cotton_color.cpp b/cotton_color.cpp index f8624bb..28c80f3 100644 --- a/cotton_color.cpp +++ b/cotton_color.cpp @@ -3,79 +3,92 @@ #include #include #include -#include // ļԻصĺ +#include // 包含文件对话框相关的函数 using namespace cv; using namespace std; /** - * @brief ɫʼ⺯ͨͶֵͼ޵ɫ + * @brief 鲜艳绿色检测函数,通过指定的 Lab 色彩范围检测输入图像中的绿色区域。 * - * @param inputImage ͼΪ cv::MatҪΪ BGR ɫʿռ䡣 - * @param outputImage ͼΪ cv::Matͼ񽫱dzɫԭʼͼߴ硣 - * @param params ӳ䣬ڴݸֿõIJ籥Ͷֵȡ + * @param inputImage 输入图像,类型为 cv::Mat,要求为 BGR 色彩空间。 + * @param outputImage 输出图像,类型为 cv::Mat,输出图像将包含检测到的绿色区域。 + * @param params 参数映射,用于传递各种可配置的参数,如绿色阈值等。 */ +void vibrantGreenDetection(const Mat& inputImage, Mat& outputImage, const map& params) { + // 从参数映射中获取绿色阈值 + int green = params.at("green"); + + // 将输入图像从 BGR 转换为 Lab + Mat lab_image; + cvtColor(inputImage, lab_image, cv::COLOR_BGR2Lab); + + // 定义偏绿色的 Lab 范围(具体值可能需要调整) + Scalar lower_green_lab(101, 101, 95); + Scalar upper_green_lab(135, 120, green); + + // 创建掩膜 + Mat mask_lab; + inRange(lab_image, lower_green_lab, upper_green_lab, mask_lab); + + // 通过掩膜提取偏绿色部分,将结果存储在 outputImage 中 + bitwise_and(inputImage, inputImage, outputImage, mask_lab); +} void vibrantColorDetection(const Mat& inputImage, Mat& outputImage, const map& params) { - // ӲӳлȡͶֵ + // 从参数映射中获取饱和度阈值 int saturationThreshold = params.at("saturationThreshold"); - // ͼ BGR תΪ HSV + // 将输入图像从 BGR 转换为 HSV Mat hsvImage; cvtColor(inputImage, hsvImage, COLOR_BGR2HSV); - // HSV ͼĸͨ + // 分离 HSV 图像的各个通道 Mat channels[3]; split(hsvImage, channels); - // ȡͶͨ (S) + // 获取饱和度通道 (S) Mat saturation = channels[1]; - // ͼ񣬽ͶȴֵΪ + // 创建输出图像,将饱和度大于阈值的区域标记为杂质 outputImage = Mat::zeros(inputImage.size(), CV_8UC1); - // ԱͶͼӦֵ + // 对饱和度图像应用阈值处理 threshold(saturation, outputImage, saturationThreshold, 255, THRESH_BINARY); } - -/** - * @brief ļԻ򣬷ѡļ· - * - * @return ѡļ·Ϊ std::wstringûȡѡ񣬷ؿַ - */ std::wstring openFileDialog() { - // ʼļѡԻ - OPENFILENAMEW ofn; // ʹÿַ汾Ľṹ - wchar_t szFile[260] = {0}; // 洢ѡļ· + // 初始化文件选择对话框 + OPENFILENAMEW ofn; // 使用宽字符版本的结构 + wchar_t szFile[260] = {0}; // 存储选择的文件路径 - // OPENFILENAMEW ṹĬֵ + // 设置 OPENFILENAMEW 结构的默认值 ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; - ofn.lpstrFile = szFile; // ļ· + ofn.lpstrFile = szFile; // 设置文件路径缓冲区 ofn.nMaxFile = sizeof(szFile) / sizeof(szFile[0]); ofn.lpstrFilter = L"Image Files\0*.BMP;*.JPG;*.JPEG;*.PNG;*.GIF\0All Files\0*.*\0"; ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; // Ҫļ + ofn.lpstrFileTitle = NULL; // 不需要单独的文件名 ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; // ʹĬϳʼĿ¼ - ofn.lpstrTitle = L"Select an image file"; // Ի + ofn.lpstrInitialDir = NULL; // 使用默认初始目录 + ofn.lpstrTitle = L"Select an image file"; // 对话框标题 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - // ļѡԻ + // 打开文件选择对话框 if (GetOpenFileNameW(&ofn) == TRUE) { - return szFile; // ѡеļ· + return szFile; // 返回选中的文件路径 } - return L""; // ûȡؿַ + return L""; // 如果用户取消,返回空字符串 } /** - * @brief ȡͼļ֧ Unicode · + * @brief 读取图像文件,支持 Unicode 路径。 * - * @return صͼΪ cv::Matʧܣؿյ Mat + * @return 加载的图像,类型为 cv::Mat。如果加载失败,返回空的 Mat。 */ Mat readImage() { - // ȡͼ· + // 读取输入图像路径 std::wstring imagePath = openFileDialog(); if (imagePath.empty()) { @@ -83,14 +96,14 @@ Mat readImage() { return Mat(); } - // ʹ Windows API ļ + // 使用 Windows API 打开文件 HANDLE hFile = CreateFileW(imagePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { wcout << L"Error: Could not open file." << endl; return Mat(); } - // ȡļС + // 获取文件大小 LARGE_INTEGER fileSize; if (!GetFileSizeEx(hFile, &fileSize)) { wcout << L"Error: Could not get file size." << endl; @@ -106,7 +119,7 @@ Mat readImage() { DWORD dwFileSize = static_cast(fileSize.QuadPart); - // ȡļݵ + // 读取文件内容到缓冲区 std::vector buffer(dwFileSize); DWORD bytesRead = 0; if (!ReadFile(hFile, buffer.data(), dwFileSize, &bytesRead, NULL) || bytesRead != dwFileSize) { @@ -117,7 +130,7 @@ Mat readImage() { CloseHandle(hFile); - // ʹ OpenCV ڴ滺ȡͼ + // 使用 OpenCV 从内存缓冲区读取图像 Mat image = imdecode(buffer, IMREAD_COLOR); if (image.empty()) { @@ -128,8 +141,21 @@ Mat readImage() { return image; } +// 辅助函数,用于调整图像大小并显示,支持等比例放大 +void showImage(const string& windowName, const Mat& img, double scaleFactor = 1.0) { + Mat resizedImg; + int newWidth = static_cast(img.cols * scaleFactor); + int newHeight = static_cast(img.rows * scaleFactor); + + // 调整图像大小 + resize(img, resizedImg, Size(newWidth, newHeight)); + + // 显示图像 + imshow(windowName, resizedImg); +} + int main() { - // ȡͼ + // 读取输入图像 Mat inputImage = readImage(); if (inputImage.empty()) { @@ -137,21 +163,24 @@ int main() { return -1; } - // ͼ + // 创建输出图像 Mat outputImage; - // ʹ map ģ + // 使用 map 模拟 JSON 参数传递 map params; - params["saturationThreshold"] = 100; // ñͶֵΪ 100 + params["green"] = 134; // 设置绿色阈值 - // ɫ⺯ - vibrantColorDetection(inputImage, outputImage, params); + // 调用鲜艳绿色检测函数 + vibrantGreenDetection(inputImage, outputImage, params); - // ʾԭͼͼ⵽ - imshow("Original Image", inputImage); - imshow("Detected Vibrant Colors", outputImage); + // 定义缩放因子,1.0 表示原始大小,>1.0 表示放大,<1.0 表示缩小 + double scaleFactor = 0.6; // 将图像放大1.5倍 - // ȴû + // 显示原图和检测到的绿色区域,使用缩放因子 + showImage("Original Image", inputImage, scaleFactor); + showImage("Detected Vibrant Green", outputImage, scaleFactor); + + // 等待用户按键 waitKey(0); return 0; } diff --git a/cotton_color2.cpp b/cotton_color2.cpp index c6ab671..5de3194 100644 --- a/cotton_color2.cpp +++ b/cotton_color2.cpp @@ -142,7 +142,7 @@ int main() { // 使用 map 模拟参数传递 map params; - params["saturationThreshold"] = 100; // 设置饱和度阈值为 100 + params["saturationThreshold"] = 134; // 设置饱和度阈值为 100 // 调用鲜艳颜色检测函数 vibrantColorDetection(inputImage, outputImage, params); diff --git a/doc/MatroxQ&A.assets/image-20241113112631605.png b/doc/MatroxQ&A.assets/image-20241113112631605.png new file mode 100644 index 0000000..7e79fec Binary files /dev/null and b/doc/MatroxQ&A.assets/image-20241113112631605.png differ diff --git a/doc/MatroxQ&A.md b/doc/MatroxQ&A.md index 162f631..71d7fb4 100644 --- a/doc/MatroxQ&A.md +++ b/doc/MatroxQ&A.md @@ -1,19 +1,24 @@ # Matrox 问题整理 ## 如何进行模板匹配 -问题详情: +问题详情: 如何正确设置匹配方式的参数(文件打不开,参数无效等). 问题回答: ## 模板匹配时模板如何载入 -问题详情: - -问题回答: +问题详情:如何使用我们自己的rgb图像进行模板匹配(模板和检测图片的导入以及模板的定义),例如一下警告: +![img.png](img.png) +![img_1.png](img_1.png) +问题回答: ## 如何调用ONNX -问题详情: +问题详情:如何使用加载的onnx执行目标检测和分类任务(如何进行推理)。 + +另外, +1. onnx模型在gpu上跑还是在CPU上跑 +2. 是单个模型处理6个相机的图片,一起拼起来进模型然后出结果快,还是串行的进模型推理快。 问题回答: diff --git a/doc/img.png b/doc/img.png new file mode 100644 index 0000000..4e6499e Binary files /dev/null and b/doc/img.png differ diff --git a/doc/img_1.png b/doc/img_1.png new file mode 100644 index 0000000..4b908ca Binary files /dev/null and b/doc/img_1.png differ