/// <summary> /// ラベリング /// </summary> /// <param name="sender"></param> /// <param name="e"></param> /// <example> /// http://schima.hatenablog.com/entry/2015/08/19/215523 /// </example> private void btnLabelling_Click(object sender, EventArgs e) { //画像準備 Mat matSrcLabelling = BitmapConverter.ToMat((Bitmap)picBoxDst.Image); Mat matGrayLabelling = matSrcLabelling.CvtColor(ColorConversionCodes.BGR2GRAY); Mat matBinary = matGrayLabelling.Threshold(0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary); //ラベリング実行 Mat matLabel = new Mat(); int nLabels = Cv2.ConnectedComponents(matBinary, matLabel, PixelConnectivity.Connectivity8, MatType.CV_32SC1); //色分け画像作成 Scalar[] colors = Enumerable.Range(0, nLabels + 1).Select(_ => Scalar.RandomColor()).ToArray(); colors[0] = Scalar.Black; int rows = matBinary.Rows; int cols = matBinary.Cols; var dst = new Mat(rows, cols, MatType.CV_8UC3); var labelIndexer = matLabel.GetGenericIndexer <int>(); var dstIndexer = dst.GetGenericIndexer <Vec3b>(); for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) { int labelValue = labelIndexer[y, x]; dstIndexer[y, x] = colors[labelValue].ToVec3b(); } } //描画 picBoxDst.Image = BitmapConverter.ToBitmap(dst); }
public static void CalculoMatrizBinariaYRelleno(Mat imagen, out Mat imagenBinaria, out Mat imagenAberturaRelleno) { imagenBinaria = new Mat(); imagenAberturaRelleno = new Mat(); imagenBinaria = 255 - imagen; Mat imagenBinariaProc = new Mat(); imagenBinaria.CopyTo(imagenBinariaProc); Mat kernelMorfologicoElipse = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3)); Mat kernelMorfologicoCruz = Cv2.GetStructuringElement(MorphShapes.Cross, new Size(3, 3)); Cv2.Erode(imagenBinariaProc, imagenBinariaProc, kernelMorfologicoElipse, iterations: 3); Cv2.Dilate(imagenBinariaProc, imagenBinariaProc, kernelMorfologicoCruz, iterations: 2); imagenBinariaProc = 255 - imagenBinariaProc; Mat imagenTransfDistancia = new Mat(); Mat imagenTransfDistanciaBinaria = new Mat(); Cv2.DistanceTransform(imagenBinariaProc, imagenTransfDistancia, DistanceTypes.C, DistanceMaskSize.Mask5); imagenTransfDistancia.ConvertTo(imagenTransfDistancia, MatType.CV_8U); imagenTransfDistancia.CopyTo(imagenTransfDistanciaBinaria); double maxDist, minDist, rangoDist; imagenTransfDistanciaBinaria.MinMaxIdx(out minDist, out maxDist); rangoDist = maxDist - minDist; var indexadorImgDistancia = imagenTransfDistanciaBinaria.GetGenericIndexer <byte>(); for (int i = 0; i < imagenTransfDistancia.Rows; i++) { for (int j = 0; j < imagenTransfDistancia.Cols; j++) { if (indexadorImgDistancia[i, j] >= maxDist - rangoDist * 0.35 || indexadorImgDistancia[i, j] <= minDist + rangoDist * 0.15) { indexadorImgDistancia[i, j] = (byte)255; } else { indexadorImgDistancia[i, j] = (byte)0; } } } Mat marcadores = new Mat(); int numMarcadores = Cv2.ConnectedComponents(imagenTransfDistanciaBinaria, marcadores, PixelConnectivity.Connectivity8, MatType.CV_16UC1); Dictionary <int, int> cantidadMarcador = new Dictionary <int, int>(); for (int i = 0; i < marcadores.Rows; i++) { for (int j = 0; j < marcadores.Cols; j++) { int areaMarcador = 0; int m = marcadores.At <int>(i, j); cantidadMarcador.TryGetValue(m, out areaMarcador); if (areaMarcador > 0) { cantidadMarcador[m] += 1; } else { cantidadMarcador[m] = 1; } //try //{ // cantidadMarcador[m] += 1; //} //catch //{ // cantidadMarcador[m] = 1; //} } } int indiceMarcadorMax = cantidadMarcador.Select(v => new Tuple <int, int>(v.Key, v.Value)) .OrderByDescending(x => x.Item1).First().Item2; Mat fondoMarcadores = new Mat(); marcadores.CopyTo(fondoMarcadores); var indexador = fondoMarcadores.GetGenericIndexer <int>(); for (int i = 0; i < fondoMarcadores.Rows; i++) { for (int j = 0; j < fondoMarcadores.Cols; j++) { indexador[i, j] = (indexador[i, j] == indiceMarcadorMax) ? 255 : 0; } } fondoMarcadores.ConvertTo(fondoMarcadores, imagenBinaria.Type()); Mat imagenBinariaSinFondo = new Mat(); Mat imagenRellenoHuecos = new Mat(); Cv2.Subtract(imagenBinaria, fondoMarcadores, imagenBinariaSinFondo); Cv2.Add(imagenBinaria, imagenBinariaSinFondo, imagenRellenoHuecos); Mat kernelMorfologicoApertura = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)); Cv2.MorphologyEx(imagenRellenoHuecos, imagenAberturaRelleno, MorphTypes.Open, kernelMorfologicoApertura, iterations: 2); /* liberar memoria */ imagenBinariaProc.Release(); imagenBinariaSinFondo.Release(); imagenRellenoHuecos.Release(); kernelMorfologicoElipse.Release(); kernelMorfologicoCruz.Release(); kernelMorfologicoApertura.Release(); }
static void Main(string[] args) { //Thread capturaVideoThread = new Thread(new ThreadStart(Program.CapturarVideo)); //capturaVideoThread.Start(); VideoCapture captura = new VideoCapture("D:\\Dictuc\\out1.avi"); VideoWriter salida = new VideoWriter("D:\\Dictuc\\outSegmentado.avi", FourCC.XVID, 10.0, new Size(captura.FrameWidth, captura.FrameHeight), true); Mat imagenProcesada = new Mat(); int numImg = 0; while (true) { //captura.Read(imagen); imagen = Cv2.ImRead("D:\\uvas2.jpg"); mutex.WaitOne(); imagen.CopyTo(imagenProcesada); mutex.ReleaseMutex(); Mat imagenRuidoFiltrado = FiltradoRuido(imagenProcesada); Mat imagenGrisContraste = EscalaGrisesEqualizada(imagenRuidoFiltrado); Mat imagenGrisFrecAltasProc = FrecuenciasAltasPotenciadasContraste(imagenGrisContraste); EdgeDetector edgeDetector = new EdgeDetector() { Threshold = (byte)18, SparseDistance = 3, WeightPreviousPoint = (float)2.0, WeightCurrentPoint = (float)1.0, WeightAfterPoint = (float)2.0, }; EdgeDetector edgeDetector2 = new EdgeDetector() { Threshold = (byte)20, SparseDistance = 5, WeightPreviousPoint = (float)0.5, WeightCurrentPoint = (float)1.0, WeightAfterPoint = (float)0.5, }; Mat imagenBordes = edgeDetector.EdgeImage(imagenGrisContraste); Mat imagenBordes2 = edgeDetector2.EdgeImage(imagenGrisContraste); Mat imagenBinaria, imagenAberturaRelleno; CalculoMatrizBinariaYRelleno(imagenBordes2, out imagenBinaria, out imagenAberturaRelleno); Mat mascaraInv = 255 - imagenAberturaRelleno; Mat DistSureFg = new Mat(); Mat AreasSureFg = new Mat(); Mat Unknown = new Mat(); AreasSureFg += 1; Cv2.DistanceTransform(imagenAberturaRelleno, DistSureFg, DistanceTypes.L1, DistanceMaskSize.Mask5); int numAreas = Cv2.ConnectedComponents(imagenAberturaRelleno, AreasSureFg, PixelConnectivity.Connectivity8); float[,] distValues = new float[DistSureFg.Rows, DistSureFg.Cols]; for (int i = 0; i < DistSureFg.Rows; i++) { for (int j = 0; j < DistSureFg.Cols; j++) { distValues[i, j] = DistSureFg.At <float>(i, j); } } Segment[] segments = new Segment[numAreas]; for (int i = 0; i < AreasSureFg.Rows; i++) { for (int j = 0; j < AreasSureFg.Cols; j++) { int m = AreasSureFg.At <Int32>(i, j); byte pixelSurrounding = 0; float distance = (float)0; //if (i >= 1) //{ // distance = distValues[i - 1, j]; // if (distance == 2) // { // pixelSurrounding |= Segment.PIXEL_SURROUNDED_LEFT; // } //} //if (i < AreasSureFg.Rows - 1) //{ // distance = distValues[i + 1, j]; // if (distance == 2) // { // pixelSurrounding |= Segment.PIXEL_SURROUNDED_RIGHT; // } //} //if (j >= 1) //{ // distance = distValues[i, j - 1]; // if (distance == 2) // { // pixelSurrounding |= Segment.PIXEL_SURROUNDED_DOWN; // } //} //if (j < AreasSureFg.Cols - 1) //{ // distance = distValues[i, j + 1]; // if (distance == 2) // { // pixelSurrounding |= Segment.PIXEL_SURROUNDED_UP; // } //} SegmentPixelData newPixel = new SegmentPixelData() { Distance = distValues[i, j], CoordsXY = new int[] { i, j }, Concave = 0, Indexes = new int[] { -1, -1 }, PixelsSurrounding = pixelSurrounding, SubsegmentLabel = 0, }; if (segments[m] == null) { segments[m] = new Segment() { SegmentId = m, PixelData = new List <SegmentPixelData>(), }; } else { segments[m].MaxDistance = (segments[m].MaxDistance > newPixel.Distance) ? (int)segments[m].MaxDistance : (int)newPixel.Distance; segments[m].PixelData.Add(newPixel); } } } Mat Centroides = new Mat(); imagenAberturaRelleno.CopyTo(Centroides); var indexadorCentroides = Centroides.GetGenericIndexer <byte>(); var indexadorFiguras = AreasSureFg.GetGenericIndexer <Int32>(); foreach (var s in segments.Where(s => s.Circularity <= 0.9)) { int distancia = 0; if (s.Circularity > 0.7) { distancia = 5; } else if (s.Circularity > 0.5) { distancia = 5; } else if (s.Circularity > 0.25) { distancia = 6; } else { distancia = 6; } distancia = (distancia < s.MaxDistance) ? distancia : s.MaxDistance - 1; foreach (var p in s.PixelData.Where(p => p.Distance <= distancia)) { if (imagenAberturaRelleno.At <byte>(p.CoordsXY[0], p.CoordsXY[1]) != (byte)0) { indexadorCentroides[p.CoordsXY[0], p.CoordsXY[1]] = 0; } } } Cv2.Subtract(imagenAberturaRelleno + 255, Centroides, Unknown); #region segmentStuff //List<int> indexConcavos = segments.Where(s => s.Circularity > 1).Select(s => s.SegmentId).ToList(); //foreach (var s in segments.Where(s => s.Circularity < 1.1 && s.Circularity > 0.9)) //{ // foreach (var p in s.PixelData/*.Where(p => p.Distance == 1)*/) // { // if (imagenAberturaRelleno.At<byte>(p.CoordsXY[0], p.CoordsXY[1]) != (byte)0) // { // indexadorFiguras[p.CoordsXY[0], p.CoordsXY[1]] = 255; // } // } //} //foreach (var s in segments.Where(s => s.Circularity >= 1.1)) //{ // foreach (var p in s.PixelData/*.Where(p => p.Distance == 1)*/) // { // if (imagenAberturaRelleno.At<byte>(p.CoordsXY[0], p.CoordsXY[1]) != (byte)0) // { // indexadorFiguras[p.CoordsXY[0], p.CoordsXY[1]] = 255; // } // } //} //foreach (var s in segments) //{ // s.SetPixelConcavity(); // s.Segmentation(); // foreach (var p in s.PixelData.Where(p => p.Distance == 1)) // { // if (p.Concave == 1) // { // indexadorFiguras[p.CoordsXY[0], p.CoordsXY[1]] = 255; // } // if (p.Concave == -1) // { // indexadorFiguras[p.CoordsXY[0], p.CoordsXY[1]] = 255; // } // } //} //foreach (var s in segments) //{ // //s.SetPixelConcavity(); // //s.Segmentation(); // foreach (var p in s.PixelData.Where(p => p.Distance == 2)) // { // indexadorFiguras[p.CoordsXY[0], p.CoordsXY[1]] = 230; // } //} //imagenAberturaRelleno.CopyTo(SureFg); #endregion Mat colormap = new Mat(); Mat Marcadores = new Mat(); Cv2.ConnectedComponents(Centroides, Marcadores); Marcadores = Marcadores + 1; var indexador2 = Marcadores.GetGenericIndexer <Int32>(); for (int i = 0; i < Unknown.Rows; i++) { for (int j = 0; j < Unknown.Cols; j++) { if (Unknown.At <byte>(i, j) == 255) { indexador2[i, j] = 0; } } } Marcadores.CopyTo(colormap); colormap.ConvertTo(colormap, MatType.CV_8UC3); Cv2.ApplyColorMap(colormap, colormap, ColormapTypes.Rainbow); Cv2.ImWrite("D:\\Dictuc\\marcadores.png", Marcadores); //Mat img1 = new Mat(); //imagen.CopyTo(img1); Mat DistColor = new Mat(); //imagenGrisContraste = 255 - imagenGrisContraste; Cv2.CvtColor(imagenAberturaRelleno, DistColor, ColorConversionCodes.GRAY2BGR); DistColor.ConvertTo(DistColor, MatType.CV_8U); Cv2.Watershed(DistColor, Marcadores); Cv2.ImWrite("D:\\Dictuc\\watersheedIn.png", DistColor); var indexador4 = imagen.GetGenericIndexer <Vec3i>(); //for (int i = 0; i < imagen.Rows; i++) //{ // for (int j = 0; j < imagen.Cols; j++) // { // //if (Centroides.At<byte>(i, j) > 0) // // indexador4[i, j] = new Vec3i(0, 0, 255); // if (Marcadores.At<Int32>(i, j) == -1) // indexador4[i, j] = new Vec3i(255, 20, 20); // } //} for (int i = 0; i < imagen.Rows; i++) { for (int j = 0; j < imagen.Cols; j++) { //if (Centroides.At<byte>(i, j) > 0) // indexador4[i, j] = new Vec3i(0, 0, 255); if (imagenBordes.At <char>(i, j) > 0) { indexador4[i, j] = new Vec3i(255, 20, 20); } } } Mat seg = new Mat(); Marcadores.CopyTo(seg); var indexador5 = seg.GetGenericIndexer <int>(); for (int i = 0; i < Marcadores.Rows; i++) { for (int j = 0; j < Marcadores.Cols; j++) { indexador5[i, j] = (Math.Abs(indexador5[i, j]) > 1) ? 255 : 0; } } Mat kE1 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(1, 1)); Cv2.Erode(seg, seg, kE1, iterations: 3); int thrs1 = 1500; int thrs2 = 1800; Mat edge1 = new Mat(); seg.ConvertTo(seg, MatType.CV_8U); Cv2.Canny(seg, edge1, thrs1, thrs2, apertureSize: 5); SimpleBlobDetector.Params params1 = new SimpleBlobDetector.Params() { MinThreshold = 0, MaxThreshold = 255, FilterByArea = true, MinArea = 15, FilterByCircularity = false, MinCircularity = (float)0.01, FilterByConvexity = false, MinConvexity = (float)0.1, FilterByInertia = false, MinInertiaRatio = (float)0.01, }; SimpleBlobDetector detectorBlobs = SimpleBlobDetector.Create(params1); KeyPoint[] segmentosBlob = detectorBlobs.Detect(edge1); Mat segmentosBlobMat = new Mat(1, segmentosBlob.Count(), MatType.CV_32FC1); var indexador6 = segmentosBlobMat.GetGenericIndexer <float>(); for (int i = 0; i < segmentosBlob.Count(); i++) { indexador6[0, i] = segmentosBlob[i].Size; } Mat hist = new Mat(); Rangef[] ranges = { new Rangef(0, (float)segmentosBlob.Max(x => x.Size)) }; Cv2.CalcHist(new Mat[] { segmentosBlobMat }, new int[] { 0 }, null, hist, 1, new int[] { 100 }, ranges, uniform: true, accumulate: true); float[] histAcumulado = new float[hist.Rows]; float[] histAcumuladoPorcentaje = new float[11]; histAcumulado[0] = hist.At <float>(0, 0); for (int i = 1; i < hist.Rows; i++) { histAcumulado[i] = hist.At <float>(i, 0) + histAcumulado[i - 1]; } int k = 1; for (int i = 1; i < histAcumuladoPorcentaje.Count(); i++) { for (; k < hist.Rows; k++) { float porcentajeActual = histAcumulado[k] / segmentosBlob.Count() * 100; float porcentajeAnterior = histAcumulado[k - 1] / segmentosBlob.Count() * 100; float porcentajeRequerido = (float)((i < 10) ? i * 10 : 99.3); if (porcentajeRequerido <= porcentajeActual) { float tamañoPorcentajeActual = (float)(k * (float)segmentosBlob.Max(x => x.Size) / 100.0); float tamañoPorcentajeAnterior = (float)((k - 1) * (float)segmentosBlob.Max(x => x.Size) / 100.0); float tasaVariacionTamañoPorcentaje = (tamañoPorcentajeActual - tamañoPorcentajeAnterior) / (porcentajeActual - porcentajeAnterior); histAcumuladoPorcentaje[i] = tamañoPorcentajeAnterior + tasaVariacionTamañoPorcentaje * (i * 10 - porcentajeAnterior); break; } } } for (int i = 0; i < histAcumuladoPorcentaje.Count(); i++) { Console.Write(histAcumuladoPorcentaje[i] + ","); } Console.WriteLine(""); // data1 = []; // for i in range(0, len(keypoints1)): // data1.append(keypoints1[i].size * coefTamano) // #tamano.write(str(i)+'\t'+str(keypoints1[i].size*2*0.3)+'\n') // cv2.line(im_with_keypoints1, (int(float(keypoints1[i].pt[0] - keypoints1[i].size)), int(float(keypoints1[i].pt[1]))), (int(float(keypoints1[i].pt[0] + keypoints1[i].size)), int(float(keypoints1[i].pt[1]))), (255, 0, 0), 1) // cv2.line(im_with_keypoints1, (int(float(keypoints1[i].pt[0])), int(float(keypoints1[i].pt[1] - keypoints1[i].size))), (int(float(keypoints1[i].pt[0])), int(float(keypoints1[i].pt[1] + keypoints1[i].size))), (255, 0, 0), 1) //# print(data1) //n1, bins1, patches1 = hist(data1, 200,[0, max(data1)], normed = 100, cumulative = True, bottom = True, histtype = 'stepfilled', align = 'mid', orientation = 'vertical', rwidth = 1, log = False, color = "r") // tamano = open(temp + "instancia_" + instancia + ".txt", "w") // x = np.array(bins1) // y = np.append([0], n1) // xnew = [x[1], x[21], x[36], x[45], x[53], x[60], x[69], x[78], x[88], x[97], x[200]] //ynew = [y[1], y[21], y[36], y[45], y[53], y[60], y[69], y[78], y[88], y[97], y[200]] //tamano.write('INSERT INTO [dbo].[Granulometria](Cod_Instancia,Fecha,P_10,P_20,P_30,P_40,P_50,P_60,P_70,P_80,P_90,P_100, Filename) values (') //tamano.write(instancia + ",CONVERT(datetime, '" + sys.argv[1][0:4] + "-" + sys.argv[1][4:6] + "-" + sys.argv[1][6:8] + ' ' + sys.argv[1][9:11] + ':' + sys.argv[1][11:13] + ':' + sys.argv[1][13:15] + "', 120)") //for j in range(1, len(xnew)): // #tamano.write (str(j)+'\t'+str(round(xnew[j],1))+'\t'+str(round(ynew[j]*100,2))+'\n') // tamano.write(',' + str(round(xnew[j], 1))) //tamano.write(",'" + sys.argv[1] + " - Resultado.jpg'") //tamano.write(')') //CvXImgProc.Thinning(mascaraInv, mascaraInv, ThinningTypes.ZHANGSUEN); Mat imWithKeypoints1 = new Mat(); Cv2.DrawKeypoints(imagen, segmentosBlob, imWithKeypoints1, new Scalar(0, 0, 255), DrawMatchesFlags.DrawRichKeypoints); var dataTamaños = segmentosBlob.Select(s => s.Size).ToArray(); Cv2.ImWrite("D:\\Dictuc\\output0" + numImg + ".png", imagen); Cv2.ImWrite("D:\\Dictuc\\output1" + numImg++ + ".png", imWithKeypoints1); Cv2.ImShow("Segmentado", imagen); Cv2.ImShow("GrisContraste", imagenGrisContraste); Cv2.ImShow("bordes90", imagenBordes); Cv2.ImShow("bordes50", imagenBordes2); salida.Write(imagen); //System.Threading.Thread.Sleep(10); Cv2.WaitKey(10); imagenRuidoFiltrado.Release(); imagenGrisContraste.Release(); imagenGrisFrecAltasProc.Release(); imagenBordes.Release(); imagenBinaria.Release(); imagenAberturaRelleno.Release(); } }