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] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8C=B9=E9=85=8D=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=8F=AF=E4=BB=A5=E6=98=BE=E7=A4=BA=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=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;