#include <mil.h>
#define EXAMPLE_IMAGE_DIR_PATH M_IMAGE_PATH MIL_TEXT("/Classification/Pasta/")
#define EXAMPLE_CLASS_CTX_PATH EXAMPLE_IMAGE_DIR_PATH MIL_TEXT("MatroxNet_PastaEx.mclass")
#define TARGET_IMAGE_DIR_PATH EXAMPLE_IMAGE_DIR_PATH MIL_TEXT("Products")
#define USE_EXAMPLE_IMAGE_FOLDER
#define BUFFERING_SIZE_MAX 10
struct ClassStruct
{
MIL_INT NbCategories,
NbOfFrames,
SourceSizeX,
SourceSizeY;
MIL_ID ClassCtx,
ClassRes,
MilDisplay,
MilDispChild,
MilOverlayImage;
};
MIL_INT MFTYPE ClassificationFunc(MIL_INT HookType,
MIL_ID EventId,
void* pHookData);
void SetupDisplay(MIL_ID MilSystem,
MIL_ID MilDisplay,
MIL_INT SourceSizeX,
MIL_INT SourceSizeY,
MIL_ID ClassCtx,
MIL_ID &MilDispImage,
MIL_ID &MilDispChild,
MIL_ID &MilOverlay,
MIL_INT NbCategories);
#ifdef USE_EXAMPLE_IMAGE_FOLDER
#define SYSTEM_TO_USE M_SYSTEM_HOST
#define DCF_TO_USE TARGET_IMAGE_DIR_PATH
#else
#define SYSTEM_TO_USE M_SYSTEM_DEFAULT
#define DCF_TO_USE MIL_TEXT("M_DEFAULT")
#endif
int main(void)
{
MIL_ID MilApplication,
MilSystem,
MilDisplay,
MilOverlay,
MilDigitizer,
MilDispImage,
MilDispChild,
ClassCtx,
ClassRes;
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX],
MilChildBufferList[BUFFERING_SIZE_MAX];
MIL_INT NumberOfCategories,
BufIndex,
SourceSizeX,
SourceSizeY,
InputSizeX,
InputSizeY;
NumberOfCategories = 0;
MappAlloc(M_NULL, M_DEFAULT, &MilApplication);
MsysAlloc(M_DEFAULT, SYSTEM_TO_USE, M_DEFAULT, M_DEFAULT, &MilSystem);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
MdigAlloc(MilSystem, M_DEFAULT, DCF_TO_USE, M_DEFAULT, &MilDigitizer);
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n"));
MosPrintf(MIL_TEXT("Mclass\n\n"));
MosPrintf(MIL_TEXT("[SYNOPSIS]\n"));
MosPrintf(MIL_TEXT("This programs shows the use of a pre-trained classification\n"));
MosPrintf(MIL_TEXT("tool to recognize product categories.\n\n"));
MosPrintf(MIL_TEXT("[MODULES USED]\n"));
MosPrintf(MIL_TEXT("Classification, Buffer, Display, Graphics, Image Processing.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n"));
MosGetchar();
MosPrintf(MIL_TEXT("Restoring the classification context from file.."));
MclassRestore(EXAMPLE_CLASS_CTX_PATH, MilSystem, M_DEFAULT, &ClassCtx);
MosPrintf(MIL_TEXT("."));
MclassPreprocess(ClassCtx, M_DEFAULT);
MosPrintf(MIL_TEXT(".ready.\n"));
MclassInquire(ClassCtx, M_CONTEXT, M_NUMBER_OF_CLASSES + M_TYPE_MIL_INT, &NumberOfCategories);
MclassInquire(ClassCtx, M_DEFAULT_SOURCE_LAYER, M_SIZE_X + M_TYPE_MIL_INT, &InputSizeX);
MclassInquire(ClassCtx, M_DEFAULT_SOURCE_LAYER, M_SIZE_Y + M_TYPE_MIL_INT, &InputSizeY);
if(NumberOfCategories > 0)
{
MosPrintf(MIL_TEXT(" - The classifier was trained to recognize %d categories\n"), NumberOfCategories);
MosPrintf(MIL_TEXT(" - The classifier was trained for %dx%d source images\n\n"), InputSizeX, InputSizeY);
MclassAllocResult(MilSystem, M_PREDICT_CNN_RESULT, M_DEFAULT, &ClassRes);
MdigInquire(MilDigitizer, M_SIZE_X, &SourceSizeX);
MdigInquire(MilDigitizer, M_SIZE_Y, &SourceSizeY);
SetupDisplay(MilSystem,
MilDisplay,
SourceSizeX,
SourceSizeY,
ClassCtx,
MilDispImage,
MilDispChild,
MilOverlay,
NumberOfCategories);
MIL_INT NumberOfFrames;
MdigInquire(MilDigitizer, M_SOURCE_NUMBER_OF_FRAMES, &NumberOfFrames);
ClassStruct ClassificationData;
ClassificationData.ClassCtx = ClassCtx;
ClassificationData.ClassRes = ClassRes;
ClassificationData.MilDisplay = MilDisplay;
ClassificationData.MilDispChild = MilDispChild;
ClassificationData.NbCategories = NumberOfCategories;
ClassificationData.MilOverlayImage = MilOverlay;
ClassificationData.SourceSizeX = SourceSizeX;
ClassificationData.SourceSizeY = SourceSizeY;
ClassificationData.NbOfFrames = NumberOfFrames;
for(BufIndex = 0; BufIndex < BUFFERING_SIZE_MAX; BufIndex++)
{
MbufAlloc2d(MilSystem, SourceSizeX, SourceSizeY, 8 + M_UNSIGNED, M_IMAGE + M_GRAB + M_PROC, &MilGrabBufferList[BufIndex]);
MbufChild2d(MilGrabBufferList[BufIndex], (SourceSizeX - InputSizeX) / 2, (SourceSizeY - InputSizeY) / 2, InputSizeX, InputSizeY, &MilChildBufferList[BufIndex]);
MobjControl(MilGrabBufferList[BufIndex], M_OBJECT_USER_DATA_PTR, &MilChildBufferList[BufIndex]);
}
if(NumberOfFrames != M_INFINITE)
MdigProcess(MilDigitizer, MilGrabBufferList, BUFFERING_SIZE_MAX, M_SEQUENCE + M_COUNT(NumberOfFrames), M_SYNCHRONOUS, &ClassificationFunc, &ClassificationData);
else
MdigProcess(MilDigitizer, MilGrabBufferList, BUFFERING_SIZE_MAX, M_START, M_DEFAULT, &ClassificationFunc, &ClassificationData);
MosPrintf(MIL_TEXT("\nPress <Enter> to exit.\n"));
MosGetch();
MdigProcess(MilDigitizer, MilGrabBufferList, BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, M_NULL, M_NULL);
MbufFree(MilDispChild);
MbufFree(MilDispImage);
for(BufIndex = 0; BufIndex < BUFFERING_SIZE_MAX; BufIndex++)
{
MbufFree(MilChildBufferList[BufIndex]);
MbufFree(MilGrabBufferList[BufIndex]);
}
MclassFree(ClassRes);
MclassFree(ClassCtx);
}
MdigFree(MilDigitizer);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
void SetupDisplay(MIL_ID MilSystem,
MIL_ID MilDisplay,
MIL_INT SourceSizeX,
MIL_INT SourceSizeY,
MIL_ID ClassCtx,
MIL_ID &MilDispImage,
MIL_ID &MilDispChild,
MIL_ID &MilOverlay,
MIL_INT NbCategories
)
{
MIL_ID MilImageLoader,
MilChildSample;
MIL_INT IconSize = SourceSizeY / NbCategories;
MilDispImage = MbufAllocColor(MilSystem, 3, SourceSizeX + IconSize, SourceSizeY, 8 + M_UNSIGNED, M_IMAGE + M_PROC + M_DISP, M_NULL);
MbufClear(MilDispImage, M_COLOR_BLACK);
MilDispChild = MbufChild2d(MilDispImage, 0, 0, SourceSizeX, SourceSizeY, M_NULL);
MgraColor(M_DEFAULT, M_COLOR_RED);
for (int iter = 0; iter < NbCategories; iter++)
{
MbufChild2d(MilDispImage, SourceSizeX, iter * IconSize, IconSize, IconSize, &MilChildSample);
MclassInquire(ClassCtx, M_CLASS_INDEX(iter), M_CLASS_ICON_ID + M_TYPE_MIL_ID, &MilImageLoader);
if (MilImageLoader != M_NULL)
{ MimResize(MilImageLoader, MilChildSample, M_FILL_DESTINATION, M_FILL_DESTINATION, M_BICUBIC + M_OVERSCAN_FAST); }
MgraRect(M_DEFAULT, MilChildSample, 0, 1, IconSize - 1, IconSize - 2);
MbufFree(MilChildSample);
}
MdispSelect(MilDisplay, MilDispImage);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MilOverlay = MdispInquire(MilDisplay, M_OVERLAY_ID, M_NULL);
}
MIL_INT MFTYPE ClassificationFunc(MIL_INT , MIL_ID EventId, void* DataPtr)
{
MIL_ID MilImage, *pMilInputImage;
MdigGetHookInfo(EventId, M_MODIFIED_BUFFER + M_BUFFER_ID, &MilImage);
ClassStruct* data = static_cast<ClassStruct*>(DataPtr);
MdispControl(data->MilDisplay, M_UPDATE, M_DISABLE);
MobjInquire(MilImage, M_OBJECT_USER_DATA_PTR, &pMilInputImage);
MbufCopy(MilImage, data->MilDispChild);
MclassPredict(data->ClassCtx, *pMilInputImage, data->ClassRes, M_DEFAULT);
MIL_DOUBLE BestScore;
MclassGetResult(data->ClassRes, M_GENERAL, M_BEST_CLASS_SCORE + M_TYPE_MIL_DOUBLE, &BestScore);
MIL_INT BestIndex;
MclassGetResult(data->ClassRes, M_GENERAL, M_BEST_CLASS_INDEX + M_TYPE_MIL_INT, &BestIndex);
MdispControl(data->MilDisplay, M_OVERLAY_CLEAR, M_TRANSPARENT_COLOR);
MIL_INT IconSize = data->SourceSizeY / data->NbCategories;
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MgraRect(M_DEFAULT, data->MilOverlayImage, data->SourceSizeX, (BestIndex*IconSize)+1, data->SourceSizeX + IconSize - 1, (BestIndex + 1)*IconSize - 2);
MIL_TEXT_CHAR Accuracy_text[256];
MosSprintf(Accuracy_text, 256, MIL_TEXT("%.1lf%% score"), BestScore);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraFont(M_DEFAULT, M_FONT_DEFAULT_SMALL);
MgraText(M_DEFAULT, data->MilOverlayImage, data->SourceSizeX+ 2, BestIndex*IconSize + 4, Accuracy_text);
MdispControl(data->MilDisplay, M_UPDATE, M_ENABLE);
if (data->NbOfFrames != M_INFINITE)
{
MosPrintf(MIL_TEXT("Press <Enter> to continue.\r"));
MosGetch();
}
return 0;
}