/// <summary> /// Execute segmentation process. /// </summary> public void Execute() { if (image != null) { UMat temp = SegmentationUtils.IncreaseContrast(image.ToUMat(), 5.0, 8); temp = SegmentationUtils.Blur(temp, 3, 1.0); temp = SegmentationUtils.Sharp(temp); Image <Bgr, byte> tempImage = new Image <Bgr, byte>(temp.Bitmap); UMat uMatChannel = SegmentationUtils.GetColorChannelAsUMat(segmentationParameters.Colorspace, tempImage, segmentationParameters.Channel); UMat thresholded = null; using (UMat copy = uMatChannel.Clone()) { if (segmentationParameters.UseOtsu) { thresholded = SegmentationUtils.ThresholdOtsu(copy); } else { thresholded = SegmentationUtils.Threshold(copy, segmentationParameters.Threshold); } } UMat closed = SegmentationUtils.Closing(thresholded, 5); //UMat eroded = SegmentationUtils.Erode(closed, 15); UMat dilated = SegmentationUtils.Dilate(closed, 10); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\dilated.png", dilated); VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); VectorOfVectorOfPoint contoursRelevant = new VectorOfVectorOfPoint(); CvInvoke.FindContours(dilated, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple); int autoMaxPixelSize = ImageUtils.GetPercentualImagePixelCount(image, 0.03f); for (int i = 0; i < contours.Size; i++) { double area = CvInvoke.ContourArea(contours[i]); if (IsContourRelevant(area, autoMaxPixelSize, segmentationParameters)) { contoursRelevant.Push(contours[i]); } } CvInvoke.DrawContours(image, contoursRelevant, -1, new MCvScalar(0, 0, 255)); mask = new Image <Gray, Byte>(image.Width, image.Height, new Gray(0.0)); CvInvoke.DrawContours(mask, contoursRelevant, -1, new MCvScalar(255.0), thickness: -1); } }
/// <summary> /// Standard segmentation of given image. /// 1. Thresholding /// 2. Morphological operations /// 3. Find contours /// 4. Calculate coefficients and classificate contours /// </summary> /// <param name="uMatChannel">image in UMat format</param> private void StandardSegmentation(UMat uMatChannel) { // thresholding UMat thresholded = null; using (UMat copy = uMatChannel.Clone()) { if (segmentationParameters.UseOtsu) { thresholded = SegmentationUtils.ThresholdOtsu(copy); } else { thresholded = SegmentationUtils.Threshold(copy, segmentationParameters.Threshold); } } // morphological operations (todo: make kernel generic or depending on image size) UMat opened = SegmentationUtils.Opening(thresholded, 5); UMat dilated = SegmentationUtils.Dilate(opened, 5); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\dilated.png", dilated); UMat inverted = new UMat(); CvInvoke.BitwiseNot(dilated, inverted); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\inverted.png", inverted); VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); VectorOfVectorOfPoint contoursRelevant = new VectorOfVectorOfPoint(); CvInvoke.FindContours(inverted, contours, null, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple); int nonRelevantPixelSize = ImageUtils.GetPercentualImagePixelCount <UMat>(inverted, 0.005f); Console.WriteLine("Non relevant pixel size: " + nonRelevantPixelSize); Console.WriteLine("Number of contours: " + contours.Size); ClassifyContours(uMatChannel, ref contours, ref contoursRelevant, nonRelevantPixelSize); // debug: show image with found contours //CvInvoke.DrawContours(image, contoursRelevant, -1, new MCvScalar(0, 255, 0)); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\image_with_contours.png", image.ToUMat()); // creat mask with rigid structures Image <Gray, byte> mask = new Image <Gray, byte>(image.Width, image.Height, new Gray(0.0)); CvInvoke.DrawContours(mask, contoursRelevant, -1, new MCvScalar(255.0), thickness: -1); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\mask.png", mask.ToUMat()); UMat inv1 = new UMat(); CvInvoke.BitwiseNot(mask, inv1); UMat convertedMask = new UMat(); inv1.ConvertTo(convertedMask, DepthType.Cv32F); // create mask with non rigid structures Image <Gray, byte> convMask = new Image <Gray, byte>(convertedMask.Bitmap); Image <Gray, byte> mask2 = new Image <Gray, byte>(image.Width, image.Height, new Gray(255.0)); CvInvoke.Subtract(particleMask, convMask, mask2); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\INV_mask.png", mask2.ToUMat()); UMat inv2 = new UMat(); //CvInvoke.BitwiseNot(mask2, inv2); CvInvoke.BitwiseAnd(mask2, mask, inv2); inv2 = SegmentationUtils.Dilate(inv2, 10); UMat convertedMask2 = new UMat(); inv2.ConvertTo(convertedMask2, DepthType.Cv32F); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\_mask1.png", convertedMask); //ReadWriteUtils.WriteUMatToFile(ApplicationContext.OutputPath + "\\_mask2.png", convertedMask2); // add masks to list masks.Add(convertedMask); masks.Add(convertedMask2); }