Click here to show toolbars of the Web Online Help System: show toolbars |
//******************************************************************************* // // File name: Mcal.cs // Location: See Matrox Example Launcher in the MIL Control Center // // // Synopsis: This program uses the Calibration module to: // - Remove distortion and then take measurements in world units using a 2D // calibration. // - Perform a 3D calibration to take measurements at several known elevations. // - Calibrate a scene using a partial calibration grid that has a 2D code // fiducial. // // Copyright (C) Matrox Electronic Systems Ltd., 1992-2016. // All Rights Reserved //******************************************************************************* using System; using System.Collections.Generic; using System.Text; using Matrox.MatroxImagingLibrary; namespace Mcal { class Program { // Example selection. private const int RUN_LINEAR_CALIBRATION_EXAMPLE = MIL.M_YES; private const int RUN_TSAI_CALIBRATION_EXAMPLE = MIL.M_YES; private const int RUN_PARTIAL_GRID_CALIBRATION_EXAMPLE = MIL.M_YES; static void Main(string[] args) { MIL_ID MilApplication = MIL.M_NULL; // Application identifier. MIL_ID MilSystem = MIL.M_NULL; // System Identifier. MIL_ID MilDisplay = MIL.M_NULL; // Display identifier. // Allocate defaults. MIL.MappAllocDefault(MIL.M_DEFAULT, ref MilApplication, ref MilSystem, ref MilDisplay, MIL.M_NULL, MIL.M_NULL); // Print module name. Console.Write("CALIBRATION MODULE:\n"); Console.Write("-------------------\n\n"); if (RUN_LINEAR_CALIBRATION_EXAMPLE == MIL.M_YES) { LinearInterpolationCalibration(MilSystem, MilDisplay); } if (RUN_TSAI_CALIBRATION_EXAMPLE == MIL.M_YES) { TsaiCalibration(MilSystem, MilDisplay); } if (RUN_PARTIAL_GRID_CALIBRATION_EXAMPLE == MIL.M_YES) { PartialGridCalibration(MilSystem, MilDisplay); } // Free defaults. MIL.MappFreeDefault(MilApplication, MilSystem, MilDisplay, MIL.M_NULL, MIL.M_NULL); } //**************************************************************************** // Linear interpolation example. //**************************************************************************** // Source image files specification. private const string GRID_IMAGE_FILE = MIL.M_IMAGE_PATH + "CalGrid.mim"; private const string BOARD_IMAGE_FILE = MIL.M_IMAGE_PATH + "CalBoard.mim"; // World description of the calibration grid. private const int GRID_OFFSET_X = 0; private const int GRID_OFFSET_Y = 0; private const int GRID_OFFSET_Z = 0; private const int GRID_ROW_SPACING = 1; private const int GRID_COLUMN_SPACING = 1; private const int GRID_ROW_NUMBER = 18; private const int GRID_COLUMN_NUMBER = 25; // Measurement boxes specification. private const int MEAS_BOX_POS_X1 = 55; private const int MEAS_BOX_POS_Y1 = 24; private const int MEAS_BOX_WIDTH1 = 7; private const int MEAS_BOX_HEIGHT1 = 425; private const int MEAS_BOX_POS_X2 = 225; private const int MEAS_BOX_POS_Y2 = 11; private const int MEAS_BOX_WIDTH2 = 7; private const int MEAS_BOX_HEIGHT2 = 450; // Specification of the stripes' constraints. private const int WIDTH_APPROXIMATION = 410; private const int WIDTH_VARIATION = 25; private const int MIN_EDGE_VALUE = 5; static void LinearInterpolationCalibration(MIL_ID MilSystem, MIL_ID MilDisplay) { MIL_ID MilImage = MIL.M_NULL; // Image buffer identifier. MIL_ID MilOverlayImage = MIL.M_NULL; // Overlay image. MIL_ID MilCalibration = MIL.M_NULL; // Calibration identifier. MIL_ID MeasMarker1 = MIL.M_NULL; // Measurement marker identifier. MIL_ID MeasMarker2 = MIL.M_NULL; // Measurement marker identifier. double WorldDistance1 = 0.0; double WorldDistance2 = 0.0; double PixelDistance1 = 0.0; double PixelDistance2 = 0.0; double PosX1 = 0.0; double PosY1 = 0.0; double PosX2 = 0.0; double PosY2 = 0.0; double PosX3 = 0.0; double PosY3 = 0.0; double PosX4 = 0.0; double PosY4 = 0.0; MIL_INT CalibrationStatus = 0; // Clear the display. MIL.MdispControl(MilDisplay, MIL.M_OVERLAY_CLEAR, MIL.M_DEFAULT); // Restore source image into an automatically allocated image buffer. MIL.MbufRestore(GRID_IMAGE_FILE, MilSystem, ref MilImage); // Display the image buffer. MIL.MdispSelect(MilDisplay, MilImage); // Prepare for overlay annotation. MIL.MdispControl(MilDisplay, MIL.M_OVERLAY, MIL.M_ENABLE); MIL.MdispInquire(MilDisplay, MIL.M_OVERLAY_ID, ref MilOverlayImage); // Pause to show the original image. Console.Write("\nLINEAR INTERPOLATION CALIBRATION:\n"); Console.Write("---------------------------------\n\n"); Console.Write("The displayed grid has been grabbed with a high distortion\n"); Console.Write("camera and will be used to calibrate the camera.\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Allocate a camera calibration context. MIL.McalAlloc(MilSystem, MIL.M_DEFAULT, MIL.M_DEFAULT, ref MilCalibration); // Calibrate the camera with the image of the grid and its world description. MIL.McalGrid(MilCalibration, MilImage, GRID_OFFSET_X, GRID_OFFSET_Y, GRID_OFFSET_Z, GRID_ROW_NUMBER, GRID_COLUMN_NUMBER, GRID_ROW_SPACING, GRID_COLUMN_SPACING, MIL.M_DEFAULT, MIL.M_DEFAULT); MIL.McalInquire(MilCalibration, MIL.M_CALIBRATION_STATUS + MIL.M_TYPE_MIL_INT, ref CalibrationStatus); if (CalibrationStatus == MIL.M_CALIBRATED) { // Perform a first image transformation with the calibration grid. MIL.McalTransformImage(MilImage, MilImage, MilCalibration, MIL.M_BILINEAR | MIL.M_OVERSCAN_CLEAR, MIL.M_DEFAULT, MIL.M_DEFAULT); // Pause to show the corrected image of the grid. Console.Write("The camera has been calibrated and the image of the grid\n"); Console.Write("has been transformed to remove its distortions.\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Read the image of the board and associate the calibration to the image. MIL.MbufLoad(BOARD_IMAGE_FILE, MilImage); MIL.McalAssociate(MilCalibration, MilImage, MIL.M_DEFAULT); // Allocate the measurement markers. MIL.MmeasAllocMarker(MilSystem, MIL.M_STRIPE, MIL.M_DEFAULT, ref MeasMarker1); MIL.MmeasAllocMarker(MilSystem, MIL.M_STRIPE, MIL.M_DEFAULT, ref MeasMarker2); // Set the markers' measurement search region. MIL.MmeasSetMarker(MeasMarker1, MIL.M_BOX_ORIGIN, MEAS_BOX_POS_X1, MEAS_BOX_POS_Y1); MIL.MmeasSetMarker(MeasMarker1, MIL.M_BOX_SIZE, MEAS_BOX_WIDTH1, MEAS_BOX_HEIGHT1); MIL.MmeasSetMarker(MeasMarker2, MIL.M_BOX_ORIGIN, MEAS_BOX_POS_X2, MEAS_BOX_POS_Y2); MIL.MmeasSetMarker(MeasMarker2, MIL.M_BOX_SIZE, MEAS_BOX_WIDTH2, MEAS_BOX_HEIGHT2); // Set markers' orientation. MIL.MmeasSetMarker(MeasMarker1, MIL.M_ORIENTATION, MIL.M_HORIZONTAL, MIL.M_NULL); MIL.MmeasSetMarker(MeasMarker2, MIL.M_ORIENTATION, MIL.M_HORIZONTAL, MIL.M_NULL); // Set markers' settings to locate the largest stripe within the range // [WIDTH_APPROXIMATION - WIDTH_VARIATION, // WIDTH_APPROXIMATION + WIDTH_VARIATION], // and with an edge strength over MIN_EDGE_VALUE. MIL.MmeasSetMarker(MeasMarker1, MIL.M_EDGEVALUE_MIN, MIN_EDGE_VALUE, MIL.M_NULL); // Remove the default strength characteristic score mapping. MIL.MmeasSetScore(MeasMarker1, MIL.M_STRENGTH_SCORE, 0.0, 0.0, MIL.M_MAX_POSSIBLE_VALUE, MIL.M_MAX_POSSIBLE_VALUE, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT); // Add a width characteristic score mapping (increasing ramp) // to find the largest stripe within a given range. // // Width score mapping to find the largest stripe within a given // width range ]Wmin, Wmax]: // // Score // ^ // | /| // | / | // | / | // +---------------> Width // Wmin Wmax // MIL.MmeasSetScore(MeasMarker1, MIL.M_STRIPE_WIDTH_SCORE, WIDTH_APPROXIMATION - WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, MIL.M_DEFAULT, MIL.M_PIXEL, MIL.M_DEFAULT); // Set the same settings for the second marker. MIL.MmeasSetMarker(MeasMarker2, MIL.M_EDGEVALUE_MIN, MIN_EDGE_VALUE, MIL.M_NULL); MIL.MmeasSetScore(MeasMarker2, MIL.M_STRENGTH_SCORE, 0.0, 0.0, MIL.M_MAX_POSSIBLE_VALUE, MIL.M_MAX_POSSIBLE_VALUE, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT); MIL.MmeasSetScore(MeasMarker2, MIL.M_STRIPE_WIDTH_SCORE, WIDTH_APPROXIMATION - WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, WIDTH_APPROXIMATION + WIDTH_VARIATION, MIL.M_DEFAULT, MIL.M_PIXEL, MIL.M_DEFAULT); // Find and measure the position and width of the board. MIL.MmeasFindMarker(MIL.M_DEFAULT, MilImage, MeasMarker1, MIL.M_STRIPE_WIDTH + MIL.M_POSITION); MIL.MmeasFindMarker(MIL.M_DEFAULT, MilImage, MeasMarker2, MIL.M_STRIPE_WIDTH + MIL.M_POSITION); // Get the world width of the two markers. MIL.MmeasGetResult(MeasMarker1, MIL.M_STRIPE_WIDTH, ref WorldDistance1); MIL.MmeasGetResult(MeasMarker2, MIL.M_STRIPE_WIDTH, ref WorldDistance2); // Get the pixel width of the two markers. MIL.MmeasSetMarker(MeasMarker1, MIL.M_RESULT_OUTPUT_UNITS, MIL.M_PIXEL, MIL.M_NULL); MIL.MmeasSetMarker(MeasMarker2, MIL.M_RESULT_OUTPUT_UNITS, MIL.M_PIXEL, MIL.M_NULL); MIL.MmeasGetResult(MeasMarker1, MIL.M_STRIPE_WIDTH, ref PixelDistance1); MIL.MmeasGetResult(MeasMarker2, MIL.M_STRIPE_WIDTH, ref PixelDistance2); // Get the edges position in pixel to draw the annotations. MIL.MmeasGetResult(MeasMarker1, MIL.M_POSITION + MIL.M_EDGE_FIRST, ref PosX1, ref PosY1); MIL.MmeasGetResult(MeasMarker1, MIL.M_POSITION + MIL.M_EDGE_SECOND, ref PosX2, ref PosY2); MIL.MmeasGetResult(MeasMarker2, MIL.M_POSITION + MIL.M_EDGE_FIRST, ref PosX3, ref PosY3); MIL.MmeasGetResult(MeasMarker2, MIL.M_POSITION + MIL.M_EDGE_SECOND, ref PosX4, ref PosY4); // Draw the measurement indicators on the image. MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_YELLOW); MIL.MmeasDraw(MIL.M_DEFAULT, MeasMarker1, MilOverlayImage, MIL.M_DRAW_WIDTH, MIL.M_DEFAULT, MIL.M_RESULT); MIL.MmeasDraw(MIL.M_DEFAULT, MeasMarker2, MilOverlayImage, MIL.M_DRAW_WIDTH, MIL.M_DEFAULT, MIL.M_RESULT); MIL.MgraBackColor(MIL.M_DEFAULT, MIL.M_COLOR_BLACK); MIL.MgraText(MIL.M_DEFAULT, MilOverlayImage, (int)(PosX1 + 0.5 - 40), (int)((PosY1 + 0.5) + ((PosY2 - PosY1) / 2.0)), " Distance 1 "); MIL.MgraText(MIL.M_DEFAULT, MilOverlayImage, (int)(PosX3 + 0.5 - 40), (int)((PosY3 + 0.5) + ((PosY4 - PosY3) / 2.0)), " Distance 2 "); // Pause to show the original image and the measurement results. Console.Write("A distorted image grabbed with the same camera was loaded and\n"); Console.Write("calibrated measurements were done to evaluate the board dimensions.\n"); Console.Write("\n========================================================\n"); Console.Write(" Distance 1 Distance 2 \n"); Console.Write("--------------------------------------------------------\n"); Console.Write(" Calibrated unit: {0,8:0.00} cm {1,6:0.00} cm \n", WorldDistance1, WorldDistance2); Console.Write(" Uncalibrated unit: {0,8:0.00} pixels {1,6:0.00} pixels\n", PixelDistance1, PixelDistance2); Console.Write("========================================================\n\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Clear the display overlay. MIL.MdispControl(MilDisplay, MIL.M_OVERLAY_CLEAR, MIL.M_DEFAULT); // Read the image of the PCB. MIL.MbufLoad(BOARD_IMAGE_FILE, MilImage); // Transform the image of the board. MIL.McalTransformImage(MilImage, MilImage, MilCalibration, MIL.M_BILINEAR + MIL.M_OVERSCAN_CLEAR, MIL.M_DEFAULT, MIL.M_DEFAULT); // show the transformed image of the board. Console.Write("The image was corrected to remove its distortions.\n"); // Free measurement markers. MIL.MmeasFree(MeasMarker1); MIL.MmeasFree(MeasMarker2); } else { Console.Write("Calibration generated an exception.\n"); Console.Write("See User Guide to resolve the situation.\n\n"); } // Wait for a key to be pressed. Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Free all allocations. MIL.McalFree(MilCalibration); MIL.MbufFree(MilImage); } //**************************************************************************** // Tsai example. //**************************************************************************** // Source image files specification. private const string GRID_ORIGINAL_IMAGE_FILE = MIL.M_IMAGE_PATH + "CalGridOriginal.mim"; private const string OBJECT_ORIGINAL_IMAGE_FILE = MIL.M_IMAGE_PATH + "CalObjOriginal.mim"; private const string OBJECT_MOVED_IMAGE_FILE = MIL.M_IMAGE_PATH + "CalObjMoved.mim"; // World description of the calibration grid. private const double GRID_ORG_ROW_SPACING = 1.5; private const double GRID_ORG_COLUMN_SPACING = 1.5; private const int GRID_ORG_ROW_NUMBER = 12; private const int GRID_ORG_COLUMN_NUMBER = 13; private const int GRID_ORG_OFFSET_X = 0; private const int GRID_ORG_OFFSET_Y = 0; private const int GRID_ORG_OFFSET_Z = 0; // Camera transformation private const double ENCODER_TRANSLATION_X = 0.817; private const double ENCODER_TRANSLATION_Y = 13.293; private const double ENCODER_TRANSLATION_Z = -14.060; private const double ENCODER_ROTATION_Y = 354.207; private const double ENCODER_ROTATION_X = 317.467; private const double ENCODER_ROTATION_Z = 281.969; // Region parameters for metrology private const int MEASURED_CIRCLE_LABEL = 1; private const double RING1_POS1_X = 2.3; private const double RING1_POS1_Y = 3.9; private const double RING2_POS1_X = 10.7; private const double RING2_POS1_Y = 11.1; private const double RING1_POS2_X = 8.6; private const double RING1_POS2_Y = 2.5; private const double RING2_POS2_X = 7.9; private const double RING2_POS2_Y = 13.2; private const double RING_START_RADIUS = 1.25; private const double RING_END_RADIUS = 2.3; // measured plane position private const double RING_THICKNESS = 0.175; private const double STEP_THICKNESS = 4.0; // Color definitions static readonly int REGION_COLOR = MIL.M_RGB888(0, 100, 255); static readonly int FEATURE_COLOR = MIL.M_RGB888(255, 0, 255); static void TsaiCalibration(MIL_ID MilSystem, MIL_ID MilDisplay) { MIL_ID MilImage = MIL.M_NULL; // Image buffer identifier. MIL_ID MilCalibration = MIL.M_NULL; // Calibration identifier. MIL_INT CalibrationStatus = 0; // Restore source image into an automatically allocated image buffer. MIL.MbufRestore(GRID_ORIGINAL_IMAGE_FILE, MilSystem, ref MilImage); // Display the image buffer. MIL.MdispSelect(MilDisplay, MilImage); // Pause to show the original image. Console.Write("\nTSAI BASED CALIBRATION:\n"); Console.Write("-----------------------\n\n"); Console.Write("The displayed grid has been grabbed with a high perspective\n"); Console.Write("camera and will be used to calibrate the camera.\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Allocate a camera calibration context. MIL.McalAlloc(MilSystem, MIL.M_TSAI_BASED, MIL.M_DEFAULT, ref MilCalibration); // Calibrate the camera with the image of the grid and its world description. MIL.McalGrid(MilCalibration, MilImage, GRID_ORG_OFFSET_X, GRID_ORG_OFFSET_Y, GRID_ORG_OFFSET_Z, GRID_ORG_ROW_NUMBER, GRID_ORG_COLUMN_NUMBER, GRID_ORG_ROW_SPACING, GRID_ORG_COLUMN_SPACING, MIL.M_DEFAULT, MIL.M_DEFAULT); // Verify if the camera calibration was successful MIL.McalInquire(MilCalibration, MIL.M_CALIBRATION_STATUS + MIL.M_TYPE_MIL_INT, ref CalibrationStatus); if (CalibrationStatus == MIL.M_CALIBRATED) { // Print camera information Console.Write("The camera has been calibrated.\n\n"); ShowCameraInformation(MilCalibration); // Load source image into an image buffer. MIL.MbufLoad(OBJECT_ORIGINAL_IMAGE_FILE, MilImage); // Set offset to the camera calibration plane and associate calibration to image. // This moves the relative origin to the top of the first measured circle SetCalibrationOffset(MilCalibration, -RING_THICKNESS, MilImage); // Measure the first circle. Console.Write("First measured circle at z = {0:0.00} cm. ", -RING_THICKNESS); MeasureRing(MilSystem, MilDisplay, MilImage, RING1_POS1_X, RING1_POS1_Y); // Set offset to the camera calibration plane and associate calibration to image. // This moves the relative origin to the top of the second measured circle SetCalibrationOffset(MilCalibration, -(STEP_THICKNESS + RING_THICKNESS), MilImage); // Measure the second circle. Console.Write("Second measured circle at z = {0:0.00} cm. ", -(STEP_THICKNESS + RING_THICKNESS)); MeasureRing(MilSystem, MilDisplay, MilImage, RING2_POS1_X, RING2_POS1_Y); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Clear the overlay to transparent. MIL.MdispControl(MilDisplay, MIL.M_OVERLAY_CLEAR, MIL.M_DEFAULT); // Move camera rotation with the tool MIL.McalSetCoordinateSystem(MilCalibration, MIL.M_TOOL_COORDINATE_SYSTEM, MIL.M_ABSOLUTE_COORDINATE_SYSTEM, MIL.M_ROTATION_YXZ | MIL.M_ASSIGN, MIL.M_NULL, ENCODER_ROTATION_Y, ENCODER_ROTATION_X, ENCODER_ROTATION_Z, MIL.M_DEFAULT); // Move camera position with the tool MIL.McalSetCoordinateSystem(MilCalibration, MIL.M_TOOL_COORDINATE_SYSTEM, MIL.M_ABSOLUTE_COORDINATE_SYSTEM, MIL.M_TRANSLATION | MIL.M_COMPOSE_WITH_CURRENT, MIL.M_NULL, ENCODER_TRANSLATION_X, ENCODER_TRANSLATION_Y, ENCODER_TRANSLATION_Z, MIL.M_DEFAULT); // Load source image into an image buffer. MIL.MbufLoad(OBJECT_MOVED_IMAGE_FILE, MilImage); // Print camera information Console.Write("Calibration module moved camera position and camera \n"); Console.Write("orientation according to known encoder transformation.\n\n"); ShowCameraInformation(MilCalibration); // Set offset to the camera calibration plane and associate calibration to image. // This moves the relative origin to the top of the first measured circle SetCalibrationOffset(MilCalibration, -RING_THICKNESS, MilImage); // Measure the first circle. Console.Write("First measured circle at z = {0:0.00} cm. ", -RING_THICKNESS); MeasureRing(MilSystem, MilDisplay, MilImage, RING1_POS2_X, RING1_POS2_Y); // Set offset to the camera calibration plane and associate calibration to image. // This moves the relative origin to the top of the second measured circle SetCalibrationOffset(MilCalibration, -(STEP_THICKNESS + RING_THICKNESS), MilImage); // Measure the second circle. Console.Write("Second measured circle at z = {0:0.00} cm. ", -(STEP_THICKNESS + RING_THICKNESS)); MeasureRing(MilSystem, MilDisplay, MilImage, RING2_POS2_X, RING2_POS2_Y); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); } else { Console.Write("Calibration generated an exception.\n"); Console.Write("See User Guide to resolve the situation.\n\n"); } // Free all allocations. MIL.McalFree(MilCalibration); MIL.MbufFree(MilImage); } // Offset camera calibration plane. static void SetCalibrationOffset(MIL_ID MilCalibration, double ZOffset, MIL_ID MilImage) { MIL.McalSetCoordinateSystem(MilCalibration, MIL.M_RELATIVE_COORDINATE_SYSTEM, MIL.M_ABSOLUTE_COORDINATE_SYSTEM, MIL.M_TRANSLATION | MIL.M_ASSIGN, MIL.M_NULL, 0, 0, ZOffset, MIL.M_DEFAULT); // Associate calibration context to source image MIL.McalAssociate(MilCalibration, MilImage, MIL.M_DEFAULT); } // Measuring function with MilMetrology module static void MeasureRing(MIL_ID MilSystem, MIL_ID MilDisplay, MIL_ID MilImage, double MeasureRingX, double MeasureRingY) { MIL_ID MilMetrolContext = MIL.M_NULL; // Metrology Context. MIL_ID MilMetrolResult = MIL.M_NULL; // Metrology Result. MIL_ID MilOverlayImage = MIL.M_NULL; // Overlay image. double Value = 0.0; // Prepare for overlay annotation. MIL.MdispControl(MilDisplay, MIL.M_OVERLAY, MIL.M_ENABLE); MIL.MdispInquire(MilDisplay, MIL.M_OVERLAY_ID, ref MilOverlayImage); // Allocate metrology context and result. MIL.MmetAlloc(MilSystem, MIL.M_DEFAULT, ref MilMetrolContext); MIL.MmetAllocResult(MilSystem, MIL.M_DEFAULT, ref MilMetrolResult); // Add a first measured segment feature to context and set its search region. MIL.MmetAddFeature(MilMetrolContext, MIL.M_MEASURED, MIL.M_CIRCLE, MEASURED_CIRCLE_LABEL, MIL.M_DEFAULT, MIL.M_NULL, MIL.M_NULL, 0, MIL.M_DEFAULT); MIL.MmetSetRegion(MilMetrolContext, MIL.M_FEATURE_LABEL(MEASURED_CIRCLE_LABEL), MIL.M_DEFAULT, MIL.M_RING, MeasureRingX, MeasureRingY, RING_START_RADIUS, RING_END_RADIUS, MIL.M_NULL, MIL.M_NULL); // Calculate. MIL.MmetCalculate(MilMetrolContext, MilImage, MilMetrolResult, MIL.M_DEFAULT); // Draw region. MIL.MgraColor(MIL.M_DEFAULT, REGION_COLOR); MIL.MmetDraw(MIL.M_DEFAULT, MilMetrolResult, MilOverlayImage, MIL.M_DRAW_REGION, MIL.M_DEFAULT, MIL.M_DEFAULT); // Draw features. MIL.MgraColor(MIL.M_DEFAULT, FEATURE_COLOR); MIL.MmetDraw(MIL.M_DEFAULT, MilMetrolResult, MilOverlayImage, MIL.M_DRAW_FEATURE, MIL.M_DEFAULT, MIL.M_DEFAULT); MIL.MmetGetResult(MilMetrolResult, MIL.M_FEATURE_LABEL(MEASURED_CIRCLE_LABEL), MIL.M_RADIUS, ref Value); Console.Write("Measured Radius: {0:0.000} cm\n", Value); // Free all allocations. MIL.MmetFree(MilMetrolResult); MIL.MmetFree(MilMetrolContext); } // Print the current camera position and orientation static void ShowCameraInformation(MIL_ID MilCalibration) { double CameraPosX = 0.0; double CameraPosY = 0.0; double CameraPosZ = 0.0; double CameraYaw = 0.0; double CameraPitch = 0.0; double CameraRoll = 0.0; MIL.McalGetCoordinateSystem(MilCalibration, MIL.M_CAMERA_COORDINATE_SYSTEM, MIL.M_ABSOLUTE_COORDINATE_SYSTEM, MIL.M_TRANSLATION, MIL.M_NULL, ref CameraPosX, ref CameraPosY, ref CameraPosZ, MIL.M_NULL); MIL.McalGetCoordinateSystem(MilCalibration, MIL.M_CAMERA_COORDINATE_SYSTEM, MIL.M_ABSOLUTE_COORDINATE_SYSTEM, MIL.M_ROTATION_YXZ, MIL.M_NULL, ref CameraYaw, ref CameraPitch, ref CameraRoll, MIL.M_NULL); // Pause to show the corrected image of the grid. Console.Write("Camera Position in cm: (x, y, z) ({0:0.00}, {1:0.00}, {2:0.00})\n", CameraPosX, CameraPosY, CameraPosZ); Console.Write("Camera Orientation in degrees: (yaw, pitch, roll) ({0:0.00}, {1:0.00}, {2:0.00})\n", CameraYaw, CameraPitch, CameraRoll); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); } //**************************************************************************** // Partial grid example. // *************************************************************************** // Source image files specification. private const string PARTIAL_GRID_IMAGE_FILE = MIL.M_IMAGE_PATH + "PartialGrid.mim"; // Definition of the region to correct. private const double CORRECTED_SIZE_X = 60.0; private const double CORRECTED_SIZE_Y = 50.0; private const double CORRECTED_OFFSET_X = -35.0; private const double CORRECTED_OFFSET_Y = -5.0; private const int CORRECTED_IMAGE_SIZE_X = 512; // Definition of the parameters for the drawing of the grid info private const int LINE_HEIGHT = 15; private const int INFO_RECT_WIDTH = 180; private const int INFO_RECT_HEIGHT = 30; static void PartialGridCalibration(MIL_ID MilSystem, MIL_ID MilDisplay) { MIL_ID MilImage = MIL.M_NULL; // Image buffer identifier. MIL_ID MilCorrectedImage = MIL.M_NULL; // Corrected image identifier. MIL_ID MilGraList = MIL.M_NULL; // Graphic list identifier. MIL_ID MilCalibration = MIL.M_NULL; // Calibration identifier. MIL_INT CalibrationStatus = 0; MIL_INT ImageType = 0; MIL_INT CorrectedImageSizeY = 0; double RowSpacing = 0.0; double ColumnSpacing = 0.0; double CorrectedPixelSize = 0.0; const string BaseUnits = "m"; double BaseUnitFactor = 0.001; // Clear the display MIL.MdispControl(MilDisplay, MIL.M_OVERLAY_CLEAR, MIL.M_DEFAULT); // Allocate a graphic list and associate it to the display. MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref MilGraList); MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraList); // Restore source image into an automatically allocated image buffer. MIL.MbufRestore(PARTIAL_GRID_IMAGE_FILE, MilSystem, ref MilImage); MIL.MbufInquire(MilImage, MIL.M_TYPE, ref ImageType); // Display the image buffer. MIL.MdispSelect(MilDisplay, MilImage); // Pause to show the partial grid image. Console.Write("\nPARTIAL GRID CALIBRATION:\n"); Console.Write("-------------------------\n\n"); Console.Write("A camera will be calibrated using a rectangular grid that\n"); Console.Write("is only partially visible in the camera's field of view.\n"); Console.Write("The 2D code in the center is used as a fiducial to retrieve\n"); Console.Write("the characteristics of the calibration grid.\n"); Console.ReadKey(); // Allocate the calibration object. MIL.McalAlloc(MilSystem, MIL.M_TSAI_BASED, MIL.M_DEFAULT, ref MilCalibration); // Set the calibration to calibrate a partial grid with fiducial. MIL.McalControl(MilCalibration, MIL.M_GRID_PARTIAL, MIL.M_ENABLE); MIL.McalControl(MilCalibration, MIL.M_GRID_FIDUCIAL, MIL.M_DATAMATRIX); // Calibrate the camera with the partial grid with fiducial. MIL.McalGrid(MilCalibration, MilImage, GRID_OFFSET_X, GRID_OFFSET_Y, GRID_OFFSET_Z, MIL.M_UNKNOWN, MIL.M_UNKNOWN, MIL.M_FROM_FIDUCIAL, MIL.M_FROM_FIDUCIAL, MIL.M_DEFAULT, MIL.M_CHESSBOARD_GRID); MIL.McalInquire(MilCalibration, MIL.M_CALIBRATION_STATUS + MIL.M_TYPE_MIL_INT, ref CalibrationStatus); if (CalibrationStatus == MIL.M_CALIBRATED) { // Draw the absolute coordinate system. MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_RED); MIL.McalDraw(MIL.M_DEFAULT, MilCalibration, MilGraList, MIL.M_DRAW_ABSOLUTE_COORDINATE_SYSTEM + MIL.M_DRAW_AXES, MIL.M_DEFAULT, MIL.M_DEFAULT); MIL.McalDraw(MIL.M_DEFAULT, MilCalibration, MilGraList, MIL.M_DRAW_ABSOLUTE_COORDINATE_SYSTEM + MIL.M_DRAW_MAJOR_MARKS, MIL.M_DEFAULT, MIL.M_DEFAULT); MIL.McalDraw(MIL.M_DEFAULT, MilCalibration, MilGraList, MIL.M_DRAW_ABSOLUTE_COORDINATE_SYSTEM + MIL.M_DRAW_MINOR_MARKS, MIL.M_DEFAULT, MIL.M_DEFAULT); // Get the information of the grid read from the fiducial. MIL.McalInquire(MilCalibration, MIL.M_ROW_SPACING, ref RowSpacing); MIL.McalInquire(MilCalibration, MIL.M_COLUMN_SPACING, ref ColumnSpacing); // Draw the information of the grid read from the fiducial. MIL.MgraControl(MIL.M_DEFAULT, MIL.M_INPUT_UNITS, MIL.M_DISPLAY); MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_BLACK); MIL.MgraRectFill(MIL.M_DEFAULT, MilGraList, 0, 0, INFO_RECT_WIDTH, INFO_RECT_HEIGHT); MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_RED); DrawGridInfo(MilGraList, "Row spacing", RowSpacing * BaseUnitFactor, 0, BaseUnits); DrawGridInfo(MilGraList, "Col spacing", ColumnSpacing * BaseUnitFactor, 1, BaseUnits); // Pause to show the calibration result. Console.Write("The camera has been calibrated.\n\n"); Console.Write("The grid information read is displayed.\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Calculate the pixel size and size Y of the corrected image. CorrectedPixelSize = CORRECTED_SIZE_X / CORRECTED_IMAGE_SIZE_X; CorrectedImageSizeY = (MIL_INT)(CORRECTED_SIZE_Y / CorrectedPixelSize); // Allocate the corrected image. MIL.MbufAlloc2d(MilSystem, CORRECTED_IMAGE_SIZE_X, CorrectedImageSizeY, ImageType, MIL.M_IMAGE + MIL.M_PROC + MIL.M_DISP, ref MilCorrectedImage); // Calibrate the corrected image. MIL.McalUniform(MilCorrectedImage, CORRECTED_OFFSET_X, CORRECTED_OFFSET_Y, CorrectedPixelSize, CorrectedPixelSize, 0.0, MIL.M_DEFAULT); // Correct the calibrated image. MIL.McalTransformImage(MilImage, MilCorrectedImage, MilCalibration, MIL.M_BILINEAR + MIL.M_OVERSCAN_CLEAR, MIL.M_DEFAULT, MIL.M_WARP_IMAGE + MIL.M_USE_DESTINATION_CALIBRATION); // Select the corrected image on the display. MIL.MgraClear(MIL.M_DEFAULT, MilGraList); MIL.MdispSelect(MilDisplay, MilCorrectedImage); // Pause to show the corrected image. Console.Write("A sub-region of the grid was selected and transformed\n"); Console.Write("to remove the distortions.\n"); Console.Write("The sub-region dimensions and position are:\n"); Console.Write(" Size X : {0:F3} {1}\n", CORRECTED_SIZE_X * BaseUnitFactor, BaseUnits); Console.Write(" Size Y : {0:F3} {1}\n", CORRECTED_SIZE_Y * BaseUnitFactor, BaseUnits); Console.Write(" Offset X: {0:F3} {1}\n", CORRECTED_OFFSET_X * BaseUnitFactor, BaseUnits); Console.Write(" Offset Y: {0:F3} {1}\n", CORRECTED_OFFSET_Y * BaseUnitFactor, BaseUnits); } else { Console.Write("Calibration generated an exception.\n"); Console.Write("See User Guide to resolve the situation.\n\n"); } // Wait for a key to be pressed. Console.Write("Press <Enter> to quit.\n\n"); Console.ReadKey(); // Free all allocations. MIL.MbufFree(MilCorrectedImage); MIL.McalFree(MilCalibration); MIL.MbufFree(MilImage); MIL.MgraFree(MilGraList); } // Draw an information of the grid. static void DrawGridInfo(MIL_ID MilGraList, string InfoTag, double Value, MIL_INT LineOffsetY, string Units) { string Info = string.Format("{0}: {1:F3} {2}", InfoTag, Value, Units); MIL.MgraText(MIL.M_DEFAULT, MilGraList, 0, LineOffsetY * LINE_HEIGHT, Info); } } }