/// <summary> /// Metodo que obtiene las subimagenes a partir de los huecos. /// </summary> /// <param name="image">La imagen a segmentar.</param> /// <param name="holes"> /// Los huecos considerados para separar las partes de la imagen. /// </param> /// <returns>Un array con las subimagenes obtenidas al segmentar.</returns> private List <MathTextBitmap> ImageCut(MathTextBitmap image, List <Hole> holes) { List <MathTextBitmap> newBitmaps = new List <MathTextBitmap>(); int start, size; int xpos = image.Position.X; int ypos = image.Position.Y; for (int i = 0; i < holes.Count - 1; i++) { //El texto esta entre el final de un hueco, y el inicio del siguiente; start = ((Hole)holes[i]).EndPixel; size = ((Hole)holes[i + 1]).StartPixel - start + 1; int x0, y0; int width0, height0; if (mode == ProjectionMode.Horizontal) { x0 = start; y0 = 0; width0 = size; height0 = image.Height; } else { x0 = 0; y0 = start; width0 = image.Width; height0 = size; } // Recortamos FloatBitmap cutImage = image.FloatImage.SubImage(x0, y0, width0, height0); // Encuadramos Gdk.Point pd; Gdk.Size sd; GetEdges(cutImage, out pd, out sd); cutImage = cutImage.SubImage(pd.X, pd.Y, sd.Width, sd.Height); // Montamos el bitmap MathTextBitmap newBitmap = new MathTextBitmap(cutImage, new Point(xpos + x0 + pd.X, ypos + y0 + pd.Y)); newBitmaps.Add(newBitmap); } if (newBitmaps.Count == 1) { newBitmaps.Clear(); } return(newBitmaps); }
private List <MathTextBitmap> WaterfallSegment(MathTextBitmap bitmap) { FloatBitmap image = Rotate(bitmap.FloatImage); if (reflection) { image = Reflect(image); } // Buscamos un pixel blanco en el que empezar. List <Point> points = new List <Point>(); // Aqui vamos a pintar la linea que divide las dos partes de la imagen. FloatBitmap cutImage = new FloatBitmap(image.Width, image.Height); // Buscamos por filas, desde abajo, para encontrar el primer pixel // negro mas cercano a la esquina (0,0). int i, j, k; if (search) { bool startFound = false; for (j = 0; j < image.Height && !startFound; j++) { for (i = 0; i < image.Width && !startFound; i++) { if (image[i, j] != FloatBitmap.White) { for (k = 0; k < j; k++) { // Añadimos a la lista de puntos los puntos // entre el borde inferior y el punto en la fila // inmediatamente inferior a la del punto negro. points.Add(new Point(i, k)); cutImage[i, k] = FloatBitmap.Black; } startFound = true; } } } } else { points.Add(new Point(image.Width / 2, 0)); cutImage[image.Width / 2, 0] = FloatBitmap.Black; } if (points.Count == 0) { return(new List <MathTextBitmap>()); } int x = points[0].X; int y = points[0].Y; bool newPoints = true; bool borderFound = false; while (newPoints && !borderFound) { if (x == image.Width - 1 || y == image.Height - 1) { borderFound = true; } else { // Aqui almacenamos los posibles vectores.. int [] vectors = new int[] { 0, 1, 1, 1, 1, 0, -1, 0, -1, 1, -1, -1, 0, -1 }; bool notNewFound = true; for (k = 0; k < vectors.Length && notNewFound; k += 2) { int xd = vectors[k]; int yd = vectors[k + 1]; // Vamos comprobando los casos // Tenemos que: // · No salirnos de los limites // · El pixel ha de ser blanco. // . No puede ser el anterior del actual, para no meternos // en un bucle. if (x + xd >= 0 && y + yd >= 0 && x + xd < image.Width && y + yd < image.Height && image[x + xd, y + yd] == FloatBitmap.White && !points.Contains(new Point(x + xd, y + yd))) { x = x + xd; y = y + yd; points.Add(new Point(x, y)); cutImage[x, y] = FloatBitmap.Black; // Indicamos que hemos encontrado el valor. notNewFound = false; } } newPoints = !notNewFound; } } List <MathTextBitmap> children = new List <MathTextBitmap>(); // Hemos encontrado el borde, cortamos la imagen. if (borderFound) { // Primero encontramos un punto blanco. bool whiteFound = false; int x0 = 0, y0 = 0; for (i = 0; i < cutImage.Width && !whiteFound; i++) { for (j = 0; j < cutImage.Height && !whiteFound; j++) { if (cutImage[i, j] != FloatBitmap.Black) { // Mas que el primer blaco, buscamos el primer // negro; whiteFound = true; x0 = i; y0 = j; } } } if (reflection) { cutImage = Reflect(cutImage); } // Tenemos que rotar la imagen de corte para alinearla con la orginal. cutImage = UndoRotate(cutImage); // Rellenamos la imagen de negro a partir del punto encontrado. cutImage.Fill(x0, y0, FloatBitmap.Black); #if DEBUG string path = System.IO.Path.GetTempFileName(); cutImage.CreatePixbuf().Save(String.Format(path + "_{0}_{1}.png", mode, reflection), "png"); #endif // Recorremos la imagen de corte, y sacamos dos imagenes; FloatBitmap res1 = new FloatBitmap(cutImage.Width, cutImage.Height); FloatBitmap res2 = new FloatBitmap(cutImage.Width, cutImage.Height); FloatBitmap origImage = bitmap.FloatImage; bool res1HasBlack = false; bool res2HasBlack = false; for (i = 0; i < cutImage.Width; i++) { for (j = 0; j < cutImage.Height; j++) { // Si estamos en la zona negra de la imagen de corte, // copiamos en la primera imagen de resultado, // y sino, en la segunda. if (cutImage[i, j] == FloatBitmap.Black) { res1[i, j] = origImage[i, j]; if (origImage[i, j] != FloatBitmap.White) { res1HasBlack = true; } } else { res2[i, j] = origImage[i, j]; if (origImage[i, j] != FloatBitmap.White) { res2HasBlack = true; } } } } // Si las dos imágenes tienen pixeles negros, hemos separado la // imagen correctamente, sino, solo hemos rodeado algo // que no fuimos capaces de segmentar. // Si no, no segmenatamos nada, se devolverá la lista vacia. if (res1HasBlack && res2HasBlack) { Gdk.Point pd; Gdk.Size sd; GetEdges(res1, out pd, out sd); res1 = res1.SubImage(pd.X, pd.Y, sd.Width, sd.Height); children.Add(new MathTextBitmap(res1, new Gdk.Point(bitmap.Position.X + pd.X, bitmap.Position.Y + pd.Y))); GetEdges(res2, out pd, out sd); res2 = res2.SubImage(pd.X, pd.Y, sd.Width, sd.Height); children.Add(new MathTextBitmap(res2, new Gdk.Point(bitmap.Position.X + pd.X, bitmap.Position.Y + pd.Y))); } } return(children); }