private static void CountObjects(MIL_ID MilDisplay, MIL_ID MilGraphicsList, MIL_ID MilGraphicsContext, MIL_ID MilBinImage, MIL_ID MilBlobFeatureList, MIL_ID MilBlobResult) { MIL_INT NumberOfBlobs = 0; MIL_INT NumberOfPrimitives = 0; MIL_INT Index; string TextLabel; // Disable the display update for better performance. MIL.MdispControl(MilDisplay, MIL.M_UPDATE, MIL.M_DISABLE); // Remove all elements from the graphics list, except the rectangle // region primitive at index 0. MIL.MgraInquireList(MilGraphicsList, MIL.M_LIST, MIL.M_DEFAULT, MIL.M_NUMBER_OF_GRAPHICS, ref NumberOfPrimitives); for (Index = NumberOfPrimitives - 1; Index > 0; Index--) { MIL.MgraControlList(MilGraphicsList, MIL.M_GRAPHIC_INDEX(Index), MIL.M_DEFAULT, MIL.M_DELETE, MIL.M_DEFAULT); } // Set the input region. The blob analysis will be done // from the (filled) interactive rectangle. MIL.MbufSetRegion(MilBinImage, MilGraphicsList, MIL.M_DEFAULT, MIL.M_RASTERIZE + MIL.M_FILL_REGION, MIL.M_DEFAULT); // Calculate the blobs and their features. MIL.MblobCalculate(MilBinImage, MIL.M_NULL, MilBlobFeatureList, MilBlobResult); // Get the total number of blobs. MIL.MblobGetNumber(MilBlobResult, ref NumberOfBlobs); // Set the input units to display unit for the count annotations. MIL.MgraControl(MilGraphicsContext, MIL.M_INPUT_UNITS, MIL.M_DISPLAY); TextLabel = string.Format(" Number of blobs found: {0:00} ", NumberOfBlobs); MIL.MgraColor(MilGraphicsContext, MIL.M_COLOR_WHITE); MIL.MgraText(MilGraphicsContext, MilGraphicsList, 10, 10, TextLabel); // Restore the input units to pixel units for result annotations. MIL.MgraControl(MilGraphicsContext, MIL.M_INPUT_UNITS, MIL.M_PIXEL); // Draw blob center of gravity annotation. MIL.MgraColor(MilGraphicsContext, MIL.M_COLOR_RED); MIL.MblobDraw(MilGraphicsContext, MilBlobResult, MilGraphicsList, MIL.M_DRAW_CENTER_OF_GRAVITY, MIL.M_INCLUDED_BLOBS, MIL.M_DEFAULT); // Draw blob bounding box annotations. MIL.MgraColor(MilGraphicsContext, MIL.M_COLOR_GREEN); MIL.MblobDraw(MilGraphicsContext, MilBlobResult, MilGraphicsList, MIL.M_DRAW_BOX, MIL.M_INCLUDED_BLOBS, MIL.M_DEFAULT); // Enable the display to update the drawings. MIL.MdispControl(MilDisplay, MIL.M_UPDATE, MIL.M_ENABLE); }
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); }
// 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); }