#include <mil.h>
#include "AutomaticBlobSelection.h"
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n"));
MosPrintf(MIL_TEXT("FixturingUsingBlob\n\n"));
MosPrintf(MIL_TEXT("[SYNOPSIS]\n"));
MosPrintf(MIL_TEXT("This example reads linear codes using a predefined blob\n")
MIL_TEXT("to fixture the operation.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to setup the read operation.\n\n"));
MosGetch();
}
static const MIL_CONST_TEXT_PTR SETUP_IMAGE = M_IMAGE_PATH MIL_TEXT("/FixturedCodeRead/BoardSetup.mim");
static const MIL_CONST_TEXT_PTR PROCESS_PATH = M_IMAGE_PATH MIL_TEXT("/FixturedCodeRead@1fps");
static const bool INTERACTIVE_EXAMPLE = false;
static const MIL_INT CODE_TYPE = M_CODE39;
static const MIL_INT THRESHOLD_MODE = M_ADAPTIVE;
static const MIL_DOUBLE THRESHOLD_VALUE = 128;
static const MIL_DOUBLE MIN_BREADTH = 6;
static const MIL_DOUBLE MIN_BLOB_AREA = 500;
static const MIL_DOUBLE MIN_DIM_FACTOR = 0.8;
static const MIL_DOUBLE MAX_DIM_FACTOR = 1.2;
static const MIL_DOUBLE MIN_FERET_RATIO = 1.5;
static const MIL_DOUBLE EXPECTED_BLOB_WIDTH = 415;
static const MIL_DOUBLE EXPECTED_BLOB_HEIGHT = 75;
static const MIL_DOUBLE CODE_REGION_START_X = 70;
static const MIL_DOUBLE CODE_REGION_START_Y = 330;
static const MIL_DOUBLE CODE_REGION_END_X = 500;
static const MIL_DOUBLE CODE_REGION_END_Y = 430;
static const MIL_INT MAX_CODE_STRING_SIZE = 512;
static const MIL_INT GRA_TEXT_SIZE_Y = 16;
struct SProcessData
{
MIL_ID MilDisplay;
MIL_ID MilGraList;
MIL_ID MilRegionGraList;
MIL_ID MilImage;
MIL_ID MilSearchImage;
MIL_ID MilSearchContext;
MIL_ID MilSearchResult;
MIL_ID MilFixturingOffset;
MIL_ID MilCodeContext;
MIL_ID MilCodeResult;
MIL_DOUBLE BlobWidth;
MIL_DOUBLE BlobHeight;
};
bool CalculateBlobFixturePosition(MIL_ID MilImage,
MIL_ID MilSearchImage,
MIL_ID MilBlobFeatureList,
MIL_ID MilBlobResult,
MIL_DOUBLE BlobWidth,
MIL_DOUBLE BlobHeight,
MIL_DOUBLE* pFixturePosX,
MIL_DOUBLE* pFixturePosY,
MIL_DOUBLE* pFixtureAngle);
void DeleteImpossibleBlobs(MIL_ID MilBlobResult);
void BinarizeImage(MIL_ID MilImage, MIL_ID MilSearchImage);
void DrawBlobFixtureAndRegion(MIL_ID MilDisplay, MIL_ID MilBlobResult, MIL_ID MilFixturingOffset, MIL_ID MilRegionGraList, MIL_ID MilGraList);
void ProcessImage(SProcessData* pProcessData);
MIL_INT MFTYPE DigProcess(MIL_INT HookType, MIL_ID MilEvent, void* pUserData);
int MosMain(void)
{
MIL_ID MilApplication = MappAlloc(M_DEFAULT, M_NULL);
MIL_ID MilSystem = M_DEFAULT_HOST;
MIL_ID MilDisplay = MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, M_NULL);
PrintHeader();
MIL_ID MilGraList = MgraAllocList(MilSystem, M_DEFAULT, M_NULL);
MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraList);
MIL_ID MilRegionGraList = MgraAllocList(MilSystem, M_DEFAULT, M_NULL);
MIL_ID MilImage = MbufRestore(SETUP_IMAGE, MilSystem, M_NULL);
MIL_ID MilGrabImage = MbufRestore(SETUP_IMAGE, MilSystem, M_NULL);
MIL_INT ImageSizeX = MbufInquire(MilImage, M_SIZE_X, M_NULL);
MIL_INT ImageSizeY = MbufInquire(MilImage, M_SIZE_Y, M_NULL);
MIL_ID MilSearchImage = MbufAlloc2d(MilSystem, ImageSizeX, ImageSizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, M_NULL);
McalUniform(MilImage, 0, 0, 1, 1, 0, M_DEFAULT);
MdispSelect(MilDisplay, MilImage);
MIL_ID MilBlobResult = MblobAllocResult(MilSystem, M_NULL);
MIL_ID MilBlobFeatureList = MblobAllocFeatureList(MilSystem, M_NULL);
MblobSelectFeature(MilBlobFeatureList, M_AREA);
MblobSelectFeature(MilBlobFeatureList, M_BREADTH);
MblobSelectFeature(MilBlobFeatureList, M_BOX);
MblobSelectFeature(MilBlobFeatureList, M_MIN_AREA_BOX);
MIL_DOUBLE BlobWidth = EXPECTED_BLOB_WIDTH;
MIL_DOUBLE BlobHeight = EXPECTED_BLOB_HEIGHT;
if (INTERACTIVE_EXAMPLE)
{
bool BlobIsChosen = ChoosePossibleFixturingBlob(MilImage,
MilSearchImage,
MilDisplay,
MilBlobResult,
MilBlobFeatureList,
MIN_DIM_FACTOR,
MAX_DIM_FACTOR,
MIN_FERET_RATIO,
BinarizeImage,
DeleteImpossibleBlobs,
&BlobWidth,
&BlobHeight);
if (!BlobIsChosen)
MosPrintf(MIL_TEXT("Default blob width and height will be used.\n\n"));
}
MIL_ID MilFixturingOffset = McalAlloc(MilSystem, M_FIXTURING_OFFSET, M_DEFAULT, M_NULL);
MIL_DOUBLE FixturePosX;
MIL_DOUBLE FixturePosY;
MIL_DOUBLE FixtureAngle;
CalculateBlobFixturePosition(MilImage, MilSearchImage, MilBlobFeatureList, MilBlobResult, BlobWidth, BlobHeight, &FixturePosX, &FixturePosY, &FixtureAngle);
McalFixture(M_NULL, MilFixturingOffset, M_LEARN_OFFSET, M_POINT_AND_ANGLE, M_DEFAULT, FixturePosX, FixturePosY, FixtureAngle, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_RED);
MgraControl(M_DEFAULT, M_INPUT_UNITS, M_WORLD);
if (INTERACTIVE_EXAMPLE)
{
MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, MilRegionGraList);
MdispControl(MilDisplay, M_GRAPHIC_LIST_INTERACTIVE, M_ENABLE);
MgraInteractive(M_DEFAULT, MilRegionGraList, M_GRAPHIC_TYPE_RECT, M_DEFAULT, M_DEFAULT);
MIL_INT ListState;
do
{
MosPrintf(MIL_TEXT("Interactively define a rectangular region around the code to be read.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> when finished.\n\n"));
MosGetch();
MgraInquireList(MilRegionGraList, M_LIST, M_DEFAULT, M_INTERACTIVE_GRAPHIC_STATE, &ListState);
}while(ListState == M_STATE_BEING_CREATED || ListState == M_STATE_WAITING_FOR_CREATION);
MgraControlList(MilRegionGraList, M_GRAPHIC_INDEX(0), M_DEFAULT, M_SELECTABLE, M_DISABLE);
MgraControlList(MilRegionGraList, M_GRAPHIC_INDEX(0), M_DEFAULT, M_EDITABLE, M_DISABLE);
MdispControl(MilDisplay, M_GRAPHIC_LIST_INTERACTIVE, M_DISABLE);
MosPrintf(MIL_TEXT("A relative region has been defined.\n\n")
MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraList);
}
else
{
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_DISABLE);
MgraRect(M_DEFAULT, MilRegionGraList, CODE_REGION_START_X, CODE_REGION_START_Y, CODE_REGION_END_X, CODE_REGION_END_Y);
}
MIL_ID MilCodeContext = McodeAlloc(MilSystem, M_DEFAULT, M_DEFAULT, M_NULL);
MIL_ID MilCodeResult = McodeAllocResult(MilSystem, M_DEFAULT, M_NULL);
MIL_ID MilCodeModel = McodeModel(MilCodeContext, M_ADD, M_CODE39, M_NULL, M_DEFAULT, M_NULL);
McodeControl(MilCodeContext, M_THRESHOLD_MODE, THRESHOLD_MODE);
McodeControl(MilCodeModel, M_SEARCH_ANGLE, M_ACCORDING_TO_REGION);
MIL_ID MilDigitizer = MdigAlloc(MilSystem, M_DEFAULT, PROCESS_PATH, M_DEFAULT, M_NULL);
MgraControl(M_DEFAULT, M_INPUT_UNITS, M_PIXEL);
DrawBlobFixtureAndRegion(MilDisplay, MilBlobResult, MilFixturingOffset, MilRegionGraList, MilGraList);
MosPrintf(MIL_TEXT("In the setup image, the user defined blob (in blue) is selected to fixture the\n")
MIL_TEXT("read operation.\n")
MIL_TEXT("The offset of the blob from the origin of the setup image (in green) is learnt.\n")
MIL_TEXT("The relative region to perform the read operation (in red) is defined in\n")
MIL_TEXT("world units.\n\n")
MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MosPrintf(MIL_TEXT("The code is now read continuously.\n")
MIL_TEXT("For each image:\n")
MIL_TEXT("-The blob is located in the image.\n")
MIL_TEXT("-The relative coordinate system is moved accordingly.\n")
MIL_TEXT("-The region is updated in the relative coordinate system.\n")
MIL_TEXT("-The linear code is read in the region.\n\n")
MIL_TEXT("Press <Enter> to end.\n\n"));
SProcessData ProcessData;
ProcessData.MilDisplay = MilDisplay;
ProcessData.MilGraList = MilGraList;
ProcessData.MilRegionGraList = MilRegionGraList;
ProcessData.MilImage = MilImage;
ProcessData.MilSearchImage = MilSearchImage;
ProcessData.MilSearchContext = MilBlobFeatureList;
ProcessData.MilSearchResult = MilBlobResult;
ProcessData.MilFixturingOffset = MilFixturingOffset;
ProcessData.MilCodeContext = MilCodeContext;
ProcessData.MilCodeResult = MilCodeResult;
ProcessData.BlobWidth = BlobWidth;
ProcessData.BlobHeight = BlobHeight;
MdigProcess(MilDigitizer, &MilGrabImage, 1, M_START, M_ASYNCHRONOUS, DigProcess, &ProcessData);
MosGetch();
MdigProcess(MilDigitizer, &MilGrabImage, 1, M_STOP, M_DEFAULT, M_NULL, M_NULL);
MdigFree(MilDigitizer);
McodeFree(MilCodeResult);
McodeFree(MilCodeContext);
McalFree(MilFixturingOffset);
MblobFree(MilBlobResult);
MblobFree(MilBlobFeatureList);
if (MilSearchImage != MilImage)
MbufFree(MilSearchImage);
MbufFree(MilImage);
MbufFree(MilGrabImage);
MgraFree(MilRegionGraList);
MgraFree(MilGraList);
MdispFree(MilDisplay);
if (MilSystem != M_DEFAULT_HOST)
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
void BinarizeImage(MIL_ID MilImage, MIL_ID MilSearchImage)
{
MimBinarize(MilImage, MilSearchImage, M_FIXED + M_GREATER, THRESHOLD_VALUE, M_NULL);
}
void DeleteImpossibleBlobs(MIL_ID MilBlobResult)
{
MblobSelect(MilBlobResult, M_DELETE, M_AREA, M_LESS, MIN_BLOB_AREA, M_NULL);
MblobSelect(MilBlobResult, M_DELETE, M_BLOB_TOUCHING_IMAGE_BORDERS, M_NULL, M_NULL, M_NULL);
MblobSelect(MilBlobResult, M_DELETE, M_BREADTH, M_LESS, MIN_BREADTH, M_NULL);
}
void DrawBlobFixtureAndRegion(MIL_ID MilDisplay, MIL_ID MilBlobResult, MIL_ID MilFixturingOffset, MIL_ID MilRegionGraList, MIL_ID MilGraList)
{
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_DISABLE);
MgraColor(M_DEFAULT, M_COLOR_BLUE);
MblobDraw(M_DEFAULT, MilBlobResult, MilGraList, M_DRAW_BLOBS, M_DEFAULT, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_LIGHT_BLUE);
McalDraw(M_DEFAULT, M_NULL, MilGraList, M_DRAW_RELATIVE_COORDINATE_SYSTEM, M_DEFAULT, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
McalDraw(M_DEFAULT, MilFixturingOffset, MilGraList, M_DRAW_FIXTURING_OFFSET, M_DEFAULT, M_DEFAULT);
MgraCopy(MilRegionGraList, MilGraList, M_COPY + M_INDEX_VALUE, M_DEFAULT, M_ALL, M_NULL, M_NULL, M_DEFAULT);
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_ENABLE);
}
bool CalculateBlobFixturePosition(MIL_ID MilImage,
MIL_ID MilSearchImage,
MIL_ID MilBlobFeatureList,
MIL_ID MilBlobResult,
MIL_DOUBLE BlobWidth,
MIL_DOUBLE BlobHeight,
MIL_DOUBLE* pFixturePosX,
MIL_DOUBLE* pFixturePosY,
MIL_DOUBLE* pFixtureAngle)
{
BinarizeImage(MilImage, MilSearchImage);
MblobCalculate(MilSearchImage, M_NULL, MilBlobFeatureList, MilBlobResult);
DeleteImpossibleBlobs(MilBlobResult);
MblobSelect(MilBlobResult, M_DELETE, M_MIN_AREA_BOX_HEIGHT, M_OUT_RANGE, BlobHeight*MIN_DIM_FACTOR, BlobHeight*MAX_DIM_FACTOR);
MblobSelect(MilBlobResult, M_DELETE, M_MIN_AREA_BOX_WIDTH, M_OUT_RANGE, BlobWidth*MIN_DIM_FACTOR, BlobWidth*MAX_DIM_FACTOR);
MIL_INT NbBlobs = MblobGetNumber(MilBlobResult, M_NULL);
if (NbBlobs == 1)
{
MIL_INT* pBlobLabels = new MIL_INT[NbBlobs];
MblobGetResult(MilBlobResult, M_LABEL_VALUE + M_TYPE_MIL_INT, pBlobLabels);
MblobGetResultSingle(MilBlobResult, pBlobLabels[0], M_MIN_AREA_BOX_CENTER_X, pFixturePosX);
MblobGetResultSingle(MilBlobResult, pBlobLabels[0], M_MIN_AREA_BOX_CENTER_Y, pFixturePosY);
MblobGetResultSingle(MilBlobResult, pBlobLabels[0], M_MIN_AREA_BOX_ANGLE, pFixtureAngle);
delete[] pBlobLabels;
}
else
return false;
return true;
}
void ProcessImage(SProcessData* pProcessData)
{
MIL_DOUBLE StartTime = MappTimer(M_TIMER_READ, M_NULL);
MgraClear(M_DEFAULT, pProcessData->MilGraList);
MIL_DOUBLE FixturePosX;
MIL_DOUBLE FixturePosY;
MIL_DOUBLE FixtureAngle;
CalculateBlobFixturePosition(pProcessData->MilImage,
pProcessData->MilSearchImage,
pProcessData->MilSearchContext,
pProcessData->MilSearchResult,
pProcessData->BlobWidth,
pProcessData->BlobHeight,
&FixturePosX, &FixturePosY, &FixtureAngle);
McalFixture(pProcessData->MilImage, pProcessData->MilFixturingOffset, M_MOVE_RELATIVE, M_POINT_AND_ANGLE, M_DEFAULT_UNIFORM_CALIBRATION, FixturePosX, FixturePosY, FixtureAngle, M_DEFAULT);
MbufSetRegion(pProcessData->MilImage, pProcessData->MilRegionGraList, M_DEFAULT, M_NO_RASTERIZE + M_FILL_REGION, M_DEFAULT);
McodeRead(pProcessData->MilCodeContext, pProcessData->MilImage, pProcessData->MilCodeResult);
MIL_INT Status;
McodeGetResult(pProcessData->MilCodeResult, M_STATUS + M_TYPE_MIL_INT, &Status);
if (Status != M_STATUS_READ_OK)
{
McalFixture(pProcessData->MilImage, pProcessData->MilFixturingOffset, M_MOVE_RELATIVE, M_POINT_AND_ANGLE, M_DEFAULT_UNIFORM_CALIBRATION, FixturePosX, FixturePosY, FixtureAngle+180, M_DEFAULT);
McodeRead(pProcessData->MilCodeContext, pProcessData->MilImage, pProcessData->MilCodeResult);
McodeGetResult(pProcessData->MilCodeResult, M_STATUS + M_TYPE_MIL_INT, &Status);
}
MIL_DOUBLE EndTime = MappTimer(M_TIMER_READ, M_NULL);
MgraControl(M_DEFAULT, M_INPUT_UNITS, M_PIXEL);
DrawBlobFixtureAndRegion(pProcessData->MilDisplay, pProcessData->MilSearchResult, pProcessData->MilFixturingOffset, pProcessData->MilRegionGraList, pProcessData->MilGraList);
MIL_TEXT_CHAR OutputString[MAX_CODE_STRING_SIZE] = MIL_TEXT("No Code Read");
MIL_TEXT_CHAR CodeString[MAX_CODE_STRING_SIZE];
MgraColor(M_DEFAULT, M_COLOR_RED);
if (Status == M_STATUS_READ_OK)
{
McodeGetResult(pProcessData->MilCodeResult, M_STRING, CodeString);
MosSprintf(OutputString, MAX_CODE_STRING_SIZE, MIL_TEXT("Code Read: %s"), CodeString);
McodeDraw(M_DEFAULT, pProcessData->MilCodeResult, pProcessData->MilGraList, M_DRAW_CODE, M_DEFAULT, M_DEFAULT);
}
MgraControl(M_DEFAULT, M_INPUT_UNITS, M_DISPLAY);
MgraText(M_DEFAULT, pProcessData->MilGraList, 0, 0, OutputString);
MosSprintf(OutputString, MAX_CODE_STRING_SIZE, MIL_TEXT("Processing Time: %.2f ms"), (EndTime - StartTime) * 1000);
MgraText(M_DEFAULT, pProcessData->MilGraList, 0, GRA_TEXT_SIZE_Y, OutputString);
}
MIL_INT MFTYPE DigProcess(MIL_INT HookType, MIL_ID MilEvent, void* pUserData)
{
SProcessData* pProcessData = (SProcessData*)pUserData;
MdispControl(pProcessData->MilDisplay, M_UPDATE, M_DISABLE);
MIL_ID MilGrabBuffer;
MdigGetHookInfo(MilEvent, M_MODIFIED_BUFFER + M_BUFFER_ID, &MilGrabBuffer);
MbufSetRegion(pProcessData->MilImage, M_NULL, M_DEFAULT, M_DELETE, M_DEFAULT);
MbufCopy(MilGrabBuffer, pProcessData->MilImage);
ProcessImage(pProcessData);
MdispControl(pProcessData->MilDisplay, M_UPDATE, M_ENABLE);
return 0;
}