/*******************************************************************************/ /* * File name: MCal.c * * Synopsis: This program uses the Calibration module to calibrate a high * distortion camera with an image of a grid. Then, an image of * a board grabbed with the same camera is loaded and some * measurements are done in real world calibrated units. Finally * the distorted board image is corrected using the same camera * calibration. */ #include #include /* Source image files specification. */ #define GRID_IMAGE_FILE M_IMAGE_PATH MIL_TEXT("CalGrid.mim") #define BOARD_IMAGE_FILE M_IMAGE_PATH MIL_TEXT("CalBoard.mim") /* World description of the calibration grid. */ #define GRID_OFFSET_X 0 #define GRID_OFFSET_Y 0 #define GRID_OFFSET_Z 0 #define GRID_ROW_SPACING 1 #define GRID_COLUMN_SPACING 1 #define GRID_ROW_NUMBER 18 #define GRID_COLUMN_NUMBER 25 /* Measurement boxes specification. */ #define MEAS_BOX_POS_X1 55 #define MEAS_BOX_POS_Y1 24 #define MEAS_BOX_WIDTH1 7 #define MEAS_BOX_HEIGHT1 425 #define MEAS_BOX_POS_X2 225 #define MEAS_BOX_POS_Y2 11 #define MEAS_BOX_WIDTH2 7 #define MEAS_BOX_HEIGHT2 450 /* Specification of the stripes' constraints. */ #define WIDTH_APPROXIMATION 425 #define WIDTH_WEIGHT_FACTOR 98 /* Main function. */ void main(void) { MIL_ID MilApplication, /* Application identifier. */ MilSystem, /* System identifier. */ MilDisplay, /* Display identifier. */ MilImage, /* Image buffer identifier. */ MilOverlayImage, /* Overlay image. */ MilCalibration, /* Calibration identifier. */ MeasMarker1, /* Measurement marker identifier. */ MeasMarker2; /* Measurement marker identifier. */ double WorldDistance1, WorldDistance2; double PixelDistance1, PixelDistance2; double PosX1, PosY1, PosX2, PosY2, PosX3, PosY3, PosX4, PosY4; /* Allocate defaults. */ MappAllocDefault(M_SETUP, &MilApplication, &MilSystem, &MilDisplay, M_NULL, M_NULL); /* Restore source image into an automatically allocated image buffer. */ MbufRestore(GRID_IMAGE_FILE, MilSystem, &MilImage); /* Display the image buffer. */ MdispSelect(MilDisplay, MilImage); /* Prepare for overlay annotation. */ MdispControl(MilDisplay, M_OVERLAY, M_ENABLE); MdispInquire(MilDisplay, M_OVERLAY_ID, &MilOverlayImage); /* Pause to show the original image. */ printf("\nCALIBRATION:\n"); printf("------------\n\n"); printf("The displayed grid has been grabbed with a high distortion\n"); printf("camera and will be used to calibrate the camera.\n"); printf("Press to continue.\n\n"); getchar(); /* Allocate a camera calibration object. */ McalAlloc(MilSystem, M_DEFAULT, M_DEFAULT, &MilCalibration); /* Calibrate the camera with the image of the grid and its world description. */ McalGrid(MilCalibration, MilImage, GRID_OFFSET_X, GRID_OFFSET_Y, GRID_OFFSET_Z, GRID_ROW_NUMBER, GRID_COLUMN_NUMBER, GRID_ROW_SPACING, GRID_COLUMN_SPACING, M_DEFAULT, M_DEFAULT); /* Perform a first image transformation with the calibration grid. */ McalTransformImage(MilImage, MilImage, MilCalibration, M_BILINEAR|M_OVERSCAN_CLEAR, M_DEFAULT, M_DEFAULT); /* Pause to show the corrected image of the grid. */ printf("The camera has been calibrated and the image of the grid\n"); printf("has been transformed to remove its distortions.\n"); printf("Press to continue.\n\n"); getchar(); /* Read the image of the board and associate the calibration to the image. */ MbufLoad(BOARD_IMAGE_FILE, MilImage); McalAssociate(MilCalibration, MilImage, M_DEFAULT); /* Allocate the measurement markers. */ MmeasAllocMarker(MilSystem, M_STRIPE, M_DEFAULT, &MeasMarker1); MmeasAllocMarker(MilSystem, M_STRIPE, M_DEFAULT, &MeasMarker2); /* Set the markers' measurement boxes. */ MmeasSetMarker(MeasMarker1, M_BOX_ORIGIN, MEAS_BOX_POS_X1, MEAS_BOX_POS_Y1); MmeasSetMarker(MeasMarker1, M_BOX_SIZE, MEAS_BOX_WIDTH1, MEAS_BOX_HEIGHT1); MmeasSetMarker(MeasMarker2, M_BOX_ORIGIN, MEAS_BOX_POS_X2, MEAS_BOX_POS_Y2); MmeasSetMarker(MeasMarker2, M_BOX_SIZE, MEAS_BOX_WIDTH2, MEAS_BOX_HEIGHT2); /* Set markers' orientation. */ MmeasSetMarker(MeasMarker1, M_ORIENTATION, M_HORIZONTAL, M_NULL); MmeasSetMarker(MeasMarker2, M_ORIENTATION, M_HORIZONTAL, M_NULL); /* Set marker's approximate width and the associated weight factor. */ MmeasSetMarker(MeasMarker1, M_WIDTH, WIDTH_APPROXIMATION, M_NULL); MmeasSetMarker(MeasMarker2, M_WIDTH, WIDTH_APPROXIMATION, M_NULL); MmeasSetMarker(MeasMarker1, M_WEIGHT_FACTOR+M_WIDTH, WIDTH_WEIGHT_FACTOR, M_NULL); MmeasSetMarker(MeasMarker2, M_WEIGHT_FACTOR+M_WIDTH, WIDTH_WEIGHT_FACTOR, M_NULL); /* Find and measure the position and width of the board. */ MmeasFindMarker(M_DEFAULT, MilImage, MeasMarker1, M_WIDTH+M_POSITION); MmeasFindMarker(M_DEFAULT, MilImage, MeasMarker2, M_WIDTH+M_POSITION); /* Get the world width of the two markers. */ MmeasGetResult(MeasMarker1, M_WIDTH, &WorldDistance1, M_NULL); MmeasGetResult(MeasMarker2, M_WIDTH, &WorldDistance2, M_NULL); /* Get the pixel width of the two markers. */ McalControl(MilCalibration, M_OUTPUT_COORDINATE_SYSTEM, M_PIXEL); MmeasGetResult(MeasMarker1, M_WIDTH, &PixelDistance1, M_NULL); MmeasGetResult(MeasMarker2, M_WIDTH, &PixelDistance2, M_NULL); /* Get the edges position in pixel to draw the annotations. */ MmeasGetResult(MeasMarker1, M_POSITION+M_EDGE_FIRST, &PosX1, &PosY1); MmeasGetResult(MeasMarker1, M_POSITION+M_EDGE_SECOND, &PosX2, &PosY2); MmeasGetResult(MeasMarker2, M_POSITION+M_EDGE_FIRST, &PosX3, &PosY3); MmeasGetResult(MeasMarker2, M_POSITION+M_EDGE_SECOND, &PosX4, &PosY4); /* Draw the measurement indicators on the image. */ MgraColor(M_DEFAULT, M_COLOR_YELLOW); MmeasDraw(M_DEFAULT, MeasMarker1, MilOverlayImage, M_DRAW_WIDTH, M_DEFAULT, M_RESULT); MmeasDraw(M_DEFAULT, MeasMarker2, MilOverlayImage, M_DRAW_WIDTH, M_DEFAULT, M_RESULT); MgraBackColor(M_DEFAULT, M_COLOR_BLACK); MgraText(M_DEFAULT, MilOverlayImage, (long)(PosX1+0.5-40), (long)((PosY1+0.5)+((PosY2 - PosY1)/2.0)), MIL_TEXT(" Distance 1 ")); MgraText(M_DEFAULT, MilOverlayImage, (long)(PosX3+0.5-40), (long)((PosY3+0.5)+((PosY4 - PosY3)/2.0)), MIL_TEXT(" Distance 2 ")); /* Pause to show the original image and the measurement results. */ printf("A distorted image grabbed with the same camera was loaded and\n"); printf("calibrated measurements were done to evaluate the board dimensions.\n"); printf("\n========================================================\n"); printf(" Distance 1 Distance 2 \n"); printf("--------------------------------------------------------\n"); printf(" Calibrated unit: %8.2lf cm %6.2lf cm \n", WorldDistance1 , WorldDistance2); printf(" Uncalibrated unit: %8.2lf pixels %6.2lf pixels\n", PixelDistance1 , PixelDistance2); printf("========================================================\n\n"); printf("Press to continue.\n\n"); getchar(); /* Clear the display overlay. */ MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT); /* Read the image of the PCB. */ MbufLoad(BOARD_IMAGE_FILE, MilImage); /* Transform the image of the board. */ McalTransformImage(MilImage, MilImage, MilCalibration, M_BILINEAR+M_OVERSCAN_CLEAR, M_DEFAULT, M_DEFAULT); /* Pause to show the transformed image of the board. */ printf("The image was corrected to remove its distortions.\n"); printf("Press to end.\n\n"); getchar(); /* Free all allocations. */ MmeasFree(MeasMarker1); MmeasFree(MeasMarker2); McalFree(MilCalibration); MbufFree(MilImage); MappFreeDefault(MilApplication, MilSystem, MilDisplay, M_NULL, M_NULL); }