#include "common.h"
#include "FeatureFinder.h"
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n")
MIL_TEXT("ObjectLocalization3d\n\n")
MIL_TEXT("[SYNOPSIS]\n")
MIL_TEXT("This example demonstrates how the calibration module can be used to determine\n")
MIL_TEXT("the 3d position and orientation of an object after locating known fiducials on\n")
MIL_TEXT("the object.\n\n")
MIL_TEXT("[MODULES USED]\n")
MIL_TEXT("Modules used: application, system, display, digitizer, buffer, graphic,\n")
MIL_TEXT(" image processing, calibration, code.\n\n")
MIL_TEXT("Press <Enter> to start.\n\n"));
MosGetch();
}
#define EXAMPLE_IMAGE_PATH M_IMAGE_PATH MIL_TEXT("ObjectLocalization3d/")
static const MIL_TEXT_CHAR* const CALIBRATION_CONTEXT_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("Calib.mca");
static const MIL_TEXT_CHAR* const SEQ_FILE = EXAMPLE_IMAGE_PATH MIL_TEXT("seq.avi");
static const MIL_DOUBLE COORDINATE_SYSTEM_COLOR = M_COLOR_GRAY;
static const MIL_DOUBLE BOUNDING_BOX_COLOR = M_COLOR_CYAN;
static const MIL_INT NB_VERTICES_PER_SIDE = 7;
static const MIL_INT NB_CAR_VERTICES = 2*NB_VERTICES_PER_SIDE;
static const MIL_DOUBLE CAR_VERTEX_X[NB_CAR_VERTICES] = { 130.1, 126.6, 115.7, 120.3, 128.6, 127.2, 135.1, 40.6, 45.4, 56.3, 49.5, 42.0, 39.5, 35.1};
static const MIL_DOUBLE CAR_VERTEX_Y[NB_CAR_VERTICES] = { 223.7, 213.3, 196.1, 82.1, 43.5, -17.7, -24.2, 221.8, 214.0, 198.1, 80.6, 41.9, -17.5, -25.3};
static const MIL_DOUBLE CAR_VERTEX_Z[NB_CAR_VERTICES] = { -21.4, -64.0, -89.9, -87.7, -64.4, -49.9, -26.7, -27.5, -63.7, -87.3, -87.7, -63.8, -50.4, -24.0};
bool LocateObject(MIL_ID MilCalibration, const SObjectFeatures* pObjectFeatures);
void DisplayBoundingBox(MIL_ID MilDisplay, MIL_ID MilCalibration);
int MosMain(void)
{
PrintHeader();
MIL_ID MilApplication = MappAlloc(M_NULL, M_DEFAULT, M_NULL);
MIL_ID MilSystem = MsysAlloc(M_DEFAULT, M_SYSTEM_HOST, M_DEFAULT, M_DEFAULT, M_NULL);
MIL_ID MilDisplay = MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, M_NULL);
MIL_INT SizeX = MbufDiskInquire(SEQ_FILE, M_SIZE_X, M_NULL);
MIL_INT SizeY = MbufDiskInquire(SEQ_FILE, M_SIZE_Y, M_NULL);
MIL_ID MilDisplayImage = MbufAlloc2d(MilSystem, SizeX, SizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC+M_DISP, M_NULL);
MbufClear(MilDisplayImage, 0.0);
MdispSelect(MilDisplay, MilDisplayImage);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MIL_ID MilCalibration = McalRestore(CALIBRATION_CONTEXT_FILE, MilSystem, M_DEFAULT, M_NULL);
if (MilCalibration != M_NULL)
{
MosPrintf(MIL_TEXT("The Tsai-based camera calibration context was restored from disk.\n\n"));
MosPrintf(MIL_TEXT("For each frame of the video sequence:\n")
MIL_TEXT(" - The circular fiducials are found using blob analysis (red crosses).\n")
MIL_TEXT(" - Each fiducial is uniquely identified by reading its bar code\n")
MIL_TEXT(" (green numeric labels).\n")
MIL_TEXT(" - The fiducials' pixel coordinates are paired with the known world\n")
MIL_TEXT(" coordinates using their labels.\n")
MIL_TEXT(" - McalList() is called to determine the position and orientation of the car.\n")
MIL_TEXT(" - The bounding box of the car is drawn in the overlay.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to exit.\n\n"));
CFeatureFinder FeatureFinder(MilSystem, SizeX, SizeY);
SObjectFeatures ObjectFeatures;
MbufImportSequence(SEQ_FILE, M_AVI_MIL, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_OPEN);
MIL_INT NbFrames = MbufDiskInquire(SEQ_FILE, M_NUMBER_OF_IMAGES, M_NULL);
MIL_DOUBLE ImagePeriod;
MbufDiskInquire(SEQ_FILE, M_FRAME_RATE, &ImagePeriod);
ImagePeriod = 1.0 / ImagePeriod;
MIL_INT CurFrame = 0;
bool MustQuit = false;
while (!MustQuit)
{
MIL_DOUBLE StartTime = MappTimer(M_DEFAULT, M_TIMER_READ, M_NULL);
MdispControl(MilDisplay, M_UPDATE, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MbufImportSequence(SEQ_FILE, M_AVI_MIL, M_LOAD, M_NULL, &MilDisplayImage, CurFrame, 1, M_READ);
FeatureFinder.Find(MilDisplay, MilDisplayImage, &ObjectFeatures);
if (ObjectFeatures.m_NumPoint >= MIN_NB_FEATURES)
{
bool ObjectWasLocated = LocateObject(MilCalibration, &ObjectFeatures);
if (ObjectWasLocated)
{
DisplayBoundingBox(MilDisplay, MilCalibration);
}
}
MdispControl(MilDisplay, M_UPDATE, M_ENABLE);
if (++CurFrame == NbFrames)
CurFrame = 0;
MIL_DOUBLE ElapsedTime;
MappTimer(M_DEFAULT, M_TIMER_READ, &ElapsedTime);
ElapsedTime -= StartTime;
MIL_DOUBLE WaitTime = ImagePeriod - ElapsedTime;
if (WaitTime > 0.0)
MappTimer(M_DEFAULT, M_TIMER_WAIT, &WaitTime);
while (MosKbhit())
{
switch (MosGetch())
{
case MIL_TEXT('\r'):
case MIL_TEXT('\n'):
MustQuit = true;
break;
}
}
}
MbufImportSequence(SEQ_FILE, M_AVI_MIL, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_CLOSE);
}
else
{
MosPrintf(MIL_TEXT("Unable to reload the calibration context.\n")
MIL_TEXT("Press <Enter> to exit.\n\n"));
MosGetch();
}
McalFree(MilCalibration);
MbufFree(MilDisplayImage);
MdispFree(MilDisplay);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
bool LocateObject(MIL_ID MilCalibration, const SObjectFeatures* pObjectFeatures)
{
MIL_INT PreviousErrorPrintingState;
MappInquire(M_DEFAULT, M_ERROR, &PreviousErrorPrintingState);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
McalList(MilCalibration,
pObjectFeatures->m_XPixArray,
pObjectFeatures->m_YPixArray,
pObjectFeatures->m_XWorldArray,
pObjectFeatures->m_YWorldArray,
pObjectFeatures->m_ZWorldArray,
pObjectFeatures->m_NumPoint,
M_DISPLACE_RELATIVE_COORD,
M_DEFAULT);
MappControl(M_DEFAULT, M_ERROR, PreviousErrorPrintingState);
MIL_INT LocateStatus = McalInquire(MilCalibration, M_CALIBRATION_STATUS, M_NULL);
return (LocateStatus == M_CALIBRATED);
}
void DisplayBoundingBox(MIL_ID MilDisplay, MIL_ID MilCalibration)
{
MIL_ID MilOverlayImage;
MdispInquire(MilDisplay, M_OVERLAY_ID, &MilOverlayImage);
MgraColor(M_DEFAULT, COORDINATE_SYSTEM_COLOR);
McalDraw(M_DEFAULT, MilCalibration, MilOverlayImage, M_DRAW_RELATIVE_COORDINATE_SYSTEM, M_DEFAULT, M_DEFAULT);
MIL_DOUBLE ImageVertexX[NB_CAR_VERTICES];
MIL_DOUBLE ImageVertexY[NB_CAR_VERTICES];
McalTransformCoordinate3dList(MilCalibration,
M_RELATIVE_COORDINATE_SYSTEM,
M_PIXEL_COORDINATE_SYSTEM,
NB_CAR_VERTICES,
CAR_VERTEX_X,
CAR_VERTEX_Y,
CAR_VERTEX_Z,
ImageVertexX,
ImageVertexY,
M_NULL,
M_DEFAULT);
MgraColor(M_DEFAULT, BOUNDING_BOX_COLOR);
MgraControl(M_DEFAULT, M_INPUT_UNITS, M_PIXEL);
MgraLines(M_DEFAULT, MilOverlayImage, NB_VERTICES_PER_SIDE,
ImageVertexX, ImageVertexY,
M_NULL, M_NULL, M_POLYGON);
MgraLines(M_DEFAULT, MilOverlayImage, NB_VERTICES_PER_SIDE,
ImageVertexX+NB_VERTICES_PER_SIDE, ImageVertexY+NB_VERTICES_PER_SIDE,
M_NULL, M_NULL, M_POLYGON);
MgraLines(M_DEFAULT, MilOverlayImage, NB_VERTICES_PER_SIDE,
ImageVertexX, ImageVertexY,
ImageVertexX+NB_VERTICES_PER_SIDE, ImageVertexY+NB_VERTICES_PER_SIDE, M_DEFAULT);
}