#include <mil.h>
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n"));
MosPrintf(MIL_TEXT("PCBModelMatching\n\n"));
MosPrintf(MIL_TEXT("[SYNOPSIS]\n"));
MosPrintf(MIL_TEXT("This example uses advanced grayscale pattern matching settings\n"));
MosPrintf(MIL_TEXT("to improve the search robustness of models with fine structures.\n"));
MosPrintf(MIL_TEXT("The settings used are pyramid level and angular tolerance, which\n"));
MosPrintf(MIL_TEXT("are set to advanced automatic modes.\n\n"));
MosPrintf(MIL_TEXT("[MODULES USED]\n"));
MosPrintf(MIL_TEXT("Modules used: application, system, display, pattern matching.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
void FindWithAutoFirstLevel(MIL_ID MilSystem, MIL_ID MilDisplay);
void BenchCompareWithAutoFirstLevel(MIL_ID MilSystem, MIL_ID MilDisplay);
void FindWithAutoAngleTolerance(MIL_ID MilSystem, MIL_ID MilDisplay);
void Restore(MIL_CONST_TEXT_PTR ModelSrcFilename, MIL_CONST_TEXT_PTR TargetSrcFilename,
MIL_ID System, MIL_ID *pParentImage, MIL_ID *pModelChild, MIL_ID *pTargetChild);
void GetOverlayChilds(MIL_ID Display, MIL_ID ParentImage, MIL_ID ModelChild, MIL_ID TargetChild,
MIL_ID *pModelOverlay, MIL_ID *pTargetOverlay);
#define EXAMPLE_IMAGE_PATH M_IMAGE_PATH MIL_TEXT("PCBModelMatching/")
static const MIL_INT MAX_CHAR_LENGTH = 256;
static MIL_CONST_TEXT_PTR SOURCE_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("PCBsource.mim");
static MIL_CONST_TEXT_PTR TARGET_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("PCBtarget.mim");
static MIL_CONST_TEXT_PTR CO_SOURCE_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("PCBrotSource.mim");
static MIL_CONST_TEXT_PTR CO_TARGET_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("PCBrotTarget.mim");
static const MIL_INT MODEL1_OFFSET_X = 45;
static const MIL_INT MODEL1_OFFSET_Y = 88;
static const MIL_INT MODEL2_OFFSET_X = 193;
static const MIL_INT MODEL2_OFFSET_Y = 22;
static const MIL_INT MODEL_SIZE_X = 111;
static const MIL_INT MODEL_SIZE_Y = 100;
static const MIL_INT CO_MODEL_OFFSET_X = 12;
static const MIL_INT CO_MODEL_OFFSET_Y = 111;
static const MIL_INT CO_MODEL_SIZE_X = 188;
static const MIL_INT CO_MODEL_SIZE_Y = 36;
static const MIL_INT MARGIN_Y = 10;
int MosMain(void)
{
MIL_ID MilApplication,
MilSystem,
MilDisplay;
MappAlloc(M_NULL, M_DEFAULT, &MilApplication);
MsysAlloc(M_DEFAULT, M_SYSTEM_HOST, M_DEFAULT, M_DEFAULT, &MilSystem);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
PrintHeader();
FindWithAutoFirstLevel(MilSystem, MilDisplay);
BenchCompareWithAutoFirstLevel(MilSystem, MilDisplay);
FindWithAutoAngleTolerance(MilSystem, MilDisplay);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
void FindWithAutoFirstLevel(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MIL_ID MilSourceImage,
MilTargetImage,
MilParentDisplayImage;
Restore(SOURCE_FILE, TARGET_FILE, MilSystem,
&MilParentDisplayImage, &MilSourceImage, &MilTargetImage);
MIL_ID MilPatModel = MpatAllocModel(MilSystem, MilSourceImage,
MODEL1_OFFSET_X, MODEL1_OFFSET_Y,
MODEL_SIZE_X, MODEL_SIZE_Y,
M_NORMALIZED, M_NULL);
MIL_ID MilModelOverlay;
MdispSelect(MilDisplay, MilSourceImage);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(MilDisplay, M_OVERLAY_ID, &MilModelOverlay);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MpatDraw(M_DEFAULT, MilPatModel, MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MosPrintf(MIL_TEXT("ADJUSTING THE PYRAMID'S FIRST LEVEL SETTING:\n"));
MosPrintf(MIL_TEXT("--------------------------------------------\n\n"));
MosPrintf(MIL_TEXT("A model with fine structures has been defined in the source image.\n\n"));
MosPrintf(MIL_TEXT("Press <ENTER> to find the model using default settings in the target image.\n\n"));
MosGetch();
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispSelect(MilDisplay, MilParentDisplayImage);
MIL_ID MilTargetOverlay;
GetOverlayChilds(MilDisplay, MilParentDisplayImage, MilSourceImage,
MilTargetImage, &MilModelOverlay, &MilTargetOverlay);
MIL_ID MilPatResult = MpatAllocResult(MilSystem, M_DEFAULT, M_NULL);
for (MIL_INT i = 0; i < 2; i++)
{
if(i == 0)
{
MpatSetSearchParameter(MilPatModel, M_FIRST_LEVEL, M_DEFAULT);
}
else
{
MpatSetSearchParameter(MilPatModel, M_FIRST_LEVEL, M_AUTO_CONTENT_BASED);
MosPrintf(MIL_TEXT("Press <ENTER> to find the model using the content-based first level\n"));
MosPrintf(MIL_TEXT("pyramid setting.\n\n"));
MosGetch();
}
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MpatDraw(M_DEFAULT, MilPatModel, MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MIL_INT FirstLevel;
MpatInquire(MilPatModel, M_PROC_FIRST_LEVEL + M_TYPE_MIL_INT, &FirstLevel);
MosPrintf(MIL_TEXT("Model first level used: %d\n"), FirstLevel);
MpatFindModel(MilTargetImage, MilPatModel, MilPatResult);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MpatDraw(M_DEFAULT, MilPatResult, MilTargetOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_DEFAULT);
if(MpatGetNumber(MilPatResult, M_NULL) == 1)
{
MIL_DOUBLE XPos, YPos, Score;
MpatGetResult(MilPatResult, M_POSITION_X, &XPos);
MpatGetResult(MilPatResult, M_POSITION_Y, &YPos);
MpatGetResult(MilPatResult, M_SCORE, &Score);
MosPrintf(MIL_TEXT("Model found at (%5.2f, %5.2f), Score = %5.2f%%\n\n"), XPos, YPos, Score);
}
else
{
MosPrintf(MIL_TEXT("Model not found!\n\n"));
MgraColor(M_DEFAULT, M_COLOR_RED);
MgraText(M_DEFAULT, MilTargetOverlay, 5, 5, MIL_TEXT("NOT FOUND!"));
}
MdispControl(MilDisplay, M_UPDATE, M_ENABLE);
}
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MbufFree(MilModelOverlay);
MbufFree(MilTargetOverlay);
MpatFree(MilPatResult);
MpatFree(MilPatModel);
MbufFree(MilSourceImage);
MbufFree(MilTargetImage);
MbufFree(MilParentDisplayImage);
}
void BenchCompareWithAutoFirstLevel(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MosPrintf(MIL_TEXT("-----------------------------------------------------------\n"));
MosPrintf(MIL_TEXT("A benchmark comparison is performed using the content-based\n"));
MosPrintf(MIL_TEXT("pyramid level setting:\n\n"));
MosPrintf(MIL_TEXT("Two models of the same size are defined in the source image.\n"));
MosPrintf(MIL_TEXT("Model #1 has larger structures than Model #0, allowing it to use\n"));
MosPrintf(MIL_TEXT("a greater pyramid first level to speed up the search.\n\n"));
MIL_ID MilSourceImage,
MilTargetImage,
MilParentDisplayImage;
Restore(SOURCE_FILE, TARGET_FILE, MilSystem,
&MilParentDisplayImage, &MilSourceImage, &MilTargetImage);
MIL_DOUBLE FindTime[2];
MIL_ID MilPatModelArray[2];
MpatAllocModel(MilSystem, MilSourceImage, MODEL1_OFFSET_X, MODEL1_OFFSET_Y,
MODEL_SIZE_X, MODEL_SIZE_Y, M_NORMALIZED, &MilPatModelArray[0]);
MpatAllocModel(MilSystem, MilSourceImage, MODEL2_OFFSET_X, MODEL2_OFFSET_Y,
MODEL_SIZE_X, MODEL_SIZE_Y, M_NORMALIZED, &MilPatModelArray[1]);
MIL_ID MilModelOverlay;
MdispSelect(MilDisplay, MilSourceImage);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(MilDisplay, M_OVERLAY_ID, &MilModelOverlay);
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MpatDraw(M_DEFAULT, MilPatModelArray[0], MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MpatDraw(M_DEFAULT, MilPatModelArray[1], MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MgraText(M_DEFAULT, MilModelOverlay, MODEL1_OFFSET_X, MODEL1_OFFSET_Y-5, MIL_TEXT("#0"));
MgraText(M_DEFAULT, MilModelOverlay, MODEL2_OFFSET_X, MODEL2_OFFSET_Y-5, MIL_TEXT("#1"));
MdispControl(MilDisplay, M_UPDATE, M_ENABLE);
MdispSelect(MilDisplay, MilParentDisplayImage);
MIL_ID MilTargetOverlay;
GetOverlayChilds(MilDisplay, MilParentDisplayImage, MilSourceImage,
MilTargetImage, &MilModelOverlay, &MilTargetOverlay);
MIL_ID MilPatResult = MpatAllocResult(MilSystem, M_DEFAULT, &MilPatResult);
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
for (MIL_INT i = 0; i < 2; i++)
{
MpatSetSearchParameter(MilPatModelArray[i], M_FIRST_LEVEL, M_AUTO_CONTENT_BASED);
MIL_INT FirstLevel;
MpatInquire(MilPatModelArray[i], M_PROC_FIRST_LEVEL + M_TYPE_MIL_INT, &FirstLevel);
MosPrintf(MIL_TEXT("Model #%d first level: %d\n"), i, FirstLevel);
MappTimer(M_DEFAULT, M_TIMER_RESET, NULL);
MpatFindModel(MilTargetImage, MilPatModelArray[i], MilPatResult);
MappTimer(M_DEFAULT, M_TIMER_READ, &FindTime[i]);
if(MpatGetNumber(MilPatResult, M_NULL) == 1)
{
MIL_DOUBLE PosX, PosY, CenterX, CenterY;
MpatGetResult(MilPatResult, M_POSITION_X, &PosX);
MpatGetResult(MilPatResult, M_POSITION_Y, &PosY);
MpatInquire(MilPatModelArray[i], M_CENTER_X, &CenterX);
MpatInquire(MilPatModelArray[i], M_CENTER_Y, &CenterY);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MpatDraw(M_DEFAULT, MilPatResult, MilTargetOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_DEFAULT);
MIL_TEXT_CHAR Label[MAX_CHAR_LENGTH];
MosSprintf(Label, MAX_CHAR_LENGTH, MIL_TEXT("#%d"), i);
MgraText(M_DEFAULT, MilTargetOverlay, PosX-CenterX, PosY-CenterY-5, Label);
}
MosPrintf(MIL_TEXT("Model #%d find time: %6.3f ms\n\n"), i, FindTime[i] * 1000.0);
}
MdispControl(MilDisplay, M_UPDATE, M_ENABLE);
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MbufFree(MilModelOverlay);
MbufFree(MilTargetOverlay);
MpatFree(MilPatResult);
MpatFree(MilPatModelArray[0]);
MpatFree(MilPatModelArray[1]);
MbufFree(MilSourceImage);
MbufFree(MilTargetImage);
MbufFree(MilParentDisplayImage);
}
void FindWithAutoAngleTolerance(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MIL_ID MilSourceImage,
MilRotatedTargetImage,
MilParentDisplayImage;
Restore(CO_SOURCE_FILE, CO_TARGET_FILE, MilSystem,
&MilParentDisplayImage, &MilSourceImage, &MilRotatedTargetImage);
MIL_ID MilPatCOModel = MpatAllocModel(MilSystem, MilSourceImage, CO_MODEL_OFFSET_X, CO_MODEL_OFFSET_Y,
CO_MODEL_SIZE_X, CO_MODEL_SIZE_Y, M_NORMALIZED + M_CIRCULAR_OVERSCAN, M_NULL);
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_MODE, M_ENABLE);
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_DELTA_NEG, 180);
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_DELTA_POS, 180);
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_INTERPOLATION_MODE, M_BILINEAR);
MIL_ID MilModelOverlay;
MdispSelect(MilDisplay, MilSourceImage);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(MilDisplay, M_OVERLAY_ID, &MilModelOverlay);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MpatDraw(M_DEFAULT, MilPatCOModel, MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MosPrintf(MIL_TEXT("ADJUSTING THE ANGULAR TOLERANCE SETTING:\n"));
MosPrintf(MIL_TEXT("----------------------------------------\n\n"));
MosPrintf(MIL_TEXT("An elongated model with fine structures has been defined in the source image.\n"));
MosPrintf(MIL_TEXT("Such a model is very sensitive to rotation: a small angular variation results\n"));
MosPrintf(MIL_TEXT("in a significant drop in correlation score.\n\n"));
MosPrintf(MIL_TEXT("Press <ENTER> to find the model using default settings in the target image.\n\n"));
MosGetch();
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispSelect(MilDisplay, MilParentDisplayImage);
MIL_ID MilTargetOverlay;
GetOverlayChilds(MilDisplay, MilParentDisplayImage, MilSourceImage,
MilRotatedTargetImage, &MilModelOverlay, &MilTargetOverlay);
MIL_ID MilPatResult = MpatAllocResult(MilSystem, M_DEFAULT, &MilPatResult);
for (MIL_INT i = 0; i < 2; i++)
{
if(i == 0)
{
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_TOLERANCE, M_DEFAULT);
}
else
{
MpatSetAngle(MilPatCOModel, M_SEARCH_ANGLE_TOLERANCE, M_AUTO);
MosPrintf(MIL_TEXT("Press <ENTER> to find the model using the automatic angular tolerance setting.\n\n"));
MosGetch();
}
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MpatDraw(M_DEFAULT, MilPatCOModel, MilModelOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_ORIGINAL);
MpatPreprocModel(M_NULL, MilPatCOModel, M_DEFAULT);
MpatFindModel(MilRotatedTargetImage, MilPatCOModel, MilPatResult);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MpatDraw(M_DEFAULT, MilPatResult, MilTargetOverlay, M_DRAW_BOX+M_DRAW_POSITION, M_DEFAULT, M_DEFAULT);
if(MpatGetNumber(MilPatResult, M_NULL) == 1)
{
MIL_DOUBLE XPos, YPos, Score, Angle;
MpatGetResult(MilPatResult, M_POSITION_X, &XPos);
MpatGetResult(MilPatResult, M_POSITION_Y, &YPos);
MpatGetResult(MilPatResult, M_SCORE, &Score);
MpatGetResult(MilPatResult, M_ANGLE, &Angle);
MosPrintf(MIL_TEXT("Model found at (%5.2f, %5.2f), Angle = %5.2f, Score = %5.2f%%\n\n"), XPos, YPos, Angle, Score);
}
else
{
MosPrintf(MIL_TEXT("Model not found!\n\n"));
MgraColor(M_DEFAULT, M_COLOR_RED);
MgraText(M_DEFAULT, MilTargetOverlay, 5, 5, MIL_TEXT("NOT FOUND!"));
}
MdispControl(MilDisplay, M_UPDATE, M_ENABLE);
}
MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
MosGetch();
MbufFree(MilModelOverlay);
MbufFree(MilTargetOverlay);
MpatFree(MilPatResult);
MpatFree(MilPatCOModel);
MbufFree(MilSourceImage);
MbufFree(MilRotatedTargetImage);
MbufFree(MilParentDisplayImage);
}
void Restore(MIL_CONST_TEXT_PTR ModelSrcFilename, MIL_CONST_TEXT_PTR TargetSrcFilename,
MIL_ID System, MIL_ID *pParentImage, MIL_ID *pModelChild, MIL_ID *pTargetChild)
{
MIL_INT ModelSizeX = MbufDiskInquire(ModelSrcFilename, M_SIZE_X, M_NULL);
MIL_INT ModelSizeY = MbufDiskInquire(ModelSrcFilename, M_SIZE_Y, M_NULL);
MIL_INT TargetSizeX = MbufDiskInquire(TargetSrcFilename, M_SIZE_X, M_NULL);
MIL_INT TargetSizeY = MbufDiskInquire(TargetSrcFilename, M_SIZE_Y, M_NULL);
MIL_INT ParentSizeX = TargetSizeX > ModelSizeX ? TargetSizeX : ModelSizeX;
MIL_INT ParentSizeY = ModelSizeY + MARGIN_Y + TargetSizeY;
MbufAlloc2d(System, ParentSizeX, ParentSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, pParentImage);
MbufClear(*pParentImage, 0);
MbufChild2d(*pParentImage, 0, 0, ModelSizeX, ModelSizeY, pModelChild);
MbufChild2d(*pParentImage, 0, ModelSizeY + MARGIN_Y, TargetSizeX, TargetSizeY, pTargetChild);
MbufLoad(ModelSrcFilename, *pModelChild);
MbufLoad(TargetSrcFilename, *pTargetChild);
}
void GetOverlayChilds(MIL_ID Display, MIL_ID ParentImage, MIL_ID ModelChild, MIL_ID TargetChild,
MIL_ID *pModelOverlay, MIL_ID *pTargetOverlay)
{
MIL_ID ParentOverlay;
MdispControl(Display, M_OVERLAY, M_ENABLE);
MdispInquire(Display, M_OVERLAY_ID, &ParentOverlay);
MIL_INT TargetSizeX = MbufInquire(TargetChild, M_SIZE_X, M_NULL);
MIL_INT TargetSizeY = MbufInquire(TargetChild, M_SIZE_Y, M_NULL);
MIL_INT SourceSizeX = MbufInquire(ModelChild, M_SIZE_X, M_NULL);
MIL_INT SourceSizeY = MbufInquire(ModelChild, M_SIZE_Y, M_NULL);
MbufChild2d(ParentOverlay, 0, 0, SourceSizeX, SourceSizeY, pModelOverlay);
MbufChild2d(ParentOverlay, 0, SourceSizeY + MARGIN_Y, TargetSizeX, TargetSizeY, pTargetOverlay);
}