#include <mil.h>
#include <math.h>
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n"));
MosPrintf(MIL_TEXT("BinaryBasedCircleDetection\n\n"));
MosPrintf(MIL_TEXT("[SYNOPSIS]\n"));
MosPrintf(MIL_TEXT("This example demonstrates how to find circles that have a radius\n")
MIL_TEXT("less than 255 pixels using a distance transform and grayscale\n"));
MosPrintf(MIL_TEXT("correlation.\n\n"));
MosPrintf(MIL_TEXT("[MODULES USED]\n"));
MosPrintf(MIL_TEXT("Modules used: application, system, display, buffer, graphic,\n")
MIL_TEXT("image processing, pattern matching.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
#define SOURCE_IMAGE_FILE M_IMAGE_PATH \
MIL_TEXT("BinaryBasedCircleDetection/BottleCaps.mim")
#define STRING_SIZE 128
#define IMAGE_THRESHOLD_VALUE 39L
#define MIN_CIRCLE_RADIUS 2L
#define SYNTHETIC_CIRCLE_RADIUS 60L
#define CONE_RADIUS 20L
int MosMain(void)
{
MIL_ID MilApplication,
MilImage,
MilDisplay,
MilGraphics,
MilGraphicList,
MilSystem;
MIL_ID MilBinarizedImage,
MilDistanceImage8bit,
MilDistanceImage16bit,
MilConeModel,
MilCircleImage,
MilCircleDistanceImage8bit,
MilCircleDistanceImage16bit,
MilPatternResult;
MIL_INT ImageSizeX,
ImageSizeY;
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();
MbufRestore(SOURCE_IMAGE_FILE, MilSystem, &MilImage);
ImageSizeX = MbufInquire(MilImage, M_SIZE_X, M_NULL);
ImageSizeY = MbufInquire(MilImage, M_SIZE_Y, M_NULL);
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
8,
M_IMAGE+M_PROC+M_DISP,
&MilBinarizedImage);
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
8,
M_IMAGE+M_PROC+M_DISP,
&MilDistanceImage8bit);
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
16,
M_IMAGE+M_PROC+M_DISP,
&MilDistanceImage16bit);
MdispSelect(MilDisplay, MilImage);
MgraAlloc(MilSystem, &MilGraphics);
MgraControl(MilGraphics, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraAllocList(MilSystem, M_DEFAULT, &MilGraphicList);
MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraphicList);
MosPrintf(MIL_TEXT("The bottle caps in the displayed image will be found using the \n")
MIL_TEXT("following steps:\n\n"));
MosPrintf(MIL_TEXT("1. Binarization.\n"));
MosPrintf(MIL_TEXT("2. Distance transform.\n"));
MosPrintf(MIL_TEXT("3. Grayscale pattern matching using the distance transform \n")
MIL_TEXT(" of a synthetic disk as a model.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MimBinarize(MilImage, MilBinarizedImage, M_FIXED+M_GREATER_OR_EQUAL,
IMAGE_THRESHOLD_VALUE, M_NULL);
MimOpen(MilBinarizedImage, MilBinarizedImage, MIN_CIRCLE_RADIUS, M_BINARY);
MimClose(MilBinarizedImage, MilBinarizedImage, MIN_CIRCLE_RADIUS, M_BINARY);
MdispSelect(MilDisplay, MilBinarizedImage);
MosPrintf(MIL_TEXT("The binarized image is displayed.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MimDistance(MilBinarizedImage, MilDistanceImage16bit, M_CHAMFER_3_4);
MbufCopy(MilDistanceImage16bit, MilDistanceImage8bit);
MdispSelect(MilDisplay, MilDistanceImage16bit);
MosPrintf(MIL_TEXT("The distance transform is displayed.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
8,
M_IMAGE+M_PROC+M_DISP,
&MilCircleImage);
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
8,
M_IMAGE+M_PROC+M_DISP,
&MilCircleDistanceImage8bit);
MbufAlloc2d(MilSystem,
ImageSizeX,
ImageSizeY,
16,
M_IMAGE+M_PROC+M_DISP,
&MilCircleDistanceImage16bit);
MbufClear(MilCircleImage, 0);
MgraColor(MilGraphics, M_COLOR_WHITE);
MIL_INT CircleCenterX = (ImageSizeX-1)/2;
MIL_INT CircleCenterY = (ImageSizeY-1)/2;
MgraArcFill(MilGraphics, MilCircleImage, CircleCenterX, CircleCenterY,
SYNTHETIC_CIRCLE_RADIUS, SYNTHETIC_CIRCLE_RADIUS, 0, 360);
MimDistance(MilCircleImage, MilCircleDistanceImage16bit, M_CHAMFER_3_4);
MbufCopy(MilCircleDistanceImage16bit, MilCircleDistanceImage8bit);
MIL_INT ModelOffsetX = CircleCenterX - CONE_RADIUS;
MIL_INT ModelOffsetY = CircleCenterY - CONE_RADIUS;
MIL_INT ModelSizeX = CONE_RADIUS*2;
MIL_INT ModelSizeY = CONE_RADIUS*2;
MpatAllocModel(MilSystem, MilCircleDistanceImage8bit, ModelOffsetX, ModelOffsetY,
ModelSizeX, ModelSizeY, M_NORMALIZED, &MilConeModel);
MpatSetNumber(MilConeModel, M_ALL);
MpatAllocResult(MilSystem, M_DEFAULT, &MilPatternResult);
MpatFindModel(MilDistanceImage8bit, MilConeModel, MilPatternResult);
MIL_INT NumOccurences = MpatGetNumber(MilPatternResult, M_NULL);
if (NumOccurences > 0)
{
MgraColor(MilGraphics, M_COLOR_GREEN);
MpatDraw(MilGraphics, MilPatternResult, MilGraphicList, M_DRAW_BOX+M_DRAW_POSITION,
M_DEFAULT, M_DEFAULT);
MIL_DOUBLE* PositionX = new MIL_DOUBLE [NumOccurences];
MIL_DOUBLE* PositionY = new MIL_DOUBLE [NumOccurences];
MpatGetResult(MilPatternResult, M_POSITION_X, PositionX);
MpatGetResult(MilPatternResult, M_POSITION_Y, PositionY);
MIL_TEXT_CHAR DistanceString[STRING_SIZE];
for (MIL_INT i=0; i<NumOccurences; i++)
{
char Distance;
MbufGet2d(MilDistanceImage8bit, (MIL_INT)(PositionX[i]),
(MIL_INT)(PositionY[i]), 1, 1, &Distance);
MosSprintf(DistanceString, STRING_SIZE, MIL_TEXT("d=%d"), (MIL_INT)Distance);
MgraText(MilGraphics, MilGraphicList, PositionX[i], PositionY[i]+20,
DistanceString);
}
MosPrintf(MIL_TEXT("A pattern matching model has been defined using the ")
MIL_TEXT("distance\ntransform of a synthetic disk, and is used to ")
MIL_TEXT("detect the caps.\n\n"));
MosPrintf(MIL_TEXT("%d bottle caps have been found. The locations and ")
MIL_TEXT("the\ncorresponding distances are shown.\n\n"),
NumOccurences);
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MgraClear(M_DEFAULT, MilGraphicList);
MgraColor(MilGraphics, M_COLOR_RED);
MdispSelect(MilDisplay, MilImage);
const MIL_DOUBLE StartAngle = 330;
const MIL_DOUBLE EndAngle = 30;
for (MIL_INT i=0; i<NumOccurences; i++)
{
char Distance;
MbufGet2d(MilDistanceImage8bit, (MIL_INT)(PositionX[i]),
(MIL_INT)(PositionY[i]), 1, 1, &Distance);
MgraLine(MilGraphics, MilGraphicList, PositionX[i], PositionY[i],
PositionX[i]+Distance, PositionY[i]);
MgraArc(MilGraphics, MilGraphicList, PositionX[i], PositionY[i], Distance,
Distance, StartAngle, EndAngle);
}
delete [] PositionX;
delete [] PositionY;
MosPrintf(MIL_TEXT("The position and approximate radius of each bottle cap is displayed\n")
MIL_TEXT("in the original image.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
MosGetch();
}
else
{
MosPrintf(MIL_TEXT("Could not find the bottle caps!\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
MosGetch();
}
MbufFree(MilCircleImage);
MbufFree(MilCircleDistanceImage8bit);
MbufFree(MilCircleDistanceImage16bit);
MbufFree(MilBinarizedImage);
MbufFree(MilDistanceImage8bit);
MbufFree(MilDistanceImage16bit);
MbufFree(MilImage);
MpatFree(MilConeModel);
MpatFree(MilPatternResult);
MgraFree(MilGraphics);
MgraFree(MilGraphicList);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}