using System;
using System.Collections.Generic;
using System.Text;
using Matrox.MatroxImagingLibrary;
namespace MPat
{
class Program
{
static void Main(string[] args)
{
MIL_ID MilApplication = MIL.M_NULL;
MIL_ID MilSystem = MIL.M_NULL;
MIL_ID MilDisplay = MIL.M_NULL;
Console.Write("\nGRAYSCALE PATTERN MATCHING:\n");
Console.Write("---------------------------\n\n");
MIL.MappAllocDefault(MIL.M_DEFAULT, ref MilApplication, ref MilSystem, ref MilDisplay, MIL.M_NULL, MIL.M_NULL);
SearchModelExample(MilSystem, MilDisplay);
SearchRotatedModelExample(MilSystem, MilDisplay);
AutoAllocationModelExample(MilSystem, MilDisplay);
MIL.MappFreeDefault(MilApplication, MilSystem, MilDisplay, MIL.M_NULL, MIL.M_NULL);
}
private const string FIND_IMAGE_FILE = MIL.M_IMAGE_PATH + "CircuitsBoard.mim";
private const int FIND_MODEL_X_POS = 153;
private const int FIND_MODEL_Y_POS = 132;
private const int FIND_MODEL_WIDTH = 128;
private const int FIND_MODEL_HEIGHT = 128;
private const double FIND_MODEL_X_CENTER = (FIND_MODEL_X_POS + (FIND_MODEL_WIDTH - 1) / 2.0);
private const double FIND_MODEL_Y_CENTER = (FIND_MODEL_Y_POS + (FIND_MODEL_HEIGHT - 1) / 2.0);
private const double FIND_SHIFT_X = 4.5;
private const double FIND_SHIFT_Y = 7.5;
private const double FIND_MODEL_MIN_MATCH_SCORE = 70.0;
private const double FIND_MODEL_MIN_ACCURACY = 0.1;
static void SearchModelExample(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MIL_ID MilImage = MIL.M_NULL;
MIL_ID GraphicList = MIL.M_NULL;
MIL_ID Model = MIL.M_NULL;
MIL_ID Result = MIL.M_NULL;
double XOrg = 0.0;
double YOrg = 0.0;
double x = 0.0;
double y = 0.0;
double ErrX = 0.0;
double ErrY = 0.0;
double Score = 0.0;
double Time = 0.0;
double AnnotationColor = MIL.M_COLOR_GREEN;
MIL.MbufRestore(FIND_IMAGE_FILE, MilSystem, ref MilImage);
MIL.MdispSelect(MilDisplay, MilImage);
MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref GraphicList);
MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList);
MIL.MpatAllocModel(MilSystem, MilImage, FIND_MODEL_X_POS, FIND_MODEL_Y_POS, FIND_MODEL_WIDTH, FIND_MODEL_HEIGHT, MIL.M_NORMALIZED, ref Model);
MIL.MpatSetAccuracy(Model, MIL.M_HIGH);
MIL.MpatSetSpeed(Model, MIL.M_HIGH);
MIL.MpatPreprocModel(MilImage, Model, MIL.M_DEFAULT);
MIL.MgraColor(MIL.M_DEFAULT, AnnotationColor);
MIL.MpatDraw(MIL.M_DEFAULT, Model, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_ORIGINAL);
Console.Write("\nA {0}x{1} model was defined in the source image.\n", FIND_MODEL_WIDTH, FIND_MODEL_HEIGHT);
Console.Write("It will be found in an image shifted by {0:0.00} in X and {1:0.00} in Y.\n", FIND_SHIFT_X, FIND_SHIFT_Y);
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
MIL.MgraClear(MIL.M_DEFAULT, GraphicList);
MIL.MimTranslate(MilImage, MilImage, FIND_SHIFT_X, FIND_SHIFT_Y, MIL.M_DEFAULT);
MIL.MpatAllocResult(MilSystem, 1, ref Result);
MIL.MpatFindModel(MilImage, Model, Result);
MIL.MappTimer(MIL.M_DEFAULT, MIL.M_TIMER_RESET + MIL.M_SYNCHRONOUS, MIL.M_NULL);
MIL.MpatFindModel(MilImage, Model, Result);
MIL.MappTimer(MIL.M_DEFAULT, MIL.M_TIMER_READ + MIL.M_SYNCHRONOUS, ref Time);
if (MIL.MpatGetNumber(Result) == 1L)
{
MIL.MpatGetResult(Result, MIL.M_POSITION_X, ref x);
MIL.MpatGetResult(Result, MIL.M_POSITION_Y, ref y);
MIL.MpatGetResult(Result, MIL.M_SCORE, ref Score);
MIL.MgraColor(MIL.M_DEFAULT, AnnotationColor);
MIL.MpatDraw(MIL.M_DEFAULT, Result, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_DEFAULT);
ErrX = Math.Abs((FIND_MODEL_X_CENTER + FIND_SHIFT_X) - x);
ErrY = Math.Abs((FIND_MODEL_Y_CENTER + FIND_SHIFT_Y) - y);
MIL.MpatInquire(Model, MIL.M_ORIGINAL_X, ref XOrg);
MIL.MpatInquire(Model, MIL.M_ORIGINAL_Y, ref YOrg);
Console.Write("Search results:\n");
Console.Write("---------------------------------------------------\n");
Console.Write("The model is found to be shifted by \tX:{0:0.00}, Y:{1:0.00}.\n", x - XOrg, y - YOrg);
Console.Write("The model position error is \t\tX:{0:0.00}, Y:{1:0.00}\n", ErrX, ErrY);
Console.Write("The model match score is \t\t{0:0.0}\n", Score);
Console.Write("The search time is \t\t\t{0:0.000} ms\n\n", Time * 1000.0);
if ((Math.Abs((x - XOrg) - FIND_SHIFT_X) > FIND_MODEL_MIN_ACCURACY) ||
(Math.Abs((y - YOrg) - FIND_SHIFT_Y) > FIND_MODEL_MIN_ACCURACY) ||
(Score < FIND_MODEL_MIN_MATCH_SCORE))
{
Console.Write("Results verification error !\n");
}
}
else
{
Console.Write("Model not found !\n");
}
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
MIL.MgraClear(MIL.M_DEFAULT, GraphicList);
MIL.MgraFree(GraphicList);
MIL.MpatFree(Result);
MIL.MpatFree(Model);
MIL.MbufFree(MilImage);
}
private const string ROTATED_FIND_IMAGE_FILE = MIL.M_IMAGE_PATH + "CircuitsBoard.mim";
private const int ROTATED_FIND_ROTATION_DELTA_ANGLE = 10;
private const int ROTATED_FIND_ROTATION_ANGLE_STEP = 1;
private const double ROTATED_FIND_RAD_PER_DEG = 0.01745329251;
private const int ROTATED_FIND_MODEL_X_POS = 153;
private const int ROTATED_FIND_MODEL_Y_POS = 132;
private const int ROTATED_FIND_MODEL_WIDTH = 128;
private const int ROTATED_FIND_MODEL_HEIGHT = 128;
private const double ROTATED_FIND_MODEL_X_CENTER = ROTATED_FIND_MODEL_X_POS + (ROTATED_FIND_MODEL_WIDTH - 1) / 2.0;
private const double ROTATED_FIND_MODEL_Y_CENTER = ROTATED_FIND_MODEL_Y_POS + (ROTATED_FIND_MODEL_HEIGHT - 1) / 2.0;
private const double ROTATED_FIND_MIN_POSITION_ACCURACY = 0.10;
private const double ROTATED_FIND_MIN_ANGLE_ACCURACY = 0.25;
private const int ROTATED_FIND_ANGLE_DELTA_POS = ROTATED_FIND_ROTATION_DELTA_ANGLE;
private const int ROTATED_FIND_ANGLE_DELTA_NEG = ROTATED_FIND_ROTATION_DELTA_ANGLE;
static void SearchRotatedModelExample(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MIL_ID MilSourceImage = MIL.M_NULL;
MIL_ID MilTargetImage = MIL.M_NULL;
MIL_ID MilDisplayImage = MIL.M_NULL;
MIL_ID GraphicList = MIL.M_NULL;
MIL_ID MilModel = MIL.M_NULL;
MIL_ID MilResult = MIL.M_NULL;
double RealX = 0.0;
double RealY = 0.0;
double RealAngle = 0.0;
double X = 0.0;
double Y = 0.0;
double Angle = 0.0;
double Score = 0.0;
double Time = 0.0;
double ErrX = 0.0;
double ErrY = 0.0;
double ErrAngle = 0.0;
double SumErrX = 0.0;
double SumErrY = 0.0;
double SumErrAngle = 0.0;
double SumTime = 0.0;
int NbFound = 0;
double AnnotationColor = MIL.M_COLOR_GREEN;
MIL.MbufRestore(ROTATED_FIND_IMAGE_FILE, MilSystem, ref MilSourceImage);
MIL.MbufRestore(ROTATED_FIND_IMAGE_FILE, MilSystem, ref MilTargetImage);
MIL.MbufRestore(ROTATED_FIND_IMAGE_FILE, MilSystem, ref MilDisplayImage);
MIL.MdispSelect(MilDisplay, MilDisplayImage);
MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref GraphicList);
MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList);
MIL.MpatAllocModel(MilSystem, MilSourceImage, ROTATED_FIND_MODEL_X_POS, ROTATED_FIND_MODEL_Y_POS, ROTATED_FIND_MODEL_WIDTH, ROTATED_FIND_MODEL_HEIGHT, MIL.M_NORMALIZED + MIL.M_CIRCULAR_OVERSCAN, ref MilModel);
MIL.MpatSetSpeed(MilModel, MIL.M_MEDIUM);
MIL.MpatSetAccuracy(MilModel, MIL.M_HIGH);
MIL.MpatSetAngle(MilModel, MIL.M_SEARCH_ANGLE_MODE, MIL.M_ENABLE);
MIL.MpatSetAngle(MilModel, MIL.M_SEARCH_ANGLE_DELTA_NEG, ROTATED_FIND_ANGLE_DELTA_NEG);
MIL.MpatSetAngle(MilModel, MIL.M_SEARCH_ANGLE_DELTA_POS, ROTATED_FIND_ANGLE_DELTA_POS);
MIL.MpatSetAngle(MilModel, MIL.M_SEARCH_ANGLE_ACCURACY, ROTATED_FIND_MIN_ANGLE_ACCURACY);
MIL.MpatSetAngle(MilModel, MIL.M_SEARCH_ANGLE_INTERPOLATION_MODE, MIL.M_BILINEAR);
MIL.MpatPreprocModel(MilSourceImage, MilModel, MIL.M_DEFAULT);
MIL.MpatAllocResult(MilSystem, 1, ref MilResult);
MIL.MpatDraw(MIL.M_DEFAULT, MilModel, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_ORIGINAL);
Console.Write("\nA {0}x{1} model was defined in the source image.\n", ROTATED_FIND_MODEL_WIDTH, ROTATED_FIND_MODEL_HEIGHT);
Console.Write("It will be searched in images rotated from {0} degree to {1} degree.\n", -ROTATED_FIND_ROTATION_DELTA_ANGLE, ROTATED_FIND_ROTATION_DELTA_ANGLE);
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
MIL.MpatFindModel(MilSourceImage, MilModel, MilResult);
if (MIL.MpatGetNumber(MilResult, MIL.M_NULL) == 1)
{
RealAngle = ROTATED_FIND_ROTATION_DELTA_ANGLE;
while (RealAngle >= -ROTATED_FIND_ROTATION_DELTA_ANGLE)
{
MIL.MimRotate(MilSourceImage, MilTargetImage, RealAngle, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_BILINEAR + MIL.M_OVERSCAN_CLEAR);
MIL.MappTimer(MIL.M_DEFAULT, MIL.M_TIMER_RESET + MIL.M_SYNCHRONOUS, MIL.M_NULL);
MIL.MpatFindModel(MilTargetImage, MilModel, MilResult);
MIL.MappTimer(MIL.M_DEFAULT, MIL.M_TIMER_READ + MIL.M_SYNCHRONOUS, ref Time);
MIL.MgraClear(MIL.M_DEFAULT, GraphicList);
if (MIL.MpatGetNumber(MilResult) == 1)
{
MIL.MpatGetResult(MilResult, MIL.M_POSITION_X, ref X);
MIL.MpatGetResult(MilResult, MIL.M_POSITION_Y, ref Y);
MIL.MpatGetResult(MilResult, MIL.M_ANGLE, ref Angle);
MIL.MpatGetResult(MilResult, MIL.M_SCORE, ref Score);
MIL.MgraColor(MIL.M_DEFAULT, AnnotationColor);
MIL.MpatDraw(MIL.M_DEFAULT, MilResult, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_DEFAULT);
MIL.MbufCopy(MilTargetImage, MilDisplayImage);
ErrAngle = CalculateAngleDist(Angle, RealAngle);
RotateModelCenter(MilSourceImage, ref RealX, ref RealY, RealAngle);
ErrX = Math.Abs(X - RealX);
ErrY = Math.Abs(Y - RealY);
SumErrAngle += ErrAngle;
SumErrX += ErrX;
SumErrY += ErrY;
SumTime += Time;
NbFound++;
if ((ErrX > ROTATED_FIND_MIN_POSITION_ACCURACY) || (ErrY > ROTATED_FIND_MIN_POSITION_ACCURACY) || (ErrAngle > ROTATED_FIND_MIN_ANGLE_ACCURACY))
{
Console.Write("Model accuracy error at angle {0:0.0} !\n\n", RealAngle);
Console.Write("Errors are X:{0:0.000}, Y:{1:0.000} and Angle:{2:0.00}\n\n", ErrX, ErrY, ErrAngle);
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
}
}
else
{
Console.Write("Model was not found at angle {0:0.0} !\n\n", RealAngle);
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
}
RealAngle -= ROTATED_FIND_ROTATION_ANGLE_STEP;
}
Console.Write("\nSearch statistics for the model found in the rotated images.\n");
Console.Write("------------------------------------------------------------\n");
Console.Write("The average position error is \t\tX:{0:0.000}, Y:{1:0.000}\n", SumErrX / NbFound, SumErrY / NbFound);
Console.Write("The average angle error is \t\t{0:0.000}\n", SumErrAngle / NbFound);
Console.Write("The average search time is \t\t{0:0.000} ms\n\n", SumTime * 1000.0 / NbFound);
}
else
{
Console.Write("Model was not found!\n\n");
}
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
MIL.MgraFree(GraphicList);
MIL.MpatFree(MilResult);
MIL.MpatFree(MilModel);
MIL.MbufFree(MilTargetImage);
MIL.MbufFree(MilSourceImage);
MIL.MbufFree(MilDisplayImage);
}
static void RotateModelCenter(MIL_ID Buffer, ref double X, ref double Y, double Angle)
{
MIL_INT BufSizeX = MIL.MbufInquire(Buffer, MIL.M_SIZE_X, MIL.M_NULL);
MIL_INT BufSizeY = MIL.MbufInquire(Buffer, MIL.M_SIZE_Y, MIL.M_NULL);
double RadAngle = Angle * ROTATED_FIND_RAD_PER_DEG;
double CosAngle = Math.Cos(RadAngle);
double SinAngle = Math.Sin(RadAngle);
double OffSetX = (BufSizeX - 1) / 2.0;
double OffSetY = (BufSizeY - 1) / 2.0;
X = (ROTATED_FIND_MODEL_X_CENTER - OffSetX) * CosAngle + (ROTATED_FIND_MODEL_Y_CENTER - OffSetY) * SinAngle + OffSetX;
Y = (ROTATED_FIND_MODEL_Y_CENTER - OffSetY) * CosAngle - (ROTATED_FIND_MODEL_X_CENTER - OffSetX) * SinAngle + OffSetY;
}
static double CalculateAngleDist(double Angle1, double Angle2)
{
double dist = Math.Abs(Angle1 - Angle2);
while (dist >= 360.0)
{
dist -= 360.0;
}
if (dist > 180.0)
{
dist = 360.0 - dist;
}
return dist;
}
private const string AUTO_MODEL_IMAGE_FILE = MIL.M_IMAGE_PATH + "Wafer.mim";
private const string AUTO_MODEL_TARGET_IMAGE_FILE = MIL.M_IMAGE_PATH + "WaferShifted.mim";
private const int AUTO_MODEL_WIDTH = 64;
private const int AUTO_MODEL_HEIGHT = 64;
static void AutoAllocationModelExample(MIL_ID MilSystem, MIL_ID MilDisplay)
{
MIL_ID MilImage = MIL.M_NULL;
MIL_ID MilSubImage = MIL.M_NULL;
MIL_ID GraphicList = MIL.M_NULL;
MIL_ID Model = MIL.M_NULL;
MIL_ID Result = MIL.M_NULL;
int AllocError = 0;
MIL_INT ImageWidth = 0;
MIL_INT ImageHeight = 0;
double OrgX = 0.0;
double OrgY = 0.0;
double x = 0.0;
double y = 0.0;
double Score = 0.0;
double AnnotationColor = MIL.M_COLOR_GREEN;
MIL.MbufRestore(AUTO_MODEL_IMAGE_FILE, MilSystem, ref MilImage);
MIL.MdispSelect(MilDisplay, MilImage);
MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref GraphicList);
MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, GraphicList);
MIL.MbufInquire(MilImage, MIL.M_SIZE_X, ref ImageWidth);
MIL.MbufInquire(MilImage, MIL.M_SIZE_Y, ref ImageHeight);
MIL.MbufChild2d(MilImage, ImageWidth / 2, ImageHeight / 2, ImageWidth / 2, ImageHeight / 2, ref MilSubImage);
MIL.MgraControl(MIL.M_DEFAULT, MIL.M_DRAW_OFFSET_X, (double)-(ImageWidth / 2));
MIL.MgraControl(MIL.M_DEFAULT, MIL.M_DRAW_OFFSET_Y, (double)-(ImageHeight / 2));
MIL.MpatAllocAutoModel(MilSystem, MilSubImage, AUTO_MODEL_WIDTH, AUTO_MODEL_HEIGHT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_NORMALIZED, MIL.M_DEFAULT, ref Model);
MIL.MpatSetAccuracy(Model, MIL.M_HIGH);
MIL.MappGetError(MIL.M_DEFAULT, MIL.M_CURRENT, ref AllocError);
if (AllocError == 0)
{
MIL.MgraColor(MIL.M_DEFAULT, AnnotationColor);
MIL.MpatDraw(MIL.M_DEFAULT, Model, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_ORIGINAL);
Console.Write("A model was automatically defined in the image.\n");
Console.Write("Press <Enter> to continue.\n\n");
Console.ReadKey();
MIL.MgraClear(MIL.M_DEFAULT, GraphicList);
MIL.MbufLoad(AUTO_MODEL_TARGET_IMAGE_FILE, MilImage);
MIL.MpatAllocResult(MilSystem, 1, ref Result);
MIL.MpatFindModel(MilSubImage, Model, Result);
if (MIL.MpatGetNumber(Result) == 1)
{
MIL.MpatGetResult(Result, MIL.M_POSITION_X, ref x);
MIL.MpatGetResult(Result, MIL.M_POSITION_Y, ref y);
MIL.MpatGetResult(Result, MIL.M_SCORE, ref Score);
MIL.MgraColor(MIL.M_DEFAULT, AnnotationColor);
MIL.MpatDraw(MIL.M_DEFAULT, Result, GraphicList, MIL.M_DRAW_BOX + MIL.M_DRAW_POSITION, MIL.M_DEFAULT, MIL.M_DEFAULT);
MIL.MpatInquire(Model, MIL.M_ORIGINAL_X, ref OrgX);
MIL.MpatInquire(Model, MIL.M_ORIGINAL_Y, ref OrgY);
Console.Write("An image misaligned by 50 pixels in X and 20 pixels in Y was loaded.\n\n");
Console.Write("The image is found to be shifted by {0:0.00} in X, and {1:0.00} in Y.\n", x - OrgX, y - OrgY);
Console.Write("Model match score is {0:0.0} percent.\n", Score);
Console.Write("Press <Enter> to end.\n\n");
Console.ReadKey();
}
else
{
Console.Write("Error: Pattern not found properly.\n");
Console.Write("Press <Enter> to end.\n\n");
Console.ReadKey();
}
MIL.MpatFree(Result);
MIL.MpatFree(Model);
}
else
{
Console.Write("Error: Automatic model definition failed.\n");
Console.Write("Press <Enter> to end.\n\n");
Console.ReadKey();
}
MIL.MgraControl(MIL.M_DEFAULT, MIL.M_DRAW_OFFSET_X, 0.0);
MIL.MgraControl(MIL.M_DEFAULT, MIL.M_DRAW_OFFSET_Y, 0.0);
MIL.MgraFree(GraphicList);
MIL.MbufFree(MilSubImage);
MIL.MbufFree(MilImage);
}
}
}