#include <mil.h>
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("SuperResolutionCode\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example aligns a sequence of images containing bar codes\n")
MIL_TEXT("and combines them with a super-resolution process to form\n")
MIL_TEXT("an enhanced image, which is then used to decode the bar codes.\n\n")
MIL_TEXT("[MODULES USED]\n")
MIL_TEXT("Modules used: application, system, display, buffer,\n")
MIL_TEXT("graphics, sequence, registration, code reader.\n\n")
MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
}
struct SSequenceDescription
{
MIL_CONST_TEXT_PTR Filename;
MIL_INT StartImage;
MIL_INT NumberOfImages;
MIL_INT ChildOffsetX;
MIL_INT ChildOffsetY;
MIL_INT ChildSizeX;
MIL_INT ChildSizeY;
MIL_DOUBLE PsfRadius;
MIL_INT PsfType;
MIL_DOUBLE Smoothness;
};
class CSuperResolution
{
public:
CSuperResolution(MIL_ID MilSystem);
~CSuperResolution();
void InitializeWithFirstImage(MIL_ID MilFirstImage,
MIL_INT NumberOfImages,
MIL_INT ChildOffsetX, MIL_INT ChildOffsetY,
MIL_INT ChildSizeX, MIL_INT ChildSizeY);
bool AddImage(MIL_ID MilImage);
void SuperResolution(MIL_DOUBLE PsfRadius, MIL_INT PsfType, MIL_DOUBLE Smoothness);
protected:
void InitializeDisplay(MIL_ID MilFirstImage, MIL_INT ChildSizeX, MIL_INT ChildSizeY);
void DrawCurrentResult();
MIL_ID m_MilSystem;
MIL_ID m_MilRegContext;
MIL_ID m_MilRegResult;
MIL_ID* m_MilSequenceImageTable;
MIL_ID* m_MilPartialSequenceImageTable;
MIL_INT m_NumberOfImagesInTable;
MIL_INT m_NumberOfAllocatedTableElements;
MIL_ID m_MilDisplay;
MIL_ID m_MilOverlayImage;
MIL_ID m_MilFullDisplayImage;
MIL_ID m_MilTrackingImage;
MIL_ID m_MilZoomedWithSuperResolutionImage;
MIL_ID m_MilTrackingOverlayImage;
MIL_INT m_FirstImageChildOffsetX;
MIL_INT m_FirstImageChildOffsetY;
};
#define EXAMPLE_SEQUENCE_PATH M_IMAGE_PATH MIL_TEXT("SuperResolutionCode/")
#define SEQUENCE_FILE EXAMPLE_SEQUENCE_PATH MIL_TEXT("code_far.avi")
static const SSequenceDescription Sequences = {
SEQUENCE_FILE,
0,
8,
80,
10,
200,
110,
0.5,
M_SQUARE,
30.0
};
static const MIL_DOUBLE MOSAIC_SCALE = 2.0;
template <class T>
inline T Max(T InValue1, T InValue2)
{
if (InValue1 > InValue2)
return InValue1;
else
return InValue2;
}
int MosMain(void)
{
MIL_ID MilApplication = MappAlloc(M_NULL, M_DEFAULT, M_NULL);
MIL_ID MilSystem = MsysAlloc(M_DEFAULT, M_SYSTEM_HOST, M_DEFAULT, M_DEFAULT, &MilSystem);
PrintHeader();
{
MbufImportSequence(Sequences.Filename, M_DEFAULT, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_OPEN);
MIL_INT NumberOfImagesInSequence = MbufDiskInquire(Sequences.Filename, M_NUMBER_OF_IMAGES, M_NULL);
MIL_DOUBLE FrameRate;
MbufDiskInquire(Sequences.Filename, M_FRAME_RATE, &FrameRate);
MIL_ID MilSequenceImage;
MbufImportSequence(Sequences.Filename, M_DEFAULT, M_RESTORE, MilSystem, &MilSequenceImage,
Sequences.StartImage, 1, M_READ);
MIL_INT FrameIndex = 1;
CSuperResolution SuperResolution(MilSystem);
SuperResolution.InitializeWithFirstImage(MilSequenceImage, Sequences.NumberOfImages,
Sequences.ChildOffsetX, Sequences.ChildOffsetY, Sequences.ChildSizeX, Sequences.ChildSizeY);
MosPrintf(MIL_TEXT("A sequence of images is captured at different focus distance using,\n")
MIL_TEXT("for example, a liquid lens optic.\n\n")
MIL_TEXT("A rectangular region defines the ROI used to perform the image alignment.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MosPrintf(MIL_TEXT("Aligning...\n"));
MIL_DOUBLE PreviousTime;
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &PreviousTime);
bool Success = true;
while (Success && FrameIndex < Sequences.NumberOfImages)
{
MbufImportSequence(Sequences.Filename, M_DEFAULT,
M_LOAD, M_NULL, &MilSequenceImage,
M_DEFAULT, 1, M_READ);
Success = SuperResolution.AddImage(MilSequenceImage);
FrameIndex++;
MIL_DOUBLE EndTime;
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &EndTime);
MIL_DOUBLE WaitTime = (1.0/FrameRate) - (EndTime - PreviousTime);
if (WaitTime > 0)
MappTimer(M_DEFAULT, M_TIMER_WAIT, &WaitTime);
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &PreviousTime);
}
MosPrintf(MIL_TEXT("\n%d images have been aligned with the first one.\n\n"), Sequences.NumberOfImages-1);
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
SuperResolution.SuperResolution(Sequences.PsfRadius, Sequences.PsfType, Sequences.Smoothness);
MosPrintf(MIL_TEXT("\nPress <Enter> to end.\n"));
MosGetch();
MbufFree(MilSequenceImage);
MbufImportSequence(Sequences.Filename, M_DEFAULT, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_CLOSE);
}
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
CSuperResolution::CSuperResolution(MIL_ID MilSystem) :
m_MilSystem (MilSystem),
m_MilRegContext (M_NULL),
m_MilRegResult (M_NULL),
m_MilSequenceImageTable (NULL),
m_MilPartialSequenceImageTable (NULL),
m_NumberOfImagesInTable (0),
m_NumberOfAllocatedTableElements (0),
m_MilDisplay (M_NULL),
m_MilOverlayImage (M_NULL),
m_MilFullDisplayImage (M_NULL),
m_MilTrackingImage (M_NULL),
m_MilZoomedWithSuperResolutionImage (M_NULL),
m_MilTrackingOverlayImage (M_NULL),
m_FirstImageChildOffsetX (0),
m_FirstImageChildOffsetY (0)
{
}
CSuperResolution::~CSuperResolution()
{
while (m_NumberOfImagesInTable)
{
m_NumberOfImagesInTable--;
MbufFree(m_MilSequenceImageTable[m_NumberOfImagesInTable]);
}
delete [] m_MilPartialSequenceImageTable;
delete [] m_MilSequenceImageTable;
if (m_MilRegResult != M_NULL)
MregFree(m_MilRegResult);
if (m_MilRegContext != M_NULL)
MregFree(m_MilRegContext);
MbufFree(m_MilTrackingOverlayImage);
MbufFree(m_MilZoomedWithSuperResolutionImage);
MbufFree(m_MilTrackingImage);
MbufFree(m_MilFullDisplayImage);
MdispFree(m_MilDisplay);
}
void CSuperResolution::InitializeWithFirstImage(MIL_ID MilFirstImage,
MIL_INT NumberOfImages,
MIL_INT ChildOffsetX, MIL_INT ChildOffsetY,
MIL_INT ChildSizeX, MIL_INT ChildSizeY)
{
MregAlloc(m_MilSystem, M_STITCHING, M_DEFAULT, &m_MilRegContext);
MregAllocResult(m_MilSystem, M_DEFAULT, &m_MilRegResult);
MregControl(m_MilRegContext, M_CONTEXT, M_NUMBER_OF_REGISTRATION_ELEMENTS, NumberOfImages);
m_FirstImageChildOffsetX = ChildOffsetX;
m_FirstImageChildOffsetY = ChildOffsetY;
m_MilSequenceImageTable = new MIL_ID[NumberOfImages];
m_MilPartialSequenceImageTable = new MIL_ID[NumberOfImages];
m_NumberOfAllocatedTableElements = NumberOfImages;
m_NumberOfImagesInTable = 0;
InitializeDisplay(MilFirstImage, ChildSizeX, ChildSizeY);
MbufCopy(MilFirstImage, m_MilFullDisplayImage);
MgraRectAngle(M_DEFAULT, m_MilOverlayImage, ChildOffsetX, ChildOffsetY, ChildSizeX-1,
ChildSizeY-1, 0, M_CORNER_AND_DIMENSION);
MbufAlloc2d(m_MilSystem, ChildSizeX, ChildSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC,
&(m_MilSequenceImageTable[0]));
m_NumberOfImagesInTable++;
MbufCopyClip(MilFirstImage, m_MilSequenceImageTable[0], -ChildOffsetX, -ChildOffsetY);
MregCalculate(m_MilRegContext, m_MilSequenceImageTable,
m_MilRegResult, m_NumberOfImagesInTable, M_DEFAULT);
MregSetLocation(m_MilRegContext, m_NumberOfImagesInTable, 0, M_POSITION_XY,
static_cast<MIL_DOUBLE>(-ChildOffsetX), static_cast<MIL_DOUBLE>(-ChildOffsetY),
M_DEFAULT, M_DEFAULT, M_DEFAULT);
}
bool CSuperResolution::AddImage(MIL_ID MilImage)
{
if (m_NumberOfImagesInTable >= m_NumberOfAllocatedTableElements)
return false;
MbufCopy(MilImage, m_MilFullDisplayImage);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_STATIC_INDEX, m_NumberOfImagesInTable-1);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_X, 0);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_Y, 0);
m_MilSequenceImageTable[m_NumberOfImagesInTable] = MbufAlloc2d(
MbufInquire(MilImage, M_OWNER_SYSTEM, M_NULL),
MbufInquire(MilImage, M_SIZE_X , M_NULL),
MbufInquire(MilImage, M_SIZE_Y , M_NULL),
MbufInquire(MilImage, M_TYPE , M_NULL),
M_IMAGE+M_PROC,
M_NULL);
MbufCopy(MilImage, m_MilSequenceImageTable[m_NumberOfImagesInTable]);
m_NumberOfImagesInTable++;
m_MilPartialSequenceImageTable[0] = m_MilSequenceImageTable[0];
for (MIL_INT i = 1; i < m_NumberOfImagesInTable-1; i++)
m_MilPartialSequenceImageTable[i] = M_NULL;
m_MilPartialSequenceImageTable[m_NumberOfImagesInTable-1] = m_MilSequenceImageTable[m_NumberOfImagesInTable-1];
MregControl(m_MilRegContext, M_CONTEXT, M_TRANSFORMATION_TYPE, M_TRANSLATION);
MregCalculate(m_MilRegContext, m_MilPartialSequenceImageTable,
m_MilRegResult, m_NumberOfImagesInTable, M_DEFAULT);
MIL_INT Status;
MregGetResult(m_MilRegResult, M_GENERAL, M_RESULT+M_TYPE_MIL_INT, &Status);
if (Status != M_SUCCESS)
return false;
MregSetLocation(m_MilRegContext,
M_ALL, M_UNCHANGED,
M_COPY_REG_RESULT,
m_MilRegResult,
M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT);
MregControl(m_MilRegContext, M_CONTEXT, M_TRANSFORMATION_TYPE, M_TRANSLATION_ROTATION_SCALE);
MregCalculate(m_MilRegContext, m_MilPartialSequenceImageTable,
m_MilRegResult, m_NumberOfImagesInTable, M_DEFAULT);
MregGetResult(m_MilRegResult, M_GENERAL, M_RESULT+M_TYPE_MIL_INT, &Status);
if (Status != M_SUCCESS)
return false;
MregSetLocation(m_MilRegContext, M_ALL, M_UNCHANGED, M_COPY_REG_RESULT, m_MilRegResult,
M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT);
if (m_NumberOfImagesInTable < m_NumberOfAllocatedTableElements)
{
MregSetLocation(m_MilRegContext,
m_NumberOfImagesInTable, 0,
M_COPY_REG_RESULT,
m_MilRegResult,
static_cast<MIL_DOUBLE>(m_NumberOfImagesInTable-1), 0,
M_DEFAULT, M_DEFAULT);
}
DrawCurrentResult();
return true;
}
#define STRING_LENGTH_MAX 64L
#define TEXT_WIDTH 140
#define TEXT_HEIGHT 20
#define DRAW_CODE_Y_OFFSET 30
void CSuperResolution::SuperResolution(MIL_DOUBLE PsfRadius, MIL_INT PsfType, MIL_DOUBLE Smoothness)
{
MbufClear(m_MilTrackingOverlayImage, (MIL_DOUBLE)(MdispInquire(m_MilDisplay, M_TRANSPARENT_COLOR, M_NULL)));
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_STATIC_INDEX, 0);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_SCALE , MOSAIC_SCALE);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_X, 0);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_Y, 0);
MregControl(m_MilRegResult, M_GENERAL, M_SR_PSF_RADIUS, PsfRadius);
MregControl(m_MilRegResult, M_GENERAL, M_SR_PSF_TYPE , PsfType);
MregControl(m_MilRegResult, M_GENERAL, M_SR_SMOOTHNESS, Smoothness);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_COMPOSITION, M_SUPER_RESOLUTION);
MregTransformImage(m_MilRegResult, m_MilSequenceImageTable, m_MilZoomedWithSuperResolutionImage,
m_NumberOfImagesInTable, M_BILINEAR, M_DEFAULT);
MgraText(M_DEFAULT, m_MilOverlayImage, MbufInquire(m_MilZoomedWithSuperResolutionImage, M_ANCESTOR_OFFSET_X, M_NULL)
+MbufInquire(m_MilZoomedWithSuperResolutionImage, M_SIZE_X, M_NULL)-TEXT_WIDTH,
MbufInquire(m_MilZoomedWithSuperResolutionImage, M_SIZE_Y, M_NULL), MIL_TEXT("Super-resolution"));
MosPrintf(MIL_TEXT("The aligned images are combined in a higher resolution image using\n")
MIL_TEXT("a super-resolution process.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MIL_ID Barcode = McodeAlloc(m_MilSystem, M_DEFAULT, M_DEFAULT, M_NULL);
MIL_ID BarModel = McodeModel(Barcode, M_ADD, M_CODE128, M_NULL, M_DEFAULT, M_NULL);
MIL_ID CodeResults = McodeAllocResult(m_MilSystem, M_DEFAULT, M_NULL);
McodeRead(Barcode, m_MilZoomedWithSuperResolutionImage, CodeResults);
MIL_INT BarcodeStatus;
McodeGetResult(CodeResults, M_GENERAL, M_GENERAL, M_STATUS+M_TYPE_MIL_INT, &BarcodeStatus);
MIL_TEXT_CHAR BarcodeString[STRING_LENGTH_MAX];
MIL_DOUBLE PositionX, PositionY;
if (BarcodeStatus == M_STATUS_READ_OK)
{
McodeGetResult(CodeResults, 0, M_GENERAL, M_STRING, BarcodeString);
McodeGetResult(CodeResults, 0, M_GENERAL, M_POSITION_X, &PositionX);
McodeGetResult(CodeResults, 0, M_GENERAL, M_POSITION_Y, &PositionY);
McodeDraw(M_DEFAULT, CodeResults, m_MilTrackingOverlayImage, M_DRAW_POSITION, M_ALL, M_GENERAL, M_DEFAULT);
MgraText(M_DEFAULT, m_MilTrackingOverlayImage, PositionX, PositionY+DRAW_CODE_Y_OFFSET, BarcodeString);
}
MIL_INT NumOfModels = McodeInquire(Barcode, M_NUMBER_OF_CODE_MODELS, M_NULL);
McodeModel(Barcode, M_DELETE, M_NULL, M_NULL, M_DEFAULT, &BarModel);
NumOfModels = McodeInquire(Barcode, M_NUMBER_OF_CODE_MODELS, M_NULL);
McodeModel(Barcode, M_ADD, M_4_STATE, M_NULL, M_DEFAULT, M_NULL);
McodeControl(Barcode, M_ENCODING, M_ENC_AUSTRALIA_MAIL_RAW);
McodeRead(Barcode, m_MilZoomedWithSuperResolutionImage, CodeResults);
McodeGetResult(CodeResults, M_GENERAL, M_GENERAL, M_STATUS+M_TYPE_MIL_INT, &BarcodeStatus);
if (BarcodeStatus == M_STATUS_READ_OK)
{
McodeGetResult(CodeResults, 0, M_GENERAL, M_STRING, BarcodeString);
McodeGetResult(CodeResults, 0, M_GENERAL, M_POSITION_X, &PositionX);
McodeGetResult(CodeResults, 0, M_GENERAL, M_POSITION_Y, &PositionY);
McodeDraw(M_DEFAULT, CodeResults, m_MilTrackingOverlayImage, M_DRAW_POSITION, M_ALL, M_GENERAL, M_DEFAULT);
MgraText(M_DEFAULT, m_MilTrackingOverlayImage, PositionX, PositionY+DRAW_CODE_Y_OFFSET, BarcodeString);
}
MosPrintf(MIL_TEXT("The codes are read from the resulting super-resolution image.\n"));
McodeFree(CodeResults);
McodeFree(Barcode);
}
void CSuperResolution::InitializeDisplay(MIL_ID MilFirstImage, MIL_INT ChildSizeX, MIL_INT ChildSizeY)
{
m_MilDisplay = MdispAlloc(m_MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, M_NULL);
MdispControl(m_MilDisplay, M_OVERLAY, M_ENABLE);
MIL_INT SequenceImageSizeX = MbufInquire(MilFirstImage, M_SIZE_X, M_NULL);
MIL_INT SequenceImageSizeY = MbufInquire(MilFirstImage, M_SIZE_Y, M_NULL);
MIL_INT ZoomedChildSizeX = static_cast<MIL_INT>(ChildSizeX * MOSAIC_SCALE);
MIL_INT ZoomedChildSizeY = static_cast<MIL_INT>(ChildSizeY * MOSAIC_SCALE);
MIL_INT FullDisplayImageSizeX = SequenceImageSizeX + Max(ZoomedChildSizeX, SequenceImageSizeX);
MIL_INT FullDisplayImageSizeY = Max(SequenceImageSizeY, ZoomedChildSizeY);
m_MilFullDisplayImage = MbufAlloc2d(m_MilSystem, FullDisplayImageSizeX, FullDisplayImageSizeY,
8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, M_NULL);
MbufClear(m_MilFullDisplayImage, M_COLOR_BLACK);
MdispSelect(m_MilDisplay, m_MilFullDisplayImage);
MdispInquire(m_MilDisplay, M_OVERLAY_ID, &m_MilOverlayImage);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MgraText(M_DEFAULT, m_MilOverlayImage, SequenceImageSizeX-TEXT_WIDTH, SequenceImageSizeY-TEXT_HEIGHT, MIL_TEXT("Source image"));
m_MilTrackingImage = MbufChild2d(m_MilFullDisplayImage, SequenceImageSizeX, 0,
SequenceImageSizeX, SequenceImageSizeY, M_NULL);
m_MilTrackingOverlayImage = MbufChild2d(m_MilOverlayImage, SequenceImageSizeX, 0,
SequenceImageSizeX, SequenceImageSizeY, M_NULL);
m_MilZoomedWithSuperResolutionImage = MbufChild2d(m_MilFullDisplayImage, SequenceImageSizeX, 0,
ZoomedChildSizeX, ZoomedChildSizeY, M_NULL);
}
void CSuperResolution::DrawCurrentResult()
{
MIL_INT i;
for (i = 0; i < m_NumberOfImagesInTable-1; i++)
m_MilPartialSequenceImageTable[i] = M_NULL;
m_MilPartialSequenceImageTable[m_NumberOfImagesInTable-1] = m_MilSequenceImageTable[m_NumberOfImagesInTable-1];
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_COMPOSITION, M_LAST_IMAGE);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_X, m_FirstImageChildOffsetX);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_Y, m_FirstImageChildOffsetY);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_STATIC_INDEX, 0);
MregTransformImage(m_MilRegResult, m_MilPartialSequenceImageTable, m_MilTrackingImage, m_NumberOfImagesInTable,
M_BILINEAR+M_OVERSCAN_CLEAR, M_DEFAULT);
if(m_NumberOfImagesInTable==2)
{
MregDraw(M_DEFAULT, m_MilRegResult, m_MilTrackingOverlayImage, M_DRAW_BOX, 0, M_DEFAULT);
MgraText(M_DEFAULT, m_MilTrackingOverlayImage, MbufInquire(m_MilTrackingOverlayImage, M_SIZE_X, M_NULL)-TEXT_WIDTH,
MbufInquire(m_MilTrackingOverlayImage, M_SIZE_Y, M_NULL)-TEXT_HEIGHT, MIL_TEXT("Realigned image"));
}
}