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. MIL_ID MilImage = MIL.M_NULL; // Image buffer identifier. MIL_ID MilGraphicList = MIL.M_NULL; // Graphic list identifier. MIL_ID MilBinImage = MIL.M_NULL; // Binary image buffer identifier. MIL_ID MilBlobResult = MIL.M_NULL; // Blob result buffer identifier. MIL_ID MilBlobFeatureList = MIL.M_NULL; // Feature list identifier. MIL_INT TotalBlobs = 0; // Total number of blobs. MIL_INT BlobsWithHoles = 0; // Number of blobs with holes. MIL_INT BlobsWithRoughHoles = 0; // Number of blobs with rough holes. MIL_INT n = 0; // Counter. MIL_INT SizeX = 0; // Size X of the source buffer MIL_INT SizeY = 0; // Size Y of the source buffer double[] CogX = null; // X coordinate of center of gravity. double[] CogY = null; // Y coordinate of center of gravity. // Allocate defaults. MIL.MappAllocDefault(MIL.M_DEFAULT, ref MilApplication, ref MilSystem, ref MilDisplay, MIL.M_NULL, MIL.M_NULL); // Restore source image into image buffer. MIL.MbufRestore(IMAGE_FILE, MilSystem, ref MilImage); // Allocate a graphic list to hold the subpixel annotations to draw. MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref MilGraphicList); // Associate the graphic list to the display. MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraphicList); // Display the buffer. MIL.MdispSelect(MilDisplay, MilImage); // Allocate a binary image buffer for fast processing. MIL.MbufInquire(MilImage, MIL.M_SIZE_X, ref SizeX); MIL.MbufInquire(MilImage, MIL.M_SIZE_Y, ref SizeY); MIL.MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_PROC, ref MilBinImage); // Pause to show the original image. Console.Write("\nBLOB ANALYSIS:\n"); Console.Write("--------------\n\n"); Console.Write("This program determines the number of bolts, nuts and washers\n"); Console.Write("in the image and finds their center of gravity.\n"); Console.Write("Press <Enter> to continue.\n\n"); Console.ReadKey(); // Binarize image. MIL.MimBinarize(MilImage, MilBinImage, MIL.M_FIXED + MIL.M_GREATER_OR_EQUAL, IMAGE_THRESHOLD_VALUE, MIL.M_NULL); // Remove small particles and then remove small holes. MIL.MimOpen(MilBinImage, MilBinImage, MIN_BLOB_RADIUS, MIL.M_BINARY); MIL.MimClose(MilBinImage, MilBinImage, MIN_BLOB_RADIUS, MIL.M_BINARY); // Allocate a feature list. MIL.MblobAllocFeatureList(MilSystem, ref MilBlobFeatureList); // Enable the Area and Center Of Gravity feature calculation. MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_AREA); MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_CENTER_OF_GRAVITY); // Allocate a blob result buffer. MIL.MblobAllocResult(MilSystem, ref MilBlobResult); // Calculate selected features for each blob. MIL.MblobCalculate(MilBinImage, MIL.M_NULL, MilBlobFeatureList, MilBlobResult); // Exclude blobs whose area is too small. MIL.MblobSelect(MilBlobResult, MIL.M_EXCLUDE, MIL.M_AREA, MIL.M_LESS_OR_EQUAL, MIN_BLOB_AREA, MIL.M_NULL); // Get the total number of selected blobs. MIL.MblobGetNumber(MilBlobResult, ref TotalBlobs); Console.Write("There are {0} objects ", TotalBlobs); // Read and print the blob's center of gravity. CogX = new double[TotalBlobs]; CogY = new double[TotalBlobs]; if (CogX != null && CogY != null) { // Get the results. MIL.MblobGetResult(MilBlobResult, MIL.M_CENTER_OF_GRAVITY_X, CogX); MIL.MblobGetResult(MilBlobResult, MIL.M_CENTER_OF_GRAVITY_Y, CogY); // Print the center of gravity of each blob. Console.Write("and their centers of gravity are:\n"); for (n = 0; n < TotalBlobs; n++) { Console.Write("Blob #{0}: X={1,5:0.0}, Y={2,5:0.0}\n", n, CogX[n], CogY[n]); } } else { Console.Write("\nError: Not enough memory.\n"); } // Draw a cross at the center of gravity of each blob. MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_RED); MIL.MblobDraw(MIL.M_DEFAULT, MilBlobResult, MilGraphicList, MIL.M_DRAW_CENTER_OF_GRAVITY, MIL.M_INCLUDED_BLOBS, MIL.M_DEFAULT); // Reverse what is considered to be the background so that // holes are seen as being blobs. MIL.MblobControl(MilBlobResult, MIL.M_FOREGROUND_VALUE, MIL.M_ZERO); // Add a feature to distinguish between types of holes.Since area // has already been added to the feature list, and the processing // mode has been changed, all blobs will be re-included and the area // of holes will be calculated automatically. MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_COMPACTNESS); // Calculate selected features for each blob. MIL.MblobCalculate(MilBinImage, MIL.M_NULL, MilBlobFeatureList, MilBlobResult); // Exclude small holes and large (the area around objects) holes. MIL.MblobSelect(MilBlobResult, MIL.M_EXCLUDE, MIL.M_AREA, MIL.M_OUT_RANGE, MIN_BLOB_AREA, MAX_BLOB_AREA); // Get the number of blobs with holes. MIL.MblobGetNumber(MilBlobResult, ref BlobsWithHoles); // Exclude blobs whose holes are compact (i.e.nuts). MIL.MblobSelect(MilBlobResult, MIL.M_EXCLUDE, MIL.M_COMPACTNESS, MIL.M_LESS_OR_EQUAL, MIN_COMPACTNESS, MIL.M_NULL); // Get the number of blobs with holes that are NOT compact. MIL.MblobGetNumber(MilBlobResult, ref BlobsWithRoughHoles); // Print results. Console.Write("\nIdentified objects:\n"); Console.Write("{0} bolts\n", TotalBlobs - BlobsWithHoles); Console.Write("{0} nuts\n", BlobsWithHoles - BlobsWithRoughHoles); Console.Write("{0} washers\n\n", BlobsWithRoughHoles); Console.Write("Press <Enter> to end.\n\n"); Console.ReadKey(); // Free all allocations. MIL.MgraFree(MilGraphicList); MIL.MblobFree(MilBlobResult); MIL.MblobFree(MilBlobFeatureList); MIL.MbufFree(MilBinImage); MIL.MbufFree(MilImage); MIL.MappFreeDefault(MilApplication, MilSystem, MilDisplay, MIL.M_NULL, MIL.M_NULL); }
private static void InteractivityExample(MIL_ID MilSystem, MIL_ID MilDisplay) { MIL_ID MilImage = MIL.M_NULL; // Image buffer identifier. MIL_ID MilGraphicsList = MIL.M_NULL; // Graphics list identifier. MIL_ID MilGraphicsContext = MIL.M_NULL; // Graphics context identifier. MIL_ID MilBinImage = MIL.M_NULL; // Binary image buffer identifier. MIL_ID MilBlobFeatureList = MIL.M_NULL; // Feature list identifier. MIL_ID MilBlobResult = MIL.M_NULL; // Blob result buffer identifier. MIL_INT SizeX = 0; // Size X of the source buffer. MIL_INT SizeY = 0; // Size Y of the source buffer. MIL_INT RegionLabel = 0; // Label value of the region. STestParameters DataStructure = new STestParameters(); // Hook function data structure. // Restore the source image. MIL.MbufRestore(IMAGE_FILE, MilSystem, ref MilImage); // Display the buffer. MIL.MdispSelect(MilDisplay, MilImage); // Allocate a graphics list to hold the subpixel annotations. MIL.MgraAllocList(MilSystem, MIL.M_DEFAULT, ref MilGraphicsList); // Associate the graphics list to the display for annotations. MIL.MdispControl(MilDisplay, MIL.M_ASSOCIATED_GRAPHIC_LIST_ID, MilGraphicsList); // Allocate a graphics context for the draw operations. MIL.MgraAlloc(MilSystem, ref MilGraphicsContext); // Enable the interactive mode. MIL.MdispControl(MilDisplay, MIL.M_GRAPHIC_LIST_INTERACTIVE, MIL.M_ENABLE); // Add a selectable rectangular region. MIL.MgraRectAngle(MilGraphicsContext, MilGraphicsList, RECTANGLE_POSITION_X, RECTANGLE_POSITION_Y, RECTANGLE_WIDTH, RECTANGLE_HEIGHT, RECTANGLE_ANGLE, MIL.M_CENTER_AND_DIMENSION); // Retrieve the label of the rectangle graphic. MIL.MgraInquireList(MilGraphicsList, MIL.M_LIST, MIL.M_DEFAULT, MIL.M_LAST_LABEL, ref RegionLabel); // Disable the selectable mode for the next annotations to the graphics list. MIL.MgraControl(MilGraphicsContext, MIL.M_SELECTABLE, MIL.M_DISABLE); // Allocate a binary image buffer for fast processing. MIL.MbufInquire(MilImage, MIL.M_SIZE_X, ref SizeX); MIL.MbufInquire(MilImage, MIL.M_SIZE_Y, ref SizeY); MIL.MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_PROC, ref MilBinImage); // Binarize the source image. MIL.MimBinarize(MilImage, MilBinImage, MIL.M_FIXED + MIL.M_LESS, IMAGE_THRESHOLD_VALUE, MIL.M_NULL); // Allocate a blob feature list and a blob result. MIL.MblobAllocFeatureList(MilSystem, ref MilBlobFeatureList); MIL.MblobAllocResult(MilSystem, ref MilBlobResult); // Select the blob features to calculate (Center Of Gravity and Box). MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_CENTER_OF_GRAVITY); MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_BOX); // Programmatically initialize the selected state of the rectangle region. MIL.MgraControlList(MilGraphicsList, MIL.M_GRAPHIC_LABEL(RegionLabel), MIL.M_DEFAULT, MIL.M_GRAPHIC_SELECTED, MIL.M_TRUE); // Perform and display a first count of the number of objects // within the initial region. CountObjects(MilDisplay, MilGraphicsList, MilGraphicsContext, MilBinImage, MilBlobFeatureList, MilBlobResult); // Initialize the hook data structure, then associate the hook function to // the "MIL.M_GRAPHIC_MODIFIED" event. The hook function will be called // with any region interaction by the user. DataStructure.MilDisplay = MilDisplay; DataStructure.MilGraphicsList = MilGraphicsList; DataStructure.MilGraphicsContext = MilGraphicsContext; DataStructure.MilBinImage = MilBinImage; DataStructure.RegionLabel = RegionLabel; DataStructure.MilBlobFeatureList = MilBlobFeatureList; DataStructure.MilBlobResult = MilBlobResult; GCHandle DataStructureHandle = GCHandle.Alloc(DataStructure); MIL_GRA_HOOK_FUNCTION_PTR HookHandlerDelegate = new MIL_GRA_HOOK_FUNCTION_PTR(HookHandler); MIL.MgraHookFunction(MilGraphicsList, MIL.M_GRAPHIC_MODIFIED, HookHandlerDelegate, GCHandle.ToIntPtr(DataStructureHandle)); if (MIL.MdispInquire(MilDisplay, MIL.M_DISPLAY_TYPE, MIL.M_NULL) != MIL.M_AUXILIARY) { Console.WriteLine("You can try using your mouse to interactively modify the"); Console.WriteLine("displayed region, such as moving, resizing, or rotating the"); Console.WriteLine("region. If you do so, the results and annotations will be"); Console.WriteLine("immediately updated\n"); Console.WriteLine(); } else { Console.WriteLine("***NOTE: This example does not implement the interactivity"); Console.WriteLine(" with an auxiliary display."); Console.WriteLine(); } Console.WriteLine("Press <Enter> to exit."); Console.ReadKey(); MIL.MgraHookFunction(MilGraphicsList, MIL.M_GRAPHIC_MODIFIED + MIL.M_UNHOOK, HookHandlerDelegate, GCHandle.ToIntPtr(DataStructureHandle)); DataStructureHandle.Free(); // Free all allocations. MIL.MblobFree(MilBlobResult); MIL.MblobFree(MilBlobFeatureList); MIL.MbufFree(MilBinImage); MIL.MgraFree(MilGraphicsContext); MIL.MgraFree(MilGraphicsList); MIL.MbufFree(MilImage); }
// Find defects in corrected depth map, compute max deviation and draw contours. static void PerformBlobAnalysis(MIL_ID MilSystem, MIL_ID MilDisplay, MIL_ID MilOverlayImage, MIL_ID MilDepthMap) { MIL_ID MilBinImage = MIL.M_NULL; // Binary image buffer identifier. MIL_ID MilBlobFeatureList = MIL.M_NULL; // Feature list identifier. MIL_ID MilBlobResult = MIL.M_NULL; // Blob result buffer identifier. MIL_INT SizeX = 0; // Width of depth map. MIL_INT SizeY = 0; // Height of depth map. MIL_INT TotalBlobs = 0; // Total number of blobs. MIL_INT n = 0; // Counter. MIL_INT[] MinPixels = null; // Maximum height of defects. double DefectThreshold = 0.0; // A gray level below it is a defect. double[] CogX = null; // X coordinate of center of gravity. double[] CogY = null; // Y coordinate of center of gravity. // Get size of depth map. MIL.MbufInquire(MilDepthMap, MIL.M_SIZE_X, ref SizeX); MIL.MbufInquire(MilDepthMap, MIL.M_SIZE_Y, ref SizeY); // Allocate a binary image buffer for fast processing. MIL.MbufAlloc2d(MilSystem, SizeX, SizeY, 1 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_PROC, ref MilBinImage); // Binarize image. DefectThreshold = (EXPECTED_HEIGHT - DEFECT_THRESHOLD) * SCALE_FACTOR; MIL.MimBinarize(MilDepthMap, MilBinImage, MIL.M_FIXED + MIL.M_LESS_OR_EQUAL, DefectThreshold, MIL.M_NULL); // Remove small particles. MIL.MimOpen(MilBinImage, MilBinImage, MIN_BLOB_RADIUS, MIL.M_BINARY); // Allocate a feature list. MIL.MblobAllocFeatureList(MilSystem, ref MilBlobFeatureList); // Enable the Center Of Gravity and Min Pixel features calculation. MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_CENTER_OF_GRAVITY); MIL.MblobSelectFeature(MilBlobFeatureList, MIL.M_MIN_PIXEL); // Allocate a blob result buffer. MIL.MblobAllocResult(MilSystem, ref MilBlobResult); // Calculate selected features for each blob. MIL.MblobCalculate(MilBinImage, MilDepthMap, MilBlobFeatureList, MilBlobResult); // Get the total number of selected blobs. MIL.MblobGetNumber(MilBlobResult, ref TotalBlobs); Console.WriteLine("Number of defects: {0}", TotalBlobs); // Read and print the blob characteristics. CogX = new double[TotalBlobs]; CogY = new double[TotalBlobs]; MinPixels = new MIL_INT[TotalBlobs]; if (CogX != null && CogY != null && MinPixels != null) { // Get the results. MIL.MblobGetResult(MilBlobResult, MIL.M_CENTER_OF_GRAVITY_X, CogX); MIL.MblobGetResult(MilBlobResult, MIL.M_CENTER_OF_GRAVITY_Y, CogY); MIL.MblobGetResult(MilBlobResult, MIL.M_MIN_PIXEL + MIL.M_TYPE_MIL_INT, MinPixels); // Draw the defects. MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_RED); MIL.MblobDraw(MIL.M_DEFAULT, MilBlobResult, MilOverlayImage, MIL.M_DRAW_BLOBS, MIL.M_INCLUDED_BLOBS, MIL.M_DEFAULT); MIL.MgraColor(MIL.M_DEFAULT, MIL.M_COLOR_WHITE); // Print the depth of each blob. for (n = 0; n < TotalBlobs; n++) { double DepthOfDefect; string DepthString; // Write the depth of the defect in the overlay. DepthOfDefect = EXPECTED_HEIGHT - (MinPixels[n] / SCALE_FACTOR); DepthString = string.Format("{0:0.00} mm", DepthOfDefect); Console.WriteLine("Defect #{0}: depth ={1,5:0.00} mm", n, DepthOfDefect); Console.WriteLine(); MIL.MgraText(MIL.M_DEFAULT, MilOverlayImage, CogX[n] + TEXT_H_OFFSET_1, CogY[n] + TEXT_V_OFFSET_1, "Defect depth"); MIL.MgraText(MIL.M_DEFAULT, MilOverlayImage, CogX[n] + TEXT_H_OFFSET_2, CogY[n] + TEXT_V_OFFSET_2, DepthString); } } else { Console.WriteLine("Error: Not enough memory."); Console.WriteLine(); } // Free all allocations. MIL.MblobFree(MilBlobResult); MIL.MblobFree(MilBlobFeatureList); MIL.MbufFree(MilBinImage); }