private void toolStripMenuItem2_Click(object sender, EventArgs e) { try { if (imgInput == null) { MessageBox.Show("please select an image."); return; } var img = new Bitmap(pictureBox1.Image).ToImage <Bgr, byte>(); var mask = img.Convert <Gray, byte>().ThresholdBinaryInv(new Gray(150), new Gray(255)); Mat distanceTransform = new Mat(); CvInvoke.DistanceTransform(mask, distanceTransform, null, Emgu.CV.CvEnum.DistType.L2, 3); CvInvoke.Normalize(distanceTransform, distanceTransform, 0, 255, Emgu.CV.CvEnum.NormType.MinMax); var markers = distanceTransform.ToImage <Gray, byte>().ThresholdBinary(new Gray(50), new Gray(255)); CvInvoke.ConnectedComponents(markers, markers); var finalmarkers = markers.Convert <Gray, Int32>(); CvInvoke.Watershed(img, finalmarkers); Image <Gray, byte> boundaaries = finalmarkers.Convert <byte>(delegate(Int32 x) { return((byte)(x == -1 ? 255 : 0)); }); boundaaries._Dilate(1); img.SetValue(new Bgr(0, 255, 0), boundaaries); // AddImage(img, ""); pictureBox2.Image = img.ToBitmap(); pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
private void processToolStripMenuItem_Click(object sender, EventArgs e) { if (imageInput == null) { return; } try { // Convert img to grayscale -> convert img to binary using max threshold of 100 // (if value is more than 100, set it to the max value [255]) -> close effects // using dilation then erosion var temp = imageInput.Convert <Gray, byte>().ThresholdBinary(new Gray(100), new Gray(255)) .Dilate(1).Erode(1); // Matrix to store the labels from the image Mat labels = new Mat(); // Find the number of connected components int nLabels = CvInvoke.ConnectedComponents(temp, labels); // Konvesi labels menjadi sebuah image connectedComponents = labels.ToImage <Gray, byte>(); // connectedComponents can not be shown because it is a value between 1 - 0 rightPictureBox.Image = temp.Bitmap; } catch (Exception exception) { MessageBox.Show(exception.Message); } }
private void processToolStripMenuItem_Click(object sender, EventArgs e) { if (imgInput == null) { return; } try { var temp = imgInput.Convert <Gray, byte>().ThresholdBinary(new Gray(100), new Gray(255)) .Dilate(1).Erode(1); Mat labels = new Mat(); int nLabels = CvInvoke.ConnectedComponents(temp, labels); CC = labels.ToImage <Gray, byte>(); pictureBox2.Image = temp.Bitmap; } catch (Exception ee) { MessageBox.Show(ee.Message); } }
private void processToolStripMenuItem_Click(object sender, EventArgs e) { if (imgInput == null) { return; } try { var tempImg = imgInput.Convert <Gray, byte>().ThresholdBinary(new Gray(65), new Gray(255)).Dilate(1).Erode(1); Mat mLabel = new Mat(); int nLabels = CvInvoke.ConnectedComponents(tempImg, mLabel); cc = mLabel.ToImage <Gray, byte>(); pictureBox2.Image = tempImg.ToBitmap(); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
static void Main(string[] args) { // Read image Mat img = CvInvoke.Imread(@"C:\EMT\Image\EMT_Lab2\ConnectImage3.png", ImreadModes.Grayscale); // Create window and show image CvInvoke.NamedWindow("Original", NamedWindowType.KeepRatio); CvInvoke.Imshow("Original", img); // Create new cv image same size as img Mat imglabel = new Mat(img.Rows, img.Cols, DepthType.Cv16U, 1); // Count number of connected components int label = CvInvoke.ConnectedComponents(img, imglabel, LineType.FourConnected, DepthType.Cv16U); // Create new cv image with unsigned 8 bit Mat imglabelscale = new Mat(img.Rows, img.Cols, DepthType.Cv8U, 1); // Find max and min values in cv image array CvInvoke.MinMaxIdx(imglabel, out double minVal, out double maxVal, null, null); // Scale image to follow min and max CvInvoke.ConvertScaleAbs(imglabel, imglabelscale, 255 / (maxVal - minVal), 0); // Write image to path as png CvInvoke.Imwrite(@"C:\EMT\Image\EMT_Lab2\Results1.png", imglabelscale); String imgtitle = "Connected Objects = " + Convert.ToString(label - 1); CvInvoke.NamedWindow(imgtitle, NamedWindowType.KeepRatio); CvInvoke.Imshow(imgtitle, imglabelscale); CvInvoke.WaitKey(0); CvInvoke.DestroyAllWindows(); }
private Bitmap Processar(string Caminho, string NomeImagem) { if (pictureBox1.Image == null) { return(null); } CelulasMicronucleadas = 0; CelulasCariolise = 0; CelulasBinucleadas = 0; CelulasNormais = 0; CelulasIgnoradas = 0; CelulasTotais = 0; Background = 0; int PosicaoThresh2 = 0; int PosicaoNucleo2 = 0; SimpleBlobDetector param = new SimpleBlobDetector(); VectorOfKeyPoint keypoint = new VectorOfKeyPoint(); Camera = new Image <Hsv, Byte>(Caminho); CameraResult = new Image <Rgb, Byte>(Caminho); Image <Gray, Byte> ImageSave = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Rgb, Byte> ImageSave2 = new Image <Rgb, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> Cellthresh = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> ThreshSet = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> ThreshSet2 = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Rgb, Byte> separateCellRGB = new Image <Rgb, Byte>(Camera.Cols, Camera.Rows); Image <Hsv, Byte> separateCell = new Image <Hsv, Byte>(Camera.Cols, Camera.Rows); Image <Hsv, Byte> separateNuclei = new Image <Hsv, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> MaskContourNuclei = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> MaskContourCell = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Hsv, Byte> maskCell = new Image <Hsv, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> ContourCompare = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Gray, Byte> Cellthresh2 = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); Image <Hsv, Byte> nothing = new Image <Hsv, Byte>(Camera.Cols, Camera.Rows); Mat EllipseKernel = new Mat(); Matrix <byte> kernel1 = new Matrix <byte>(new Byte[3, 3] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }); var mask = Camera[0]; //ImageSave = mask; //ImageSave.Save("met_hsv.png"); EllipseKernel = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(5, 5), new Point(-1, -1)); CvInvoke.MorphologyEx(mask, mask, MorphOp.Open, EllipseKernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); CvInvoke.MorphologyEx(mask, mask, MorphOp.Close, EllipseKernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); //ImageSave = mask; //ImageSave.Save("met_openclose.png"); CvInvoke.Threshold(mask, mask, 50, 255, ThresholdType.Otsu); //ImageSave = mask; //ImageSave.Save("met_otsu.png"); Mat distanceTransform = new Mat(); CvInvoke.DistanceTransform(mask, distanceTransform, null, Emgu.CV.CvEnum.DistType.L2, 5); CvInvoke.Normalize(distanceTransform, distanceTransform, 0, 255, NormType.MinMax); var markers = distanceTransform.ToImage <Gray, byte>(); //ImageSave = markers; //ImageSave.Save("met_distancetransform.png"); markers = markers.ThresholdBinary(new Gray(100), new Gray(255)); CvInvoke.ConnectedComponents(markers, markers); var finalMarkers = markers.Convert <Gray, Int32>(); CvInvoke.Watershed(Camera, finalMarkers); Image <Gray, byte> boundaries = finalMarkers.Convert <byte>(delegate(Int32 x) { return((byte)(x == -1 ? 255 : 0)); }); boundaries._Dilate(1); //ImageSave = boundaries; //ImageSave.Save("met_watershed.png"); CvInvoke.Threshold(boundaries, boundaries, 0, 255, ThresholdType.BinaryInv); Image <Gray, Byte> CellsBoundaries = new Image <Gray, Byte>(Camera.Cols, Camera.Rows); CellsBoundaries.SetZero(); CellsBoundaries = boundaries & mask; //ImageSave = CellsBoundaries; //ImageSave.Save("met_segmentado.png"); //////////////////////////////////////// // aqui cria o contorno do watershed e separa o nucleo de cada celula encontrada VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); Mat hierarchy = new Mat(); CvInvoke.FindContours(CellsBoundaries, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone); for (int i = 0; i < contours.Size; i++) { maskCell.SetZero(); separateCell.SetZero(); separateCellRGB.SetZero(); separateNuclei.SetZero(); MaskContourNuclei.SetZero(); MaskContourCell.SetZero(); nothing.SetZero(); double area = CvInvoke.ContourArea(contours[i]); double perimeter = CvInvoke.ArcLength(contours[i], true); //cria a mascara para separar cada célula e seus núcleos //caso o contorno for a area total da foto, ignora if (area < 400) { Background += 1; continue; } //se a celula for muito grande é uma célula a ser ignorada else if (area > 4000 || area < 1000 || perimeter > 250 || perimeter < 100) { CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 255, 255)); CelulasIgnoradas += 1; continue; } //se tudo estiver correto, realiza a análise do núcleo da célula else { CvInvoke.DrawContours(maskCell, contours, i, new MCvScalar(255, 255, 255), -1); separateCell = Camera & maskCell; ImageSave = separateCell[0].Convert <Gray, Byte>(); ImageSave.Save("met_mascaracelula.png"); var teste2 = separateCell.Convert <Gray, Byte>(); Double intensity = 0.0; double pixelintensity = 0; for (int cols = 0; cols < teste2.Cols; cols++) { for (int rows = 0; rows < teste2.Rows; rows++) { intensity += teste2.Data[rows, cols, 0]; if (teste2.Data[rows, cols, 0] > 0) { pixelintensity++; } } } intensity = intensity / pixelintensity; // verifica a intensidade de pixels na celula if (intensity < 40) { CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 0, 255)); CelulasCariolise++; break; } else if (intensity < 55) { thresh = 120; } else { thresh = 110; } int AchouNucleo = 0; int PosicaoThresh = 0; int PosicaoNucleo = 0; int Nucleos = 0; int Micronucleada = 0; int Binucleada = 0; int Normal = 0; double AreaNucleo1 = 0; double AreaNucleo2 = 0; int OutroNucleo = 0; double AreaOutroNucleo = 0; int PosicaoOutroNucleo = 0; VectorOfVectorOfPoint Nucleithresh = new VectorOfVectorOfPoint(); for (int k = thresh; k > 95; k--) { Mat NucleihierarchyThresh = new Mat(); Mat MorphStructuring = new Mat(); Cellthresh = separateCell[0]; MorphStructuring = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(5, 5), new Point(-1, -1)); CvInvoke.Threshold(Cellthresh, Cellthresh, k, 255, ThresholdType.Binary); CvInvoke.MorphologyEx(Cellthresh, Cellthresh, MorphOp.Dilate, MorphStructuring, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); CvInvoke.FindContours(Cellthresh, Nucleithresh, NucleihierarchyThresh, RetrType.Tree, ChainApproxMethod.ChainApproxSimple); Nucleos = 0; AchouNucleo = 0; AreaNucleo1 = 0; AreaNucleo2 = 0; OutroNucleo = 0; if (Nucleithresh.Size > 0 && Nucleithresh.Size < 3) { for (int j = 0; j < Nucleithresh.Size; j++) { ContourCompare.SetZero(); MaskContourCell.SetZero(); MaskContourNuclei.SetZero(); double AreaNucleiThresh = CvInvoke.ContourArea(Nucleithresh[j]); double PerimeterNucleiThresh = CvInvoke.ArcLength(Nucleithresh[j], true); CvInvoke.DrawContours(MaskContourCell, contours, i, new MCvScalar(255, 255, 255)); CvInvoke.DrawContours(MaskContourNuclei, Nucleithresh, j, new MCvScalar(255, 255, 255)); ContourCompare = MaskContourCell & MaskContourNuclei; int pixel = 0; for (int cols = 0; cols < ContourCompare.Cols; cols++) { for (int rows = 0; rows < ContourCompare.Rows; rows++) { pixel += ContourCompare.Data[rows, cols, 0]; } } if (AreaNucleiThresh > 100 || pixel > 0) { break; } if (AreaNucleiThresh < 100 && AreaNucleiThresh > 25 && pixel == 0 && AchouNucleo == 0 && PerimeterNucleiThresh < 31) { AchouNucleo = 1; PosicaoThresh = k; PosicaoNucleo = j; ThreshSet = Cellthresh; AreaNucleo1 = AreaNucleiThresh; } if (AreaNucleiThresh < 25 && pixel == 0 && AchouNucleo == 0 && OutroNucleo == 0) { OutroNucleo = 1; AreaOutroNucleo = AreaNucleiThresh; PosicaoOutroNucleo = j; } if (AchouNucleo == 1 && OutroNucleo == 1 && pixel == 0) { Nucleos++; if (Math.Abs(AreaNucleo1 - AreaOutroNucleo) > 20) { Micronucleada = 1; } else { Binucleada = 1; } continue; } if ((AchouNucleo == 1 && OutroNucleo == 0 && pixel == 0)) { Nucleos++; AreaNucleo2 = AreaNucleiThresh; if (Nucleos > 1) { if (Math.Abs(AreaNucleo1 - AreaNucleo2) > 20) { Micronucleada = 1; } else { Binucleada = 1; } continue; } else if (Nucleos == 1) { Normal = 1; } } } } if (AchouNucleo == 1) { break; } } // CONTABILIZA E PINTA A CÉLULA if (AchouNucleo == 1) { int check = 0; for (int j = 0; j < Nucleithresh.Size; j++) { if (Nucleos == 2 && Binucleada == 1) { if (check == 0) // conta somente uma vez! { check = 1; CelulasBinucleadas++; } CvInvoke.DrawContours(CameraResult, Nucleithresh, j, new MCvScalar(255, 0, 0)); CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 0, 0)); } else if (Nucleos == 2 && Micronucleada == 1) { if (check == 0) //checa somente uma vez! { check = 1; CelulasMicronucleadas++; } CvInvoke.DrawContours(CameraResult, Nucleithresh, j, new MCvScalar(255, 128, 0)); CvInvoke.DrawContours(CameraResult, Nucleithresh, PosicaoOutroNucleo, new MCvScalar(255, 128, 0)); CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 128, 0)); } else if (Nucleos == 1 && Normal == 1) { VectorOfVectorOfPoint NucleithreshFinal = new VectorOfVectorOfPoint(); //VERIFICA A PRESENÇA DE OUTRO NUCLEO DENTRO DA CELULA! for (int k = PosicaoThresh; k > 95; k--) { VectorOfVectorOfPoint Nucleithresh2 = new VectorOfVectorOfPoint(); int AchouNucleo2 = 0; Mat NucleihierarchyThresh2 = new Mat(); Mat MorphStructuring = new Mat(); Mat MorphStructuring2 = new Mat(); Cellthresh = separateCell[0]; Cellthresh2 = separateCell[0]; MorphStructuring = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(5, 5), new Point(-1, -1)); MorphStructuring2 = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(9, 9), new Point(-1, -1)); CvInvoke.Threshold(Cellthresh, Cellthresh, PosicaoThresh, 255, ThresholdType.Binary); //MessageBox.Show(PosicaoThresh.ToString()); CvInvoke.Threshold(Cellthresh2, Cellthresh2, k, 255, ThresholdType.Binary); CvInvoke.MorphologyEx(Cellthresh, Cellthresh, MorphOp.Dilate, MorphStructuring2, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); CvInvoke.MorphologyEx(Cellthresh2, Cellthresh2, MorphOp.Dilate, MorphStructuring, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); CvInvoke.MorphologyEx(Cellthresh2, Cellthresh2, MorphOp.Erode, MorphStructuring, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); Cellthresh2 = Cellthresh2 - Cellthresh; CvInvoke.FindContours(Cellthresh2, Nucleithresh2, NucleihierarchyThresh2, RetrType.Tree, ChainApproxMethod.ChainApproxSimple); if (Nucleithresh2.Size > 0 && Nucleithresh2.Size < 10) { for (int z = 0; z < Nucleithresh2.Size; z++) { ContourCompare.SetZero(); MaskContourCell.SetZero(); MaskContourNuclei.SetZero(); double perimeter2 = CvInvoke.ArcLength(Nucleithresh2[z], true); double AreaNucleiThresh2 = CvInvoke.ContourArea(Nucleithresh2[z]); CvInvoke.DrawContours(MaskContourCell, contours, i, new MCvScalar(255, 255, 255)); CvInvoke.DrawContours(MaskContourNuclei, Nucleithresh2, z, new MCvScalar(255, 255, 255)); ContourCompare = MaskContourCell & MaskContourNuclei; int pixel2 = 0; for (int cols = 0; cols < ContourCompare.Cols; cols++) { for (int rows = 0; rows < ContourCompare.Rows; rows++) { pixel2 += ContourCompare.Data[rows, cols, 0]; } } if (AreaNucleiThresh2 < 50 && AreaNucleiThresh2 > 30 && pixel2 == 0 && AchouNucleo2 == 0 && perimeter2 < 27) { AchouNucleo2 = 1; PosicaoThresh2 = k; PosicaoNucleo2 = z; ThreshSet2 = Cellthresh; NucleithreshFinal = Nucleithresh2; AreaNucleo2 = AreaNucleiThresh2; break; } } } if (AchouNucleo2 == 1 && Math.Abs(AreaNucleo1 - AreaNucleo2) > 20) { Nucleos++; Micronucleada = 1; Normal = 0; break; } else if (AchouNucleo2 == 1 && Math.Abs(AreaNucleo1 - AreaNucleo2) < 20) { Nucleos++; Binucleada = 1; Normal = 0; break; } } if (Normal == 1) { if (check == 0) //checa somente uma vez! { check = 1; CelulasNormais++; } CvInvoke.DrawContours(CameraResult, Nucleithresh, j, new MCvScalar(0, 255, 0)); CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(0, 255, 0)); break; } else if (Binucleada == 1) { if (check == 0) //checa somente uma vez! { check = 1; CelulasBinucleadas++; } CvInvoke.DrawContours(CameraResult, Nucleithresh, PosicaoNucleo, new MCvScalar(255, 0, 0)); CvInvoke.DrawContours(CameraResult, NucleithreshFinal, PosicaoNucleo2, new MCvScalar(255, 0, 0)); CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 0, 0)); break; } else if (Micronucleada == 1) { if (check == 0) //checa somente uma vez! { check = 1; CelulasMicronucleadas++; } CvInvoke.DrawContours(CameraResult, Nucleithresh, PosicaoNucleo, new MCvScalar(255, 128, 0)); CvInvoke.DrawContours(CameraResult, NucleithreshFinal, PosicaoNucleo2, new MCvScalar(255, 128, 0)); CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 128, 0)); break; } } } } if (AchouNucleo == 0) //provavelmente a célula não possui núcleo -- cariólise { CvInvoke.DrawContours(CameraResult, contours, i, new MCvScalar(255, 0, 255)); CelulasCariolise++; } } } NomeImagemSaida = Path.GetFileName(Caminho); CelulasNormais2 = CelulasNormais; CelulasMicronucleadas2 = CelulasMicronucleadas; CelulasBinucleadas2 = CelulasBinucleadas; CelulasCariolise2 = CelulasCariolise; CelulasTotais2 = CelulasNormais2 + CelulasBinucleadas2 + CelulasCariolise2 + CelulasMicronucleadas2; return(CameraResult.ToBitmap()); }
private void watershedToolStripMenuItem_Click(object sender, EventArgs e) { // Segmentation - watershed if (ActiveMdiChild is ImageView) { Mat src = ((ImageView)ActiveMdiChild).Mat; Mat gray = new Mat(); Mat thresh = new Mat(); Mat kernel = new Mat(); Mat opening = new Mat(); Mat item_bg = new Mat(); Mat item_fg = new Mat(); Mat dist_transform = new Mat(); Mat unknown = new Mat(); Mat markers = new Mat(); Mat dst = src.Clone(); // Converting to Gray CvInvoke.CvtColor(src, gray, ColorConversion.Bgra2Gray); // Thresholding with Otsu CvInvoke.Threshold(gray, thresh, 0, 255, ThresholdType.BinaryInv | ThresholdType.Otsu); // Morphology operations kernel = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new Size(3, 3), new Point(-1, -1)); CvInvoke.MorphologyEx(thresh, opening, MorphOp.Open, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar(1, 0)); CvInvoke.Dilate(opening, item_bg, kernel, new Point(-1, -1), 4, BorderType.Default, new MCvScalar(1, 0)); // Distance transformation CvInvoke.DistanceTransform(opening, dist_transform, null, DistType.L2, 5); // Enhancing visibility CvInvoke.Threshold(dist_transform, item_fg, 0.5, 255, ThresholdType.Binary); CvInvoke.MorphologyEx(item_fg, item_fg, MorphOp.Erode, kernel, new Point(-1, -1), 10, BorderType.Default, new MCvScalar(1, 0)); item_fg.ConvertTo(item_fg, DepthType.Cv8U); // Subtraction foreground from background CvInvoke.Subtract(item_bg, item_fg, unknown); // Getting markers CvInvoke.ConnectedComponents(item_fg, markers); // Converting to appropriate types for watershed dst.ConvertTo(dst, DepthType.Cv8U); markers.ConvertTo(markers, DepthType.Cv32S); // Calling Watershed from cvInvoke CvInvoke.Watershed(dst, markers); // Converting dst to Image to perform subscription directly without pointers Image <Bgr, byte> outputImage = dst.ToImage <Bgr, byte>(false); // Draw distinct objects red for (int i = 0; i < markers.Rows; ++i) { for (int j = 0; j < markers.Cols; ++j) { outputImage.Data[i, j, 2] = 255; } } ((ImageView)ActiveMdiChild).setImage(outputImage.Mat); ((ImageView)ActiveMdiChild).Refresh(); } else { MessageBox.Show("Image shold be selected!", "Watershed Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); } }
public void ApplyWatershed() { var image = GetBitmap().ToImage <Bgr, byte>(); var bg = GetClone(); bg.GradeTrans(254); var msk = bg.GetClone(); msk.ApplyNegative(); bg.Erosion(3, 3); var bgImage = bg.GetBitmap().ToImage <Bgr, byte>().Convert <Gray, byte>(); bgImage.ToBitmap().Save("1-bgImage.jpg"); //Search for ~local minimums var localMinimums = GetClone(); localMinimums.MarkLocalMinimums(); localMinimums.Dilatation(3, 3); localMinimums.ApplyMask(msk); var minimums = localMinimums.GetBitmap().ToImage <Bgr, byte>().Convert <Gray, byte>(); minimums.ToBitmap().Save("2-minimums.jpg"); //Markers CvInvoke.ConnectedComponents(minimums, minimums); minimums.ToBitmap().Save("3-minimums.jpg"); var output = minimums.Convert <Gray, int>(); output.ToBitmap().Save("4-output.jpg"); var max = int.MinValue; for (var i = 0; i < image.Height; i++) { for (var j = 0; j < image.Width; j++) { max = Math.Max(output.Data[i, j, 0] + 1, max); } } for (var i = 0; i < image.Height; i++) { for (var j = 0; j < image.Width; j++) { if (bgImage.Data[i, j, 0] == 255) { output.Data[i, j, 0] = max; } } } output.ToBitmap().Save("5-output.jpg"); //Do watershed CvInvoke.Watershed(image, output); //Load image var newData = new List <PointPairList>(); var height = output.Data.GetLength(0); var width = output.Data.GetLength(1); for (var i = 0; i < height; i++) { var ppl = new PointPairList(); for (var j = 0; j < width; j++) { var color = output.Data[i, j, 0]; ppl.Add(0, (color == max || color == 0) ? -1 : output.Data[i, j, 0]); } newData.Add(ppl); } Data = newData; }