#include <mil.h>
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("SuperResolution\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example aligns all images in a video sequence\n")
MIL_TEXT("with the child of the first image of the sequence.\n\n")
MIL_TEXT("It then uses super-resolution to build an image with\n")
MIL_TEXT("a resolution that is higher that the individual images\n")
MIL_TEXT("of the sequence.\n\n")
MIL_TEXT("[MODULES USED]\n")
MIL_TEXT("Modules used: application, system, buffer, display,\n")
MIL_TEXT("graphic, registration\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_MilZoomedWithAverageImage;
MIL_ID m_MilZoomedWithSuperResolutionImage;
MIL_ID m_MilTrackingOverlayImage;
MIL_INT m_FirstImageChildOffsetX;
MIL_INT m_FirstImageChildOffsetY;
};
static const MIL_INT NumberOfSequences = 3;
static const SSequenceDescription Sequences[NumberOfSequences] = {
{M_IMAGE_PATH MIL_TEXT("SuperResolution/car_far.avi"), 0, 25, 285, 200, 45, 30, 0.5, M_SQUARE , 30.0},
{M_IMAGE_PATH MIL_TEXT("SuperResolution/car_near.avi"), 0, 25, 210, 300, 160, 90, 0.5, M_SQUARE , 30.0},
{M_IMAGE_PATH MIL_TEXT("SuperResolution/res_chart.avi"), 0, 19, 250, 125, 105, 70, 0.5, M_DEFAULT, 30.0}
};
static const MIL_DOUBLE MOSAIC_SCALE = 3.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();
MIL_INT i;
for (i = 0; i < NumberOfSequences; i++)
{
const SSequenceDescription SequenceDescription = Sequences[i];
MbufImportSequence(SequenceDescription.Filename, M_DEFAULT, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_OPEN);
MIL_INT NumberOfImagesInSequence = MbufDiskInquire(SequenceDescription.Filename, M_NUMBER_OF_IMAGES, M_NULL);
MIL_DOUBLE FrameRate;
MbufDiskInquire(SequenceDescription.Filename, M_FRAME_RATE, &FrameRate);
MIL_ID MilSequenceImage;
MbufImportSequence(SequenceDescription.Filename, M_DEFAULT,
M_RESTORE, MilSystem, &MilSequenceImage,
SequenceDescription.StartImage, 1, M_READ);
MIL_INT FrameIndex = 1;
CSuperResolution SuperResolution(MilSystem);
SuperResolution.InitializeWithFirstImage(MilSequenceImage,
SequenceDescription.NumberOfImages,
SequenceDescription.ChildOffsetX,
SequenceDescription.ChildOffsetY,
SequenceDescription.ChildSizeX,
SequenceDescription.ChildSizeY);
MosPrintf(MIL_TEXT("This is the first image of the sequence.\n")
MIL_TEXT("A rectangular region is set. All the other images of the sequence\n")
MIL_TEXT("will be realigned such that their content matches the content of the\n")
MIL_TEXT("first image in the region.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MIL_DOUBLE PreviousTime;
MappTimer(M_DEFAULT, M_TIMER_READ+M_SYNCHRONOUS, &PreviousTime);
bool Success = true;
while (Success && FrameIndex < NumberOfImagesInSequence)
{
MbufImportSequence(SequenceDescription.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("All images have been aligned.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
SuperResolution.SuperResolution(SequenceDescription.PsfRadius ,
SequenceDescription.PsfType ,
SequenceDescription.Smoothness);
MosPrintf(MIL_TEXT("The data contained in the selected region of all the images is composed\n")
MIL_TEXT("to form a scaled image using two methods:\n")
MIL_TEXT("- Averaging all images.\n")
MIL_TEXT("- Super-resolution.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
MosGetch();
MbufFree(MilSequenceImage);
MbufImportSequence(SequenceDescription.Filename, M_DEFAULT,
M_NULL, M_NULL, M_NULL,
M_NULL, M_NULL, M_CLOSE);
}
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
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_MilZoomedWithAverageImage (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_MilZoomedWithAverageImage);
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_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);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
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] = MbufAllocColor(
MbufInquire(MilImage, M_OWNER_SYSTEM, M_NULL),
MbufInquire(MilImage, M_SIZE_BAND , 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];
MIL_INT i;
for (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;
}
void CSuperResolution::SuperResolution(MIL_DOUBLE PsfRadius, MIL_INT PsfType, MIL_DOUBLE Smoothness)
{
MbufClear(m_MilTrackingImage, 0);
MbufClear(m_MilTrackingOverlayImage, static_cast<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_COMPOSITION, M_AVERAGE_IMAGE);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_X, 0);
MregControl(m_MilRegResult, M_GENERAL, M_MOSAIC_OFFSET_Y, 0);
MregTransformImage(m_MilRegResult,
m_MilSequenceImageTable,
m_MilZoomedWithAverageImage,
m_NumberOfImagesInTable,
M_BILINEAR, M_DEFAULT);
MIL_INT Margin = 10;
MIL_INT TextPositionX = MbufInquire(m_MilZoomedWithAverageImage, M_ANCESTOR_OFFSET_X, M_NULL) + MbufInquire(m_MilZoomedWithAverageImage, M_SIZE_X, M_NULL) - Margin;
MIL_INT TextPositionY = MbufInquire(m_MilZoomedWithAverageImage, M_ANCESTOR_OFFSET_Y, M_NULL) + Margin;
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MgraControl(M_DEFAULT, M_TEXT_ALIGN_HORIZONTAL, M_RIGHT);
MgraControl(M_DEFAULT, M_TEXT_ALIGN_VERTICAL, M_TOP);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraText(M_DEFAULT, m_MilOverlayImage, TextPositionX, TextPositionY, MIL_TEXT("Average"));
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);
TextPositionX = MbufInquire(m_MilZoomedWithSuperResolutionImage, M_ANCESTOR_OFFSET_X, M_NULL) + MbufInquire(m_MilZoomedWithSuperResolutionImage, M_SIZE_X, M_NULL) - Margin;
TextPositionY = MbufInquire(m_MilZoomedWithSuperResolutionImage, M_ANCESTOR_OFFSET_Y, M_NULL) + Margin;
MgraText(M_DEFAULT, m_MilOverlayImage, TextPositionX, TextPositionY, MIL_TEXT("Super-resolution"));
}
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, 2*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);
m_MilTrackingImage = MbufChild2d(m_MilFullDisplayImage,
SequenceImageSizeX, 0,
SequenceImageSizeX, SequenceImageSizeY, M_NULL);
m_MilTrackingOverlayImage = MbufChild2d(m_MilOverlayImage,
SequenceImageSizeX, 0,
SequenceImageSizeX, SequenceImageSizeY, M_NULL);
m_MilZoomedWithAverageImage = MbufChild2d(
m_MilFullDisplayImage,
SequenceImageSizeX, 0,
ZoomedChildSizeX, ZoomedChildSizeY, M_NULL);
m_MilZoomedWithSuperResolutionImage = MbufChild2d(
m_MilFullDisplayImage,
SequenceImageSizeX, ZoomedChildSizeY,
ZoomedChildSizeX, ZoomedChildSizeY, M_NULL);
}
void CSuperResolution::DrawCurrentResult()
{
MdispControl(m_MilDisplay, M_UPDATE, M_DISABLE);
MdispControl(m_MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
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_MOSAIC_STATIC_INDEX, m_NumberOfImagesInTable-1);
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MregDraw(M_DEFAULT, m_MilRegResult, m_MilOverlayImage, M_DRAW_BOX, 0, M_DEFAULT);
MgraControl(M_DEFAULT, M_TEXT_ALIGN_HORIZONTAL, M_LEFT);
MgraControl(M_DEFAULT, M_TEXT_ALIGN_VERTICAL, M_TOP);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_OPAQUE);
MIL_INT Margin = 10;
MgraText(M_DEFAULT, m_MilOverlayImage, Margin, Margin, MIL_TEXT("Source image"));
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);
MregDraw(M_DEFAULT, m_MilRegResult, m_MilTrackingOverlayImage, M_DRAW_BOX, 0, M_DEFAULT);
MgraText(M_DEFAULT, m_MilTrackingOverlayImage, Margin, Margin, MIL_TEXT("Realigned image"));
MdispControl(m_MilDisplay, M_UPDATE, M_ENABLE);
}