#include <mil.h>
#define EXAMPLE_IMAGE_PATH M_IMAGE_PATH MIL_TEXT("MultipleDatamatrixCodeRead/")
#define IMAGE_FILE EXAMPLE_IMAGE_PATH MIL_TEXT("MultipleDatamatrix.mim")
#define MAXIMUM_STRING_SIZE 100
#define TEXT_OFFSET_X -150
#define TEXT_OFFSET_Y_1 -70
#define TEXT_OFFSET_Y_2 -40
#define NB_LOOP 4
void SingleReadingExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay);
void SequentialReadingsExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay);
void ParallelReadingsExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay);
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("MultipleDatamatrixCodeRead\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example shows three techniques to locate and read several\n")
MIL_TEXT("datamatrix codes in an image:\n")
MIL_TEXT("1- Performing a single reading in the whole image.\n")
MIL_TEXT("2- Performing multiple sequential readings in regions of interest (ROIs).\n")
MIL_TEXT("3- Performing multiple parallel readings in regions of interest (ROIs).\n\n")
MIL_TEXT("[MODULES USED]\n")
MIL_TEXT("Modules used: application, system, thread, display, buffer,\n")
MIL_TEXT("image processing, blob, code, graphics.\n\n")
MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
int MosMain(void)
{
MIL_ID MilApplication,
MilSystem,
MilDisplay,
MilCodeContext,
MilCodeModel,
MilDispGraList,
MilImage;
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_WINDOWED, &MilDisplay);
McodeAlloc(MilSystem, M_DEFAULT, M_DEFAULT, &MilCodeContext);
McodeModel(MilCodeContext, M_ADD, M_DATAMATRIX, M_NULL, M_DEFAULT, &MilCodeModel);
MbufRestore(IMAGE_FILE, MilSystem, &MilImage);
MdispZoom(MilDisplay, 0.5, 0.5);
MdispSelect(MilDisplay, MilImage);
MgraAllocList(MilSystem, M_DEFAULT, &MilDispGraList);
MdispControl(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, MilDispGraList);
PrintHeader();
McodeControl(MilCodeModel, M_NUMBER, M_ALL);
SingleReadingExample(MilSystem, MilCodeContext, MilImage, MilDisplay);
McodeControl(MilCodeModel, M_NUMBER, 1);
SequentialReadingsExample(MilSystem, MilCodeContext, MilImage, MilDisplay);
ParallelReadingsExample(MilSystem, MilCodeContext, MilImage, MilDisplay);
McodeFree(MilCodeContext);
MgraFree(MilDispGraList);
MbufFree(MilImage);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
void SingleReadingExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay)
{
MIL_ID MilDispGraList,
MilCodeResult;
MIL_INT NumberOfCodes,
CodeIndex,
ReadIndex;
MIL_DOUBLE Time;
MosPrintf(MIL_TEXT("--------------------------------------------------\n"));
MosPrintf(MIL_TEXT("1- Performing a single reading in the whole image.\n\n"));
MosPrintf(MIL_TEXT("A Code Reader context is set up to locate and read an unknown\n"));
MosPrintf(MIL_TEXT("number of datamatrix codes in an image.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
McodeAllocResult(MilSystem, M_DEFAULT, &MilCodeResult);
McodeRead(MilCodeContext, MilImage, MilCodeResult);
McodeGetResult(MilCodeResult, M_NUMBER+M_TYPE_MIL_INT, &NumberOfCodes);
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_DISABLE);
MdispInquire(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, &MilDispGraList);
MgraClear(M_DEFAULT, MilDispGraList);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
McodeDraw(M_DEFAULT, MilCodeResult, MilDispGraList, M_DRAW_BOX, M_ALL, M_DEFAULT);
MosPrintf(MIL_TEXT("\n\tString\t\t\tPosition\n\t------------------------------------------\n"));
for (CodeIndex=0; CodeIndex<NumberOfCodes; CodeIndex++)
{
MIL_DOUBLE PositionX,
PositionY;
MIL_TEXT_CHAR DecodedString[MAXIMUM_STRING_SIZE];
MIL_TEXT_CHAR CharBuffer[MAXIMUM_STRING_SIZE];
McodeGetResultSingle(MilCodeResult, CodeIndex, M_POSITION_X, &PositionX);
McodeGetResultSingle(MilCodeResult, CodeIndex, M_POSITION_Y, &PositionY);
McodeGetResultSingle(MilCodeResult, CodeIndex, M_STRING, &DecodedString[0]);
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("Code%d"), CodeIndex+1);
MgraText(M_DEFAULT, MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_1, CharBuffer);
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("%s"),DecodedString);
MgraText(M_DEFAULT, MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_2, CharBuffer);
MosPrintf(MIL_TEXT("Code%d:\t%s\t(%.2f, %.2f)\n"), CodeIndex+1, DecodedString, PositionX, PositionY);
}
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_ENABLE);
MosPrintf(MIL_TEXT("\n%d datamatrix codes were read.\n"), NumberOfCodes);
MosPrintf(MIL_TEXT("\nTiming benchmark in progress; please wait ...\n"));
MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);
for (ReadIndex=0; ReadIndex<NB_LOOP; ReadIndex++)
McodeRead(MilCodeContext, MilImage, MilCodeResult);
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time);
MosPrintf(MIL_TEXT("\nThe %d codes were read in %.2f msec.\n\n"), NumberOfCodes, Time*1000/NB_LOOP);
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
McodeFree(MilCodeResult);
}
#define EXPECTED_CELL_SIZE 4.9
#define EXPECTED_CELL_NUMBER_X 16
#define EXPECTED_CELL_NUMBER_Y 16
#define EXPECTED_MAX_NUMBER_OF_CODES 50
typedef struct
{
MIL_ID MilImage;
MIL_ID MilResizedImage;
MIL_ID MilResizedBinImage;
MIL_ID MilStructElement;
MIL_ID MilBlobFeatureList;
MIL_ID MilBlobResult;
MIL_ID MilCodeContext;
MIL_ID MilCodeResult;
MIL_ID MilDispGraList;
MIL_ID MilRoiGraList;
MIL_DOUBLE ResizeFactor;
MIL_INT NumberOfCodes;
bool IsTimerActive;
} SEQUENTIAL_PROC_PARAM;
void SequentialInit(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilDisplay, MIL_ID MilImage, SEQUENTIAL_PROC_PARAM &ProcParamPtr);
void SequentialFree(SEQUENTIAL_PROC_PARAM &ProcParamPtr);
void SequentialProcessing(SEQUENTIAL_PROC_PARAM &ProcParamPtr);
void SequentialReadingsExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay)
{
MIL_INT ReadIndex;
MIL_DOUBLE Time;
SEQUENTIAL_PROC_PARAM ProcessingParam;
SequentialInit(MilSystem, MilCodeContext, MilDisplay, MilImage, ProcessingParam);
MosPrintf(MIL_TEXT("---------------------------------------------------\n"));
MosPrintf(MIL_TEXT("2- Performing multiple sequential readings in ROIs.\n\n"));
MosPrintf(MIL_TEXT("A Code Reader context is set up to read a single datamatrix code.\n"));
MosPrintf(MIL_TEXT("A custom preprocessing algorithm is used to locate potential\n"));
MosPrintf(MIL_TEXT("datamatrix codes and to define an ROI around each one.\n"));
MosPrintf(MIL_TEXT("The reading is performed for each ROI sequentially.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MosPrintf(MIL_TEXT("\n\tString\t\t\tPosition\n\t------------------------------------------\n"));
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_DISABLE);
SequentialProcessing(ProcessingParam);
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_ENABLE);
MosPrintf(MIL_TEXT("\nA total of %d datamatrix codes were read.\n"), ProcessingParam.NumberOfCodes);
ProcessingParam.IsTimerActive = true;
MosPrintf(MIL_TEXT("\nTiming benchmark in progress; please wait ...\n"));
MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);
for (ReadIndex=0; ReadIndex<NB_LOOP; ReadIndex++)
{
ProcessingParam.NumberOfCodes = 0;
SequentialProcessing(ProcessingParam);
}
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time);
MosPrintf(MIL_TEXT("\nThe %d codes were read with sequential readings in %.2f msec.\n\n"), ProcessingParam.NumberOfCodes, Time*1000/NB_LOOP);
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
SequentialFree(ProcessingParam);
}
void SequentialInit(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilDisplay, MIL_ID MilImage, SEQUENTIAL_PROC_PARAM &ProcParamPtr)
{
MIL_INT BufSizeX,
BufSizeY,
BufType,
NewBufSizeX,
NewBufSizeY;
McodeAllocResult(MilSystem, M_DEFAULT, &ProcParamPtr.MilCodeResult);
MblobAllocFeatureList(MilSystem, &ProcParamPtr.MilBlobFeatureList);
MblobSelectFeature(ProcParamPtr.MilBlobFeatureList, M_AREA);
MblobSelectFeature(ProcParamPtr.MilBlobFeatureList, M_BOX);
MblobAllocResult(MilSystem, &ProcParamPtr.MilBlobResult);
MblobControl(ProcParamPtr.MilBlobResult, M_IDENTIFIER_TYPE, M_BINARY);
MbufInquire(MilImage, M_SIZE_X, &BufSizeX);
MbufInquire(MilImage, M_SIZE_Y, &BufSizeY);
MbufInquire(MilImage, M_TYPE, &BufType);
ProcParamPtr.ResizeFactor = 1/EXPECTED_CELL_SIZE;
NewBufSizeX = (MIL_INT) (BufSizeX * ProcParamPtr.ResizeFactor);
NewBufSizeY = (MIL_INT) (BufSizeY * ProcParamPtr.ResizeFactor);
MbufAlloc2d(MilSystem, NewBufSizeX, NewBufSizeY, BufType, M_IMAGE+M_PROC, &ProcParamPtr.MilResizedImage);
MbufAlloc2d(MilSystem, NewBufSizeX, NewBufSizeY, 1+M_UNSIGNED, M_IMAGE+M_PROC, &ProcParamPtr.MilResizedBinImage);
MbufAlloc2d(MilSystem, 3, 3, 32+M_UNSIGNED, M_STRUCT_ELEMENT, &ProcParamPtr.MilStructElement);
MbufClear(ProcParamPtr.MilStructElement, 1);
MdispInquire(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, &ProcParamPtr.MilDispGraList);
MgraClear(M_DEFAULT, ProcParamPtr.MilDispGraList);
MgraAllocList(MilSystem, M_DEFAULT, &ProcParamPtr.MilRoiGraList);
ProcParamPtr.NumberOfCodes = 0;
ProcParamPtr.IsTimerActive = false;
ProcParamPtr.MilImage = MilImage;
ProcParamPtr.MilCodeContext = MilCodeContext;
}
void SequentialFree(SEQUENTIAL_PROC_PARAM &ProcParamPtr)
{
McodeFree(ProcParamPtr.MilCodeResult);
MgraFree(ProcParamPtr.MilRoiGraList);
MbufFree(ProcParamPtr.MilResizedBinImage);
MbufFree(ProcParamPtr.MilStructElement);
MbufFree(ProcParamPtr.MilResizedImage);
MblobFree(ProcParamPtr.MilBlobResult);
MblobFree(ProcParamPtr.MilBlobFeatureList);
}
void SequentialProcessing(SEQUENTIAL_PROC_PARAM &ProcParamPtr)
{
MIL_INT NumberOfBlobs;
MIL_DOUBLE ExpectedAreaMin,
ExpectedAreaMax;
MimResize(ProcParamPtr.MilImage, ProcParamPtr.MilResizedImage, ProcParamPtr.ResizeFactor, ProcParamPtr.ResizeFactor, M_NEAREST_NEIGHBOR+M_OVERSCAN_ENABLE+M_FAST);
MimMorphic(ProcParamPtr.MilResizedImage, ProcParamPtr.MilResizedImage, ProcParamPtr.MilStructElement, M_BOTTOM_HAT, 5, M_GRAYSCALE);
MimBinarize(ProcParamPtr.MilResizedImage, ProcParamPtr.MilResizedBinImage, M_BIMODAL+M_GREATER_OR_EQUAL, M_NULL, M_NULL);
MimDilate(ProcParamPtr.MilResizedBinImage, ProcParamPtr.MilResizedBinImage, 1, M_BINARY);
MblobCalculate(ProcParamPtr.MilResizedBinImage, M_NULL, ProcParamPtr.MilBlobFeatureList, ProcParamPtr.MilBlobResult);
ExpectedAreaMin = (EXPECTED_CELL_NUMBER_X * EXPECTED_CELL_NUMBER_Y * 0.8);
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_AREA, M_LESS, ExpectedAreaMin, M_NULL);
ExpectedAreaMax = EXPECTED_CELL_NUMBER_X * EXPECTED_CELL_NUMBER_Y*1.3;
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_AREA, M_GREATER, ExpectedAreaMax, M_NULL);
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_BOX_ASPECT_RATIO, M_OUT_RANGE, 0.85, 1.15);
MblobGetNumber(ProcParamPtr.MilBlobResult, &NumberOfBlobs);
if (NumberOfBlobs > 0)
{
MIL_INT BlobIndex,
*BoxXMin,
*BoxXMax,
*BoxYMin,
*BoxYMax;
BoxXMin = new MIL_INT[NumberOfBlobs];
BoxXMax = new MIL_INT[NumberOfBlobs];
BoxYMin = new MIL_INT[NumberOfBlobs];
BoxYMax = new MIL_INT[NumberOfBlobs];
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_X_MIN+M_TYPE_MIL_INT, &BoxXMin[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_X_MAX+M_TYPE_MIL_INT, &BoxXMax[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_Y_MIN+M_TYPE_MIL_INT, &BoxYMin[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_Y_MAX+M_TYPE_MIL_INT, &BoxYMax[0]);
for(BlobIndex=0; BlobIndex<NumberOfBlobs; BlobIndex++)
{
MIL_INT CodeReadStatus;
MIL_INT Margin = 3;
MIL_INT BoxStartX = (MIL_INT)((BoxXMin[BlobIndex] * (1/ProcParamPtr.ResizeFactor))-(Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxStartY = (MIL_INT)((BoxYMin[BlobIndex] * (1/ProcParamPtr.ResizeFactor))-(Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxSizeX = (MIL_INT)(((BoxXMax[BlobIndex] - BoxXMin[BlobIndex])*(1/ProcParamPtr.ResizeFactor))+(2*Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxSizeY = (MIL_INT)(((BoxYMax[BlobIndex] - BoxYMin[BlobIndex])*(1/ProcParamPtr.ResizeFactor))+(2*Margin*EXPECTED_CELL_SIZE));
MgraClear(M_DEFAULT, ProcParamPtr.MilRoiGraList);
MgraRectAngle(M_DEFAULT, ProcParamPtr.MilRoiGraList, BoxStartX, BoxStartY, BoxSizeX, BoxSizeY, 0, M_CORNER_AND_DIMENSION+M_FILLED);
MbufSetRegion(ProcParamPtr.MilImage, ProcParamPtr.MilRoiGraList, M_DEFAULT, M_NO_RASTERIZE, M_DEFAULT);
McodeRead(ProcParamPtr.MilCodeContext, ProcParamPtr.MilImage, ProcParamPtr.MilCodeResult);
McodeGetResult(ProcParamPtr.MilCodeResult, M_STATUS+M_TYPE_MIL_INT, &CodeReadStatus);
if (CodeReadStatus == M_STATUS_READ_OK)
{
if (!ProcParamPtr.IsTimerActive)
{
MIL_DOUBLE PositionX,
PositionY;
MIL_TEXT_CHAR DecodedString[MAXIMUM_STRING_SIZE];
MIL_TEXT_CHAR CharBuffer[MAXIMUM_STRING_SIZE];
McodeGetResult(ProcParamPtr.MilCodeResult, M_STRING, &DecodedString[0]);
McodeGetResult(ProcParamPtr.MilCodeResult, M_POSITION_X, &PositionX);
McodeGetResult(ProcParamPtr.MilCodeResult, M_POSITION_Y, &PositionY);
MgraColor(M_DEFAULT, M_COLOR_CYAN);
McodeDraw(M_DEFAULT, ProcParamPtr.MilCodeResult, ProcParamPtr.MilDispGraList, M_DRAW_BOX, M_ALL, M_DEFAULT);
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("Code%d"), ProcParamPtr.NumberOfCodes+1);
MgraText(M_DEFAULT, ProcParamPtr.MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_1, CharBuffer);
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("%s"), DecodedString);
MgraText(M_DEFAULT, ProcParamPtr.MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_2, CharBuffer);
MosPrintf(MIL_TEXT("Code%d:\t%s\t(%.2f, %.2f)\n"), ProcParamPtr.NumberOfCodes+1, DecodedString, PositionX, PositionY);
}
ProcParamPtr.NumberOfCodes++;
}
}
MbufSetRegion(ProcParamPtr.MilImage, M_NULL, M_DEFAULT, M_DELETE, M_DEFAULT);
delete []BoxXMin;
delete []BoxXMax;
delete []BoxYMin;
delete []BoxYMax;
}
}
#define MAXIMUM_NUMBER_OF_CODES 50
typedef struct SBoxParam
{
MIL_INT MinX;
MIL_INT MinY;
MIL_INT MaxX;
MIL_INT MaxY;
}BOX_PARAM;
typedef struct SThreadParam
{
MIL_ID MilThread;
MIL_ID MilImage;
MIL_ID MilCodeContext;
MIL_ID MilCodeResult;
MIL_ID MilRoiGraList;
MIL_ID ReadyEvent;
MIL_ID DoneEvent;
MIL_INT NumberOfCodes;
MIL_INT ReadStatus;
bool DoExit;
MIL_DOUBLE ResizeFactor;
BOX_PARAM BlobBox;
MIL_TEXT_CHAR* CodesRead[MAXIMUM_NUMBER_OF_CODES];
MIL_DOUBLE PosX[MAXIMUM_NUMBER_OF_CODES];
MIL_DOUBLE PosY[MAXIMUM_NUMBER_OF_CODES];
} THREAD_PARAM;
typedef struct
{
MIL_ID MilImage;
MIL_ID MilResizedImage;
MIL_ID MilResizedBinImage;
MIL_ID MilStructElement;
MIL_ID MilBlobFeatureList;
MIL_ID MilBlobResult;
MIL_ID MilDispGraList;
MIL_ID* DoneEventPtr;
MIL_INT NumProcCores;
MIL_INT InitialMpUse;
MIL_DOUBLE ResizeFactor;
bool IsTimerActive;
THREAD_PARAM *ThreadParam;
} PARALLEL_PROC_PARAM;
void ParallelInit(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilDisplay, MIL_ID MilImage, PARALLEL_PROC_PARAM &ProcParamPtr);
void ParallelFree(PARALLEL_PROC_PARAM &ProcParamPtr);
void ParallelProcessing(PARALLEL_PROC_PARAM &ProcParamPtr);
void ParallelGetResults(THREAD_PARAM &ThreadParamPtr, MIL_ID MilDispGraList);
MIL_UINT32 MFTYPE ParallelProcessingThread(void *ThreadParam);
void ParallelReadingsExample(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilImage, MIL_ID MilDisplay)
{
MIL_INT ReadIndex,
ThreadIndex,
TotalNumberOfCodes;
MIL_DOUBLE Time;
PARALLEL_PROC_PARAM ProcessingParam;
ParallelInit(MilSystem, MilCodeContext, MilDisplay, MilImage, ProcessingParam);
MosPrintf(MIL_TEXT("-------------------------------------------------\n"));
MosPrintf(MIL_TEXT("3- Performing multiple parallel readings in ROIs.\n\n"));
MosPrintf(MIL_TEXT("A Code Reader context is set up to read a single datamatrix code.\n"));
MosPrintf(MIL_TEXT("A custom preprocessing algorithm is used to locate potential\n"));
MosPrintf(MIL_TEXT("datamatrix codes and to define an ROI around each one.\n"));
MosPrintf(MIL_TEXT("Readings are then performed for several ROIs on parallel threads.\n"));
MosPrintf(MIL_TEXT("The number of threads used is equal to the number of cores\n"));
MosPrintf(MIL_TEXT("available on the system.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MosPrintf(MIL_TEXT("\n\t\tString\t\t\tPosition\n\t\t------------------------------------------\n"));
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_DISABLE);
ParallelProcessing(ProcessingParam);
MdispControl(MilDisplay, M_UPDATE_GRAPHIC_LIST, M_ENABLE);
TotalNumberOfCodes = 0;
MosPrintf(MIL_TEXT("\n"));
for (ThreadIndex=0; ThreadIndex<ProcessingParam.NumProcCores; ThreadIndex++)
{
MosPrintf(MIL_TEXT("A total of %d datamatrix codes were read in thread %d.\n"), ProcessingParam.ThreadParam[ThreadIndex].NumberOfCodes, ThreadIndex+1);
TotalNumberOfCodes+=ProcessingParam.ThreadParam[ThreadIndex].NumberOfCodes;
}
ProcessingParam.IsTimerActive = true;
MosPrintf(MIL_TEXT("\nTiming benchmark in progress; please wait ...\n"));
MappTimer(M_DEFAULT, M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);
for (ReadIndex=0; ReadIndex<NB_LOOP; ReadIndex++)
{
ParallelProcessing(ProcessingParam);
}
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &Time);
MosPrintf(MIL_TEXT("\nThe %d codes were read with parallel readings in %.2f msec.\n\n"), TotalNumberOfCodes, Time*1000/NB_LOOP);
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
ParallelFree(ProcessingParam);
}
void ParallelInit(MIL_ID MilSystem, MIL_ID MilCodeContext, MIL_ID MilDisplay, MIL_ID MilImage, PARALLEL_PROC_PARAM &ProcParamPtr)
{
MIL_INT BufSizeX,
BufSizeY,
BufType,
NewBufSizeX,
NewBufSizeY,
ContextByteSize,
ThreadIndex;
MIL_TEXT_CHAR* MemPtr = NULL;
MblobAllocFeatureList(MilSystem, &ProcParamPtr.MilBlobFeatureList);
MblobSelectFeature(ProcParamPtr.MilBlobFeatureList, M_AREA);
MblobSelectFeature(ProcParamPtr.MilBlobFeatureList, M_BOX);
MblobAllocResult(MilSystem, &ProcParamPtr.MilBlobResult);
MblobControl(ProcParamPtr.MilBlobResult, M_IDENTIFIER_TYPE, M_BINARY);
ProcParamPtr.MilImage = MilImage;
MbufInquire(MilImage, M_SIZE_X, &BufSizeX);
MbufInquire(MilImage, M_SIZE_Y, &BufSizeY);
MbufInquire(MilImage, M_TYPE, &BufType);
ProcParamPtr.ResizeFactor = 1/EXPECTED_CELL_SIZE;
NewBufSizeX = (MIL_INT) (BufSizeX * ProcParamPtr.ResizeFactor);
NewBufSizeY = (MIL_INT) (BufSizeY * ProcParamPtr.ResizeFactor);
MbufAlloc2d(MilSystem, NewBufSizeX, NewBufSizeY, BufType, M_IMAGE+M_PROC, &ProcParamPtr.MilResizedImage);
MbufAlloc2d(MilSystem, NewBufSizeX, NewBufSizeY, 1+M_UNSIGNED, M_IMAGE+M_PROC, &ProcParamPtr.MilResizedBinImage);
MbufAlloc2d(MilSystem, 3, 3, 32+M_UNSIGNED, M_STRUCT_ELEMENT, &ProcParamPtr.MilStructElement);
MbufClear(ProcParamPtr.MilStructElement, 1);
MdispInquire(MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, &ProcParamPtr.MilDispGraList);
MgraClear(M_DEFAULT, ProcParamPtr.MilDispGraList);
ProcParamPtr.IsTimerActive = false;
MappInquireMp(M_DEFAULT, M_MP_USE, M_DEFAULT, M_DEFAULT, &ProcParamPtr.InitialMpUse);
MappInquireMp(M_DEFAULT, M_CORE_NUM_PROCESS, M_DEFAULT, M_NULL, &ProcParamPtr.NumProcCores);
if ((ProcParamPtr.NumProcCores > 1) && (ProcParamPtr.InitialMpUse == M_ENABLE))
{
MappControlMp(M_DEFAULT, M_MP_USE, M_DEFAULT, M_DISABLE, M_NULL);
}
ProcParamPtr.ThreadParam = new THREAD_PARAM[ProcParamPtr.NumProcCores];
ProcParamPtr.DoneEventPtr = new MIL_ID[ProcParamPtr.NumProcCores];
McodeStream(M_NULL , MilSystem, M_INQUIRE_SIZE_BYTE, M_MEMORY, M_DEFAULT, M_DEFAULT, &MilCodeContext, &ContextByteSize);
MemPtr = new MIL_TEXT_CHAR[ContextByteSize];
McodeStream(MemPtr, M_NULL, M_SAVE, M_MEMORY, M_DEFAULT, M_DEFAULT, &MilCodeContext, &ContextByteSize);
for (ThreadIndex=0; ThreadIndex<ProcParamPtr.NumProcCores; ThreadIndex++)
{
MIL_INT CodeIndex;
McodeStream(MemPtr , MilSystem, M_RESTORE, M_MEMORY, M_DEFAULT, M_DEFAULT, &ProcParamPtr.ThreadParam[ThreadIndex].MilCodeContext, &ContextByteSize);
ProcParamPtr.ThreadParam[ThreadIndex].DoExit = false;
ProcParamPtr.ThreadParam[ThreadIndex].ResizeFactor = ProcParamPtr.ResizeFactor;
McodeAllocResult(MilSystem, M_DEFAULT, &ProcParamPtr.ThreadParam[ThreadIndex].MilCodeResult);
MbufAlloc2d(MilSystem, BufSizeX, BufSizeY, BufType, M_IMAGE+M_PROC, &ProcParamPtr.ThreadParam[ThreadIndex].MilImage);
MbufCopy(MilImage, ProcParamPtr.ThreadParam[ThreadIndex].MilImage);
MgraAllocList(MilSystem, M_DEFAULT, &ProcParamPtr.ThreadParam[ThreadIndex].MilRoiGraList);
MthrAlloc(MilSystem, M_EVENT, M_NOT_SIGNALED+M_AUTO_RESET, M_NULL, M_NULL, &ProcParamPtr.ThreadParam[ThreadIndex].ReadyEvent);
ProcParamPtr.DoneEventPtr[ThreadIndex] = MthrAlloc(MilSystem, M_EVENT, M_NOT_SIGNALED+M_AUTO_RESET, M_NULL, M_NULL, &ProcParamPtr.ThreadParam[ThreadIndex].DoneEvent);
for (CodeIndex=0; CodeIndex<MAXIMUM_NUMBER_OF_CODES; CodeIndex++)
ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex] = NULL;
MthrAlloc(MilSystem, M_THREAD, M_DEFAULT, &ParallelProcessingThread, &ProcParamPtr.ThreadParam[ThreadIndex], &ProcParamPtr.ThreadParam[ThreadIndex].MilThread);
}
delete []MemPtr;
}
void ParallelFree(PARALLEL_PROC_PARAM &ProcParamPtr)
{
MIL_ID ThreadIndex;
if (ProcParamPtr.InitialMpUse == M_ENABLE)
MappControlMp(M_DEFAULT, M_MP_USE, M_DEFAULT, M_ENABLE, M_NULL);
MbufFree(ProcParamPtr.MilResizedBinImage);
MbufFree(ProcParamPtr.MilStructElement);
MbufFree(ProcParamPtr.MilResizedImage);
MblobFree(ProcParamPtr.MilBlobResult);
MblobFree(ProcParamPtr.MilBlobFeatureList);
for (ThreadIndex=0; ThreadIndex<ProcParamPtr.NumProcCores; ThreadIndex++)
{
MIL_INT CodeIndex;
ProcParamPtr.ThreadParam[ThreadIndex].DoExit = true;
MthrControl(ProcParamPtr.ThreadParam[ThreadIndex].ReadyEvent, M_EVENT_SET, M_SIGNALED);
MthrWait(ProcParamPtr.ThreadParam[ThreadIndex].DoneEvent, M_EVENT_WAIT, M_NULL);
McodeFree(ProcParamPtr.ThreadParam[ThreadIndex].MilCodeContext);
McodeFree(ProcParamPtr.ThreadParam[ThreadIndex].MilCodeResult);
MgraFree(ProcParamPtr.ThreadParam[ThreadIndex].MilRoiGraList);
MbufFree(ProcParamPtr.ThreadParam[ThreadIndex].MilImage);
MthrFree(ProcParamPtr.ThreadParam[ThreadIndex].ReadyEvent);
MthrFree(ProcParamPtr.ThreadParam[ThreadIndex].DoneEvent);
for (CodeIndex=0; CodeIndex<MAXIMUM_NUMBER_OF_CODES; CodeIndex++)
{
if (ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex] != NULL)
{
delete []ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex];
ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex] = NULL;
}
}
MthrFree(ProcParamPtr.ThreadParam[ThreadIndex].MilThread);
}
delete []ProcParamPtr.DoneEventPtr;
delete []ProcParamPtr.ThreadParam;
}
void ParallelProcessing(PARALLEL_PROC_PARAM &ProcParamPtr)
{
MIL_INT NumberOfBlobs;
MIL_ID ThreadIndex;
MIL_DOUBLE ExpectedAreaMin,
ExpectedAreaMax;
for (ThreadIndex=0; ThreadIndex<ProcParamPtr.NumProcCores; ThreadIndex++)
{
ProcParamPtr.ThreadParam[ThreadIndex].NumberOfCodes = 0;
ProcParamPtr.ThreadParam[ThreadIndex].ReadStatus = M_STATUS_NOT_FOUND;
MthrControl(ProcParamPtr.ThreadParam[ThreadIndex].DoneEvent, M_EVENT_SET, M_SIGNALED);
}
MimResize(ProcParamPtr.MilImage, ProcParamPtr.MilResizedImage, ProcParamPtr.ResizeFactor, ProcParamPtr.ResizeFactor, M_NEAREST_NEIGHBOR+M_OVERSCAN_ENABLE+M_FAST);
MimMorphic(ProcParamPtr.MilResizedImage, ProcParamPtr.MilResizedImage, ProcParamPtr.MilStructElement, M_BOTTOM_HAT, 5, M_GRAYSCALE);
MimBinarize(ProcParamPtr.MilResizedImage, ProcParamPtr.MilResizedBinImage, M_BIMODAL+M_GREATER_OR_EQUAL, M_NULL, M_NULL);
MimDilate(ProcParamPtr.MilResizedBinImage, ProcParamPtr.MilResizedBinImage, 1, M_BINARY);
MblobCalculate(ProcParamPtr.MilResizedBinImage, M_NULL, ProcParamPtr.MilBlobFeatureList, ProcParamPtr.MilBlobResult);
ExpectedAreaMin = (EXPECTED_CELL_NUMBER_X * EXPECTED_CELL_NUMBER_Y * 0.8);
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_AREA, M_LESS, ExpectedAreaMin, M_NULL);
ExpectedAreaMax = EXPECTED_CELL_NUMBER_X * EXPECTED_CELL_NUMBER_Y*1.3;
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_AREA, M_GREATER, ExpectedAreaMax, M_NULL);
MblobSelect(ProcParamPtr.MilBlobResult, M_EXCLUDE, M_BOX_ASPECT_RATIO, M_OUT_RANGE, 0.85, 1.15);
MblobGetNumber(ProcParamPtr.MilBlobResult, &NumberOfBlobs);
if (NumberOfBlobs > 0)
{
MIL_INT BlobIndex,
ThreadIndex,
EventIndex,
*BoxXMin,
*BoxXMax,
*BoxYMin,
*BoxYMax;
BoxXMin = new MIL_INT[NumberOfBlobs];
BoxXMax = new MIL_INT[NumberOfBlobs];
BoxYMin = new MIL_INT[NumberOfBlobs];
BoxYMax = new MIL_INT[NumberOfBlobs];
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_X_MIN+M_TYPE_MIL_INT, &BoxXMin[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_X_MAX+M_TYPE_MIL_INT, &BoxXMax[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_Y_MIN+M_TYPE_MIL_INT, &BoxYMin[0]);
MblobGetResult(ProcParamPtr.MilBlobResult, M_BOX_Y_MAX+M_TYPE_MIL_INT, &BoxYMax[0]);
for (BlobIndex=0; BlobIndex<NumberOfBlobs; BlobIndex++ )
{
MthrWaitMultiple(&ProcParamPtr.DoneEventPtr[0], ProcParamPtr.NumProcCores, M_EVENT_WAIT, &EventIndex);
if (!ProcParamPtr.IsTimerActive)
{
if (ProcParamPtr.ThreadParam[EventIndex].ReadStatus == M_STATUS_READ_OK)
{
ParallelGetResults(ProcParamPtr.ThreadParam[EventIndex], ProcParamPtr.MilDispGraList);
}
}
ProcParamPtr.ThreadParam[EventIndex].BlobBox.MinX = BoxXMin[BlobIndex];
ProcParamPtr.ThreadParam[EventIndex].BlobBox.MinY = BoxYMin[BlobIndex];
ProcParamPtr.ThreadParam[EventIndex].BlobBox.MaxX = BoxXMax[BlobIndex];
ProcParamPtr.ThreadParam[EventIndex].BlobBox.MaxY = BoxYMax[BlobIndex];
MthrControl(ProcParamPtr.ThreadParam[EventIndex].ReadyEvent, M_EVENT_SET, M_SIGNALED);
}
MthrWaitMultiple(&ProcParamPtr.DoneEventPtr[0], ProcParamPtr.NumProcCores, M_EVENT_WAIT+M_ALL_OBJECTS, M_NULL);
if (!ProcParamPtr.IsTimerActive)
{
MIL_INT CodeIndex;
MIL_TEXT_CHAR CharBuffer[MAXIMUM_STRING_SIZE];
for (ThreadIndex=0; ThreadIndex<ProcParamPtr.NumProcCores; ThreadIndex++)
{
ParallelGetResults(ProcParamPtr.ThreadParam[ThreadIndex], ProcParamPtr.MilDispGraList);
for (CodeIndex=0; CodeIndex<ProcParamPtr.ThreadParam[ThreadIndex].NumberOfCodes; CodeIndex++)
{
MIL_DOUBLE PositionX = ProcParamPtr.ThreadParam[ThreadIndex].PosX[CodeIndex];
MIL_DOUBLE PositionY = ProcParamPtr.ThreadParam[ThreadIndex].PosY[CodeIndex];
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("Thread%d_Code%d"), ThreadIndex+1, CodeIndex);
MgraText(M_DEFAULT, ProcParamPtr.MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_1, CharBuffer);
MosSprintf(CharBuffer, MAXIMUM_STRING_SIZE, MIL_TEXT("%s"),ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex]);
MgraText(M_DEFAULT, ProcParamPtr.MilDispGraList, PositionX+TEXT_OFFSET_X, PositionY+TEXT_OFFSET_Y_2, CharBuffer);
MosPrintf(MIL_TEXT("Thread%d Code%d\t%s\t(%.2f, %.2f)\n"), ThreadIndex+1, CodeIndex+1, ProcParamPtr.ThreadParam[ThreadIndex].CodesRead[CodeIndex], PositionX, PositionY);
}
}
}
delete []BoxXMin;
delete []BoxXMax;
delete []BoxYMin;
delete []BoxYMax;
}
}
MIL_UINT32 MFTYPE ParallelProcessingThread(void *ThreadParameters)
{
THREAD_PARAM *ThreadParam = (THREAD_PARAM *)ThreadParameters;
while(!ThreadParam->DoExit)
{
MthrWait(ThreadParam->ReadyEvent, M_EVENT_WAIT, M_NULL);
if (!ThreadParam->DoExit)
{
MIL_INT Margin = 3;
MIL_INT BoxStartX = (MIL_INT)((ThreadParam->BlobBox.MinX * (1/ThreadParam->ResizeFactor))-(Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxStartY = (MIL_INT)((ThreadParam->BlobBox.MinY * (1/ThreadParam->ResizeFactor))-(Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxSizeX = (MIL_INT)(((ThreadParam->BlobBox.MaxX - ThreadParam->BlobBox.MinX)*(1/ThreadParam->ResizeFactor))+(2*Margin*EXPECTED_CELL_SIZE));
MIL_INT BoxSizeY = (MIL_INT)(((ThreadParam->BlobBox.MaxY - ThreadParam->BlobBox.MinY)*(1/ThreadParam->ResizeFactor))+(2*Margin*EXPECTED_CELL_SIZE));
MgraClear(M_DEFAULT, ThreadParam->MilRoiGraList);
MgraRectAngle(M_DEFAULT, ThreadParam->MilRoiGraList, BoxStartX, BoxStartY, BoxSizeX, BoxSizeY, 0, M_CORNER_AND_DIMENSION+M_FILLED);
MbufSetRegion(ThreadParam->MilImage, ThreadParam->MilRoiGraList, M_DEFAULT, M_NO_RASTERIZE, M_DEFAULT);
McodeRead(ThreadParam->MilCodeContext, ThreadParam->MilImage, ThreadParam->MilCodeResult);
McodeGetResult(ThreadParam->MilCodeResult, M_STATUS+M_TYPE_MIL_INT, &ThreadParam->ReadStatus);
if (ThreadParam->ReadStatus == M_STATUS_READ_OK)
ThreadParam->NumberOfCodes++;
}
MthrControl(ThreadParam->DoneEvent, M_EVENT_SET, M_SIGNALED);
}
return(1);
}
void ParallelGetResults(THREAD_PARAM &ThreadParamPtr, MIL_ID MilDispGraList)
{
MIL_INT CodeIndex = ThreadParamPtr.NumberOfCodes-1;
if(ThreadParamPtr.CodesRead[CodeIndex] == NULL)
ThreadParamPtr.CodesRead[CodeIndex] = new MIL_TEXT_CHAR[MAXIMUM_STRING_SIZE];
McodeGetResult(ThreadParamPtr.MilCodeResult, M_STRING, ThreadParamPtr.CodesRead[CodeIndex]);
McodeGetResult(ThreadParamPtr.MilCodeResult, M_POSITION_X, &ThreadParamPtr.PosX[CodeIndex]);
McodeGetResult(ThreadParamPtr.MilCodeResult, M_POSITION_Y, &ThreadParamPtr.PosY[CodeIndex]);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
McodeDraw(M_DEFAULT, ThreadParamPtr.MilCodeResult, MilDispGraList, M_DRAW_BOX, M_ALL, M_DEFAULT);
}