#include <mil.h>
#define EXAMPLE_IMAGE_PATH M_IMAGE_PATH MIL_TEXT("BlobAnalysis/BlobMerge/")
#define SEQUENCE_FILE EXAMPLE_IMAGE_PATH MIL_TEXT("BlobMerge.avi")
#define DISPLAY_X_OFFSET 300
void MFTYPE OfflineMergeHook(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
void OfflineBlobAnalysis(void* HookDataPtr);
void MFTYPE OnlineMergeAndBlobAnalysisHook(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
void OnlineDrawBlobResults(void* HookDataPtr, MIL_ID BlobResultId);
void OfflineExample();
void OnlineExample();
typedef struct
{
MIL_ID MilGrabDisp;
MIL_ID MilBinImage;
MIL_ID MilDispImage;
MIL_ID MilDisplayBlobMerge;
MIL_ID MilGraphicList;
MIL_ID MilBlobFeatureList;
MIL_ID MilPreviousBlobResult;
MIL_ID MilCurrentBlobResult;
MIL_ID MilDestinationBlobResult;
MIL_INT SizeX;
MIL_INT SizeY;
MIL_INT ImageCount;
} HookDataStruct;
#define BUFFERING_SIZE 5
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("BlobMerge\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example shows two approaches to merge blob results from\n")
MIL_TEXT("vertically adjacent buffers.\n\n")
MIL_TEXT("\n[MODULES USED]\n")
MIL_TEXT("Modules used: application, system, display, buffer,\n")
MIL_TEXT("blob, graphics, image processing.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
int MosMain(void)
{
PrintHeader();
OfflineExample();
OnlineExample();
}
void OfflineExample()
{
MosPrintf(MIL_TEXT("\n------------------------------------------------------------------"));
MosPrintf(MIL_TEXT("\n1- Off-line analysis:\n\n"));
MosPrintf(MIL_TEXT("Blobs from all vertically adjacent buffers are merged into a single\n"));
MosPrintf(MIL_TEXT("result buffer; subsequently, a blob analysis is performed.\n\n"));
MosPrintf(MIL_TEXT("\nPress <Enter> to start accumulating the blobs.\n\n"));
MosGetch();
MIL_ID MilApplication = M_NULL,
MilSystem = M_NULL,
MilDigitizer = M_NULL,
MilDisplay = M_NULL,
MilDisplayBlobMerge = M_NULL,
MilImage = M_NULL,
MilBinImage = M_NULL,
MilDispImage = M_NULL,
MilBlobFeatureList = M_NULL,
MilPreviousBlobResult = M_NULL,
MilCurrentBlobResult = M_NULL,
MilDestinationBlobResult= M_NULL,
MilGraphicList = M_NULL;
MIL_ID MilGrabBufferList[BUFFERING_SIZE] = { 0 };
HookDataStruct UserHookData;
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);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, &MilDisplayBlobMerge);
MdigAlloc(MilSystem, M_DEFAULT, SEQUENCE_FILE, M_EMULATED, &MilDigitizer);
MIL_INT SizeX = MdigInquire(MilDigitizer, M_SIZE_X, M_NULL);
MIL_INT SizeY = MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8+M_UNSIGNED, M_IMAGE+M_DISP, &MilImage);
MdispControl(MilDisplay, M_TITLE, M_PTR_TO_DOUBLE(MIL_TEXT("Grab image")));
MbufClear(MilImage, 0L);
MbufAlloc2d(MilSystem, SizeX, SizeY, 1+M_UNSIGNED, M_IMAGE+M_PROC, &MilBinImage);
MbufAlloc2d(MilSystem, SizeX, SizeY*BUFFERING_SIZE, 8+M_UNSIGNED, M_IMAGE+M_DISP,
&MilDispImage);
MdispControl(MilDisplayBlobMerge, M_TITLE, M_PTR_TO_DOUBLE(MIL_TEXT("Off-line blob merge")));
MdispControl(MilDisplayBlobMerge, M_WINDOW_INITIAL_POSITION_X, DISPLAY_X_OFFSET);
MgraAllocList(MilSystem, M_DEFAULT, &MilGraphicList);
MdispControl(MilDisplayBlobMerge, M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraphicList);
MblobAllocFeatureList(MilSystem, &MilBlobFeatureList);
MblobSelectFeature(MilBlobFeatureList, M_BOX);
MblobSelectFeature(MilBlobFeatureList, M_CENTER_OF_GRAVITY);
MblobAllocResult(MilSystem, &MilPreviousBlobResult);
MblobAllocResult(MilSystem, &MilCurrentBlobResult);
MblobAllocResult(MilSystem, &MilDestinationBlobResult);
MIL_INT MilGrabBufferListSize;
for(MilGrabBufferListSize = 0; MilGrabBufferListSize < BUFFERING_SIZE;
MilGrabBufferListSize++)
{
MbufAlloc2d(MilSystem, SizeX, SizeY, 8+M_UNSIGNED, M_IMAGE+M_GRAB+M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]);
}
UserHookData.MilGrabDisp = MilImage;
UserHookData.MilBinImage = MilBinImage;
UserHookData.MilBlobFeatureList = MilBlobFeatureList;
UserHookData.MilPreviousBlobResult = MilPreviousBlobResult;
UserHookData.MilCurrentBlobResult = MilCurrentBlobResult;
UserHookData.MilDestinationBlobResult = MilDestinationBlobResult;
UserHookData.MilDispImage = MilDispImage;
UserHookData.MilGraphicList = MilGraphicList;
UserHookData.SizeX = SizeX;
UserHookData.SizeY = SizeY;
UserHookData.ImageCount = 0;
MdispSelect(MilDisplayBlobMerge, MilDispImage);
MdispSelect(MilDisplay, MilImage);
MdigProcess(MilDigitizer, MilGrabBufferList, BUFFERING_SIZE, M_SEQUENCE, M_DEFAULT,
(MIL_DIG_HOOK_FUNCTION_PTR)OfflineMergeHook, &UserHookData);
OfflineBlobAnalysis(&UserHookData);
MosPrintf(MIL_TEXT("\nPress <Enter> to continue.\n\n"));
MosGetch();
while(MilGrabBufferListSize > 0)
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
MblobFree(MilDestinationBlobResult);
MblobFree(MilCurrentBlobResult);
MblobFree(MilPreviousBlobResult);
MblobFree(MilBlobFeatureList);
MgraFree(MilGraphicList);
MbufFree(MilDispImage);
MbufFree(MilBinImage);
MbufFree(MilImage);
MdigFree(MilDigitizer);
MdispFree(MilDisplayBlobMerge);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
}
void MFTYPE OfflineMergeHook(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
MIL_ID BufferId, tempId;
HookDataStruct * UserHookDataPtr = (HookDataStruct *)HookDataPtr;
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &BufferId);
MbufCopy(BufferId, UserHookDataPtr->MilGrabDisp);
MbufCopyClip(BufferId, UserHookDataPtr->MilDispImage, 0, UserHookDataPtr->SizeY *
UserHookDataPtr->ImageCount);
MimBinarize(BufferId, UserHookDataPtr->MilBinImage, M_BIMODAL+M_LESS, M_NULL, M_NULL);
if (UserHookDataPtr->ImageCount > 0)
{
MosPrintf(MIL_TEXT("The blobs from the current frame are extracted"));
MblobCalculate(UserHookDataPtr->MilBinImage, M_NULL, UserHookDataPtr->MilBlobFeatureList,
UserHookDataPtr->MilCurrentBlobResult);
MosPrintf(MIL_TEXT(" and merged\ninto the destination result buffer.\n"));
MblobMerge(UserHookDataPtr->MilPreviousBlobResult, UserHookDataPtr->MilCurrentBlobResult,
UserHookDataPtr->MilDestinationBlobResult, M_MOVE);
}
else
{
MosPrintf(MIL_TEXT("The blobs from the current frame are extracted.\n"));
MblobCalculate(UserHookDataPtr->MilBinImage, M_NULL, UserHookDataPtr->MilBlobFeatureList,
UserHookDataPtr->MilDestinationBlobResult);
}
MgraClear(M_DEFAULT, UserHookDataPtr->MilGraphicList);
MgraColor(M_DEFAULT, M_COLOR_BLUE);
MblobDraw(M_DEFAULT, UserHookDataPtr->MilDestinationBlobResult,
UserHookDataPtr->MilGraphicList, M_DRAW_BLOBS, M_INCLUDED_BLOBS, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
for(MIL_INT j=1; j<=UserHookDataPtr->ImageCount; j++)
MgraLine(M_DEFAULT, UserHookDataPtr->MilGraphicList, 0,UserHookDataPtr->SizeY*j,
UserHookDataPtr->SizeX-1, UserHookDataPtr->SizeY*j);
tempId = UserHookDataPtr->MilPreviousBlobResult;
UserHookDataPtr->MilPreviousBlobResult = UserHookDataPtr->MilDestinationBlobResult;
UserHookDataPtr->MilDestinationBlobResult = tempId;
UserHookDataPtr->ImageCount++;
MosPrintf(MIL_TEXT("\nPress <Enter> to load the next frame.\n\n"));
MosGetch();
}
void OfflineBlobAnalysis(void* HookDataPtr)
{
HookDataStruct * UserHookDataPtr = (HookDataStruct *)HookDataPtr;
MosPrintf(MIL_TEXT("\nAll the blobs have been extracted from all frames.\n"));
MblobSelect(UserHookDataPtr->MilPreviousBlobResult, M_EXCLUDE, M_BLOB_TOUCHING_IMAGE_BORDERS, M_NULL, M_NULL,M_NULL);
MgraClear(M_DEFAULT, UserHookDataPtr->MilGraphicList);
MgraColor(M_DEFAULT, M_COLOR_BLUE);
MblobDraw(M_DEFAULT, UserHookDataPtr->MilPreviousBlobResult,
UserHookDataPtr->MilGraphicList, M_DRAW_BLOBS, M_INCLUDED_BLOBS, M_DEFAULT);
MIL_INT TotalBlobs = MblobGetNumber(UserHookDataPtr->MilPreviousBlobResult, M_NULL);
MosPrintf(MIL_TEXT("\nThe top and bottom-touching partial blobs are excluded.\n"));
MosPrintf(MIL_TEXT("Blob features are calculated and displayed.\n"));
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MblobDraw(M_DEFAULT, UserHookDataPtr->MilPreviousBlobResult,
UserHookDataPtr->MilGraphicList, M_DRAW_CENTER_OF_GRAVITY,
M_INCLUDED_BLOBS, M_DEFAULT);
};
void OnlineExample()
{
MosPrintf(MIL_TEXT("\n-----------------------------------------------------------------------"));
MosPrintf(MIL_TEXT("\n2- On-line analysis:\n\n"));
MosPrintf(MIL_TEXT("Blobs from the current frame are merged with the bottom-touching partial\n"));
MosPrintf(MIL_TEXT("blobs from the previous frame. The bottom-touching partial blobs from\n"));
MosPrintf(MIL_TEXT("the current frame are excluded. Then the merged blobs are analyzed.\n"));
MosPrintf(MIL_TEXT("\nPress <Enter> to start the operation.\n\n"));
MosGetch();
MIL_ID MilApplication = M_NULL,
MilSystem = M_NULL,
MilDigitizer = M_NULL,
MilDisplay = M_NULL,
MilDisplayBlobMerge = M_NULL,
MilImage = M_NULL,
MilBinImage = M_NULL,
MilDispImage = M_NULL,
MilBlobFeatureList = M_NULL,
MilPreviousBlobResult = M_NULL,
MilCurrentBlobResult = M_NULL,
MilDestinationBlobResult= M_NULL,
MilGraphicList = M_NULL;
MIL_ID MilGrabBufferList[BUFFERING_SIZE] = { 0 };
HookDataStruct UserHookData;
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);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, &MilDisplayBlobMerge);
MdigAlloc(MilSystem, M_DEFAULT, SEQUENCE_FILE, M_EMULATED, &MilDigitizer);
MIL_INT SizeX = MdigInquire(MilDigitizer, M_SIZE_X, M_NULL);
MIL_INT SizeY = MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL);
MbufAlloc2d(MilSystem, SizeX, SizeY, 8+M_UNSIGNED, M_IMAGE+M_DISP, &MilImage);
MbufClear(MilImage, 0x0);
MdispControl(MilDisplay, M_TITLE, M_PTR_TO_DOUBLE(MIL_TEXT("Grab image")));
MbufAlloc2d(MilSystem, SizeX, SizeY, 1+M_UNSIGNED, M_IMAGE+M_PROC, &MilBinImage);
MblobAllocFeatureList(MilSystem, &MilBlobFeatureList);
MblobSelectFeature(MilBlobFeatureList, M_BOX);
MblobSelectFeature(MilBlobFeatureList, M_CENTER_OF_GRAVITY);
MblobAllocResult(MilSystem, &MilPreviousBlobResult);
MblobAllocResult(MilSystem, &MilCurrentBlobResult);
MblobAllocResult(MilSystem, &MilDestinationBlobResult);
MbufAlloc2d(MilSystem, SizeX, SizeY*2, 8+M_UNSIGNED, M_IMAGE+M_DISP, &MilDispImage);
MdispControl(MilDisplayBlobMerge, M_TITLE, M_PTR_TO_DOUBLE(MIL_TEXT("On-line blob merge")));
MdispControl(MilDisplayBlobMerge, M_WINDOW_INITIAL_POSITION_X, DISPLAY_X_OFFSET);
MbufClear(MilDispImage, 0);
MgraAllocList(MilSystem, M_DEFAULT, &MilGraphicList);
MdispControl(MilDisplayBlobMerge, M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraphicList);
UserHookData.MilGrabDisp = MilImage;
UserHookData.MilBinImage = MilBinImage;
UserHookData.MilBlobFeatureList = MilBlobFeatureList;
UserHookData.MilPreviousBlobResult = MilPreviousBlobResult;
UserHookData.MilCurrentBlobResult = MilCurrentBlobResult;
UserHookData.MilDestinationBlobResult = MilDestinationBlobResult;
UserHookData.MilDisplayBlobMerge = MilDisplayBlobMerge;
UserHookData.MilDispImage = MilDispImage;
UserHookData.MilGraphicList = MilGraphicList;
UserHookData.SizeX = SizeX;
UserHookData.SizeY = SizeY;
UserHookData.ImageCount = 0;
MIL_INT MilGrabBufferListSize;
for(MilGrabBufferListSize = 0; MilGrabBufferListSize < BUFFERING_SIZE;
MilGrabBufferListSize++)
{
MbufAlloc2d(MilSystem, SizeX, SizeY, 8+M_UNSIGNED, M_IMAGE+M_GRAB+M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]);
}
MdispSelect(MilDisplay, MilImage);
MdispSelect(MilDisplayBlobMerge, MilDispImage);
MdigProcess(MilDigitizer, MilGrabBufferList, BUFFERING_SIZE, M_SEQUENCE, M_DEFAULT,
(MIL_DIG_HOOK_FUNCTION_PTR)OnlineMergeAndBlobAnalysisHook, &UserHookData);
MosPrintf(MIL_TEXT("\nPress <Enter> to end.\n\n"));
MosGetch();
MgraFree(MilGraphicList);
MbufFree(MilDispImage);
while(MilGrabBufferListSize > 0)
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
MblobFree(MilDestinationBlobResult);
MblobFree(MilCurrentBlobResult);
MblobFree(MilPreviousBlobResult);
MblobFree(MilBlobFeatureList);
MbufFree(MilBinImage);
MbufFree(MilImage);
MdigFree(MilDigitizer);
MdispFree(MilDisplayBlobMerge);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);}
void MFTYPE OnlineMergeAndBlobAnalysisHook(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
HookDataStruct * UserHookDataPtr = (HookDataStruct *)HookDataPtr;
MIL_ID BufferId, TempId;
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &BufferId);
MbufCopy(BufferId, UserHookDataPtr->MilGrabDisp);
if(UserHookDataPtr->ImageCount > 0)
{
MbufCopyClip(BufferId, UserHookDataPtr->MilDispImage, 0, UserHookDataPtr->SizeY);
MdispControl(UserHookDataPtr->MilDisplayBlobMerge, M_UPDATE, M_ENABLE);
MosPrintf(MIL_TEXT("The blobs from the current frame are extracted.\n"));
MimBinarize(BufferId, UserHookDataPtr->MilBinImage, M_BIMODAL+M_LESS, M_NULL, M_NULL);
MblobCalculate(UserHookDataPtr->MilBinImage, M_NULL, UserHookDataPtr->MilBlobFeatureList,
UserHookDataPtr->MilCurrentBlobResult);
MosPrintf(MIL_TEXT("The blobs are merged with the bottom-touching blobs from the"));
MosPrintf(MIL_TEXT(" previous frame.\n"));
MblobSelect(UserHookDataPtr->MilPreviousBlobResult, M_INCLUDE_ONLY, M_EXCLUDED_BLOBS,
M_NULL, M_NULL, M_NULL);
MblobMerge(UserHookDataPtr->MilPreviousBlobResult, UserHookDataPtr->MilCurrentBlobResult,
UserHookDataPtr->MilDestinationBlobResult, M_COPY);
OnlineDrawBlobResults(HookDataPtr, UserHookDataPtr->MilDestinationBlobResult);
MosPrintf(MIL_TEXT("\nPress <Enter> to load the next frame.\n\n"));
MosGetch();
MdispControl(UserHookDataPtr->MilDisplayBlobMerge, M_UPDATE, M_DISABLE);
MbufCopy(BufferId, UserHookDataPtr->MilDispImage);
}
else
{
MbufCopy(BufferId, UserHookDataPtr->MilDispImage);
MosPrintf(MIL_TEXT("The blobs from the current frame are extracted.\n"));
MimBinarize(BufferId, UserHookDataPtr->MilBinImage, M_BIMODAL+M_LESS, M_NULL, M_NULL);
MblobCalculate(UserHookDataPtr->MilBinImage, M_NULL, UserHookDataPtr->MilBlobFeatureList,
UserHookDataPtr->MilCurrentBlobResult);
OnlineDrawBlobResults(HookDataPtr, UserHookDataPtr->MilCurrentBlobResult);
MosPrintf(MIL_TEXT("\nPress <Enter> to load the next frame.\n\n"));
MosGetch();
}
TempId = UserHookDataPtr->MilPreviousBlobResult;
UserHookDataPtr->MilPreviousBlobResult = UserHookDataPtr->MilCurrentBlobResult;
UserHookDataPtr->MilCurrentBlobResult = TempId;
MblobSelect(UserHookDataPtr->MilPreviousBlobResult, M_EXCLUDE, M_BLOB_TOUCHING_IMAGE_BORDERS,
M_NULL, M_NULL, M_NULL);
UserHookDataPtr->ImageCount++;
}
void OnlineDrawBlobResults(void* HookDataPtr, MIL_ID BlobResultId)
{
HookDataStruct * UserHookDataPtr = (HookDataStruct *)HookDataPtr;
MblobSelect(BlobResultId, M_EXCLUDE, M_BLOB_TOUCHING_IMAGE_BORDERS , M_NULL, M_NULL, M_NULL);
MgraColor(M_DEFAULT, M_COLOR_BLUE);
MgraClear(M_DEFAULT, UserHookDataPtr->MilGraphicList);
MblobDraw(M_DEFAULT, BlobResultId, UserHookDataPtr->MilGraphicList, M_DRAW_BLOBS,
M_INCLUDED_BLOBS, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MblobDraw(M_DEFAULT, BlobResultId, UserHookDataPtr->MilGraphicList, M_DRAW_CENTER_OF_GRAVITY,
M_INCLUDED_BLOBS, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MgraLine(M_DEFAULT, UserHookDataPtr->MilGraphicList, 0, UserHookDataPtr->SizeY,
UserHookDataPtr->SizeX-1, UserHookDataPtr->SizeY);
MIL_INT TotalBlobs = MblobGetNumber(BlobResultId, M_NULL);
MosPrintf(MIL_TEXT("%d blobs have been found and analyzed from acquisition #%d.\n\n"),
TotalBlobs, UserHookDataPtr->ImageCount+1);
}