internal String CreateNewCurves() { TaggedUndirectedEdge <Pixel, EdgeTag> firstEdge; TaggedUndirectedEdge <Pixel, EdgeTag> lastEdge; Pixel lastPoint = null; Pixel firstPoint; bool hasEdge; foreach (var edge in ng.Edges) { firstPoint = null; //localiza uma aresta visivel e que seja de valencia diferente de 2, ou seja o inicio de uma curva. if (edge.Tag.Visible && (edge.Source.valence != 2 || edge.Target.valence != 2)) { //cria um array de pontos para esta curva ArrayList curveOfEdges = new ArrayList(); //ir para inicio da curva, ou seja nodo com valencia != 2 firstEdge = edge; if (firstEdge.Source.valence != 2 && firstEdge.Target.valence != 2)// curva de apenas dois pontos { edge.Tag.Visible = false; firstPoint = null; curveOfEdges.Add(firstEdge); curvesOfEdges.Add(curveOfEdges); if (edge.Tag.ColorA != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorA)); } if (edge.Tag.ColorB != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorB)); } } else { edge.Tag.Visible = false; curveOfEdges.Add(firstEdge); if (firstEdge.Target.valence != 2) { firstPoint = firstEdge.Target; lastPoint = firstEdge.Source; } else { firstPoint = firstEdge.Source; lastPoint = firstEdge.Target; } } if (firstPoint == null) { hasEdge = false; } else { hasEdge = true; } lastEdge = firstEdge; while (hasEdge)//enquanto existirem mais arestas nesta curva adiciona elas { hasEdge = false; //Obtem proxima aresta foreach (var e in ng.AdjacentEdges(lastPoint)) { if (e.Tag.Visible == true) { e.Tag.Visible = false; if (e.Target.Equals(lastPoint)) { lastPoint = e.Source; } else { lastPoint = e.Target; } //Se a valencia for dois a curva continua if (lastPoint.valence == 2 && lastPoint != firstPoint) { curveOfEdges.Add(e); hasEdge = true; } else { hasEdge = false; curveOfEdges.Add(e); curvesOfEdges.Add(curveOfEdges); if (edge.Tag.ColorA != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorA)); } if (edge.Tag.ColorB != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorB)); } } } } } } } //Percorre as arestas que ficaram de fora por formarem um caminho fechado de arestas, todas com valencia 2 foreach (var edge in ng.Edges) { ArrayList curveOfEdges = new ArrayList(); if (edge.Tag.Visible) { firstEdge = edge; edge.Tag.Visible = false; curveOfEdges.Add(firstEdge); firstPoint = firstEdge.Source; hasEdge = true; lastPoint = firstEdge.Target; while (hasEdge) { hasEdge = false; //Obtem proxima aresta foreach (var e in ng.AdjacentEdges(lastPoint)) { if (e.Tag.Visible == true) { e.Tag.Visible = false; if (e.Target.Equals(lastPoint)) { lastPoint = e.Source; } else { lastPoint = e.Target; } if (lastPoint.valence == 2 && lastPoint != firstPoint) { hasEdge = true; curveOfEdges.Add(e); } else { hasEdge = false; curveOfEdges.Add(e); curvesOfEdges.Add(curveOfEdges); if (edge.Tag.ColorA != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorA)); } if (edge.Tag.ColorB != Color.Beige) { curvesC.Add(new Curve(curveOfEdges, edge.Tag.ColorB)); } } } } } } } SvgVector svg = new SvgVector { Height = Height * scale, Width = Width * scale, scale = 1//scale; }; return(svg.ToCurves(CurvesOfEdgesToPoints(curvesOfEdges), "NewCurves.svg")); }
/* * Altera o formato do pixel com base nos visinhos */ public String ReshapePixelCell() { foreach (var v in g.Vertices) { int x = v.x; int y = v.y; Color c = v.color; // foreach (var e in g.AdjacentEdges(v)) // Console.WriteLine("Aresta entre " + e.Source.x + "," + e.Source.y + " - " + e.Target.x + "," + e.Target.y); //TOP LEFT //Canto Superior Esquerdo /* * if tem tl * -2 +2 +2 -2 * if o de cima tem bl +2 +2 * senao * 0 0 */ //Firt Pixel fp - Last Pixel Lp Pixel fP = null, p1 = null, p2 = null, p3 = null, p4 = null, lP = null, xP = null; if (HasEdges(x, y, x - 1, y - 1, g)) //existe uma aresta entre este pixel e o pixel superior esquerdo { v.points.Add(new Point(x * scale - 2, y * scale + 2)); v.points.Add(new Point(x * scale + 2, y * scale - 2)); fP = GetOrAddVertex(x * scale - 2, y * scale + 2, ng); p1 = GetOrAddVertex(x * scale + 2, y * scale - 2, ng); AddNewEdge(fP, p1, PixelColorIs(x - 1, y - 1, g), c, ng); // se o pixel de superior esquerdo é da mesma cor ele não precisa aparecer } else if (HasEdges(x - 1, y, x, y - 1, g)) //verifica se existe uma aresta entre o pixel superior e o da esquerda { v.points.Add(new Point(x * scale + 2, y * scale + 2)); fP = GetOrAddVertex(x * scale + 2, y * scale + 2, ng); } else { v.points.Add(new Point(x * scale, y * scale)); fP = GetOrAddVertex(x * scale, y * scale, ng); } if (p1 != null) { lP = p1; } else { lP = fP; } //TOP RIGHT /* * if tem tr +5 -2 +9 +2 * if o de cima tem br +5 +2 * senao +7 +0 */ if (HasEdges(x, y, x + 1, y - 1, g)) //existe uma aresta entre este pixel e o pixel superior direito { v.points.Add(new Point(x * scale + 5, y * scale - 2)); v.points.Add(new Point(x * scale + 9, y * scale + 2)); p2 = GetOrAddVertex(x * scale + 5, y * scale - 2, ng); xP = GetOrAddVertex(x * scale + 9, y * scale + 2, ng); AddNewEdge(p2, xP, PixelColorIs(x + 1, y - 1, g), c, ng); //se o pixel superior direito é da mesma cor ele não precisa aparecer } else if (HasEdges(x + 1, y, v.x, y - 1, g)) //verifica se existe uma aresta entre o pixel superior e o da direita { v.points.Add(new Point(x * scale + 5, y * scale + 2)); p2 = GetOrAddVertex(x * scale + 5, y * scale + 2, ng); } else { v.points.Add(new Point(x * scale + 7, y * scale)); p2 = GetOrAddVertex(x * scale + 7, y * scale, ng); } if (lP != null && p2 != null) { AddNewEdge(lP, p2, PixelColorIs(x, y - 1, g), c, ng); } if (xP != null) { lP = xP; } else { lP = p2; } xP = null; //botton righ /* * if tem br +9 +5 +5 +9 * if o de cima tem tr +5 +5 * senao +7 +7 */ if (HasEdges(x + 1, y + 1, x, y, g)) //existe uma aresta entre este pixel e o pixel inferior direito { v.points.Add(new Point(x * scale + 9, y * scale + 5)); v.points.Add(new Point(x * scale + 5, y * scale + 9)); p3 = GetOrAddVertex(x * scale + 9, y * scale + 5, ng); xP = GetOrAddVertex(x * scale + 5, y * scale + 9, ng); AddNewEdge(p3, xP, PixelColorIs(x + 1, y + 1, g), c, ng); //Se o pixel de baixo é da mesma cor esta aresta não precisa aparecer } else if (HasEdges(v.x, y + 1, x + 1, v.y, g)) //verifica se existe uma aresta entre o pixel inferior e o da direita { v.points.Add(new Point(x * scale + 5, y * scale + 5)); p3 = GetOrAddVertex(x * scale + 5, y * scale + 5, ng); } else { v.points.Add(new Point(x * scale + 7, y * scale + 7)); p3 = GetOrAddVertex(x * scale + 7, y * scale + 7, ng); } if (lP != null && p3 != null) { AddNewEdge(lP, p3, PixelColorIs(x + 1, y, g), c, ng); } if (xP != null) { lP = xP; } else { lP = p3; } xP = null; //BOTTON LEFT /* * if tem bl +2 +9 * -2 +5 * if o de cima tem tl +2 +5 * senao +0 +7 */ if (HasEdges(x - 1, y + 1, x, y, g)) //existe uma aresta entre este pixel e o pixel inferior esquerdo { v.points.Add(new Point(x * scale + 2, y * scale + 9)); v.points.Add(new Point(x * scale - 2, y * scale + 5)); p4 = GetOrAddVertex(x * scale + 2, y * scale + 9, ng); xP = GetOrAddVertex(x * scale - 2, y * scale + 5, ng); AddNewEdge(p4, xP, PixelColorIs(x - 1, y + 1, g), c, ng); //se o pixel inferior esquerdo for da mesma cor ele não precisa aparecer } else if (HasEdges(x, y + 1, x - 1, y, g)) //verifica se existe uma aresta entre o pixel inferior e o da esquerda { v.points.Add(new Point(x * scale + 2, y * scale + 5)); p4 = GetOrAddVertex(x * scale + 2, y * scale + 5, ng); } else { v.points.Add(new Point(x * scale + 0, y * scale + 7)); p4 = GetOrAddVertex(x * scale + 0, y * scale + 7, ng); } if (lP != null && p4 != null) { AddNewEdge(lP, p4, PixelColorIs(x, y + 1, g), c, ng); } if (xP != null) { lP = xP; } else { lP = p4; } xP = null; if (lP != null && fP != null) { AddNewEdge(lP, fP, PixelColorIs(x - 1, y, g), c, ng); } } SvgVector svg = new SvgVector { Height = Height, Width = Width, scale = scale, DrawNewCells = true, DrawCellBorder = true, DrawPixelArt = false, DrawVertex = false, DrawEdges = false }; return(svg.ToImageSVG(g, "PixelReshaped.svg")); }
/* * p11 p12 p13 * p21 p p23 * p31 p32 p33 */ internal String ImageToGraph(Bitmap b) { // FastBitmap fb = new FastBitmap(b); Bitmap fb = b; Height = b.Height; Width = b.Width; //Le imagem orignal e adiciona vertex - nodos for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { Pixel p = new Pixel(x, y, fb.GetPixel(x, y)); g.AddVertex(p); } } //Le imagem orignal e adiciona edges - arestas for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { Pixel p = VertexSearch(x, y, g); Pixel p11 = VertexSearch(x - 1, y - 1, g); if (p11 != null && Pixel.colorIsSimilar(p11.color, p.color)) { var e1 = new TaggedUndirectedEdge <Pixel, EdgeTag>(p, p11, new EdgeTag()); g.AddEdge(e1); p.valence++; p11.valence++; } Pixel p12 = VertexSearch(x, y - 1, g); if (p12 != null && Pixel.colorIsSimilar(p12.color, p.color)) { var e2 = new TaggedUndirectedEdge <Pixel, EdgeTag>(p, p12, new EdgeTag()); g.AddEdge(e2); p.valence++; p12.valence++; } Pixel p13 = VertexSearch(x + 1, y - 1, g); if (p13 != null && Pixel.colorIsSimilar(p13.color, p.color)) { if (p <= p13) { var e3 = new TaggedUndirectedEdge <Pixel, EdgeTag>(p, p13, new EdgeTag()); g.AddEdge(e3); } else { var e3 = new TaggedUndirectedEdge <Pixel, EdgeTag>(p13, p, new EdgeTag()); g.AddEdge(e3); } p.valence++; p13.valence++; } Pixel p21 = VertexSearch(x - 1, y, g); if (p21 != null && Pixel.colorIsSimilar(p21.color, p.color)) { var e4 = new TaggedUndirectedEdge <Pixel, EdgeTag>(p, p21, new EdgeTag()); g.AddEdge(e4); p.valence++; p21.valence++; } } } SvgVector svg = new SvgVector { Height = Height, Width = Width }; return(svg.ToImageSVG(g, "Graph.svg")); }
/* * Examinar blocos de 2x2 nodos para eliminar a maior quantidade de arestas, e remover cruzamentos ambiguos * 00 10 * 01 11 */ internal String SolveAmbiguities() { for (int y = 0; y < Height - 1; y++) { for (int x = 0; x < Width - 1; x++) { Pixel p00 = VertexSearch(x, y, g); Pixel p10 = VertexSearch(x + 1, y, g); Pixel p01 = VertexSearch(x, y + 1, g); Pixel p11 = VertexSearch(x + 1, y + 1, g); //Console.WriteLine("P= " + x + " " + y + " Valence =" + p00.valence); g.TryGetEdge(p11, p00, out TaggedUndirectedEdge <Pixel, EdgeTag> edge1); g.TryGetEdge(p01, p10, out TaggedUndirectedEdge <Pixel, EdgeTag> edge2); if (edge1 != null) { if (edge2 != null) { //Identificada uma ambiguidade if (Pixel.colorIsSimilar(p00.color, p01.color)) { //Se as 4 cores são iguais remove todas as arestas internas if (edge1 != null) { g.RemoveEdge(edge1); } if (edge2 != null) { g.RemoveEdge(edge2); } } //Heuristica da ilha else if (edge1.Source.valence == 1 || edge1.Target.valence == 1) { if (edge2 != null) { g.RemoveEdge(edge2); } } else if (edge2.Source.valence == 1 || edge2.Target.valence == 1) { if (edge1 != null) { g.RemoveEdge(edge1); } } else { //Heuristica da curva if (edge1.Source.valence == 2 || edge1.Target.valence == 2 || edge2.Source.valence == 2 || edge2.Target.valence == 2) { if (CurveSize(edge1) <= CurveSize(edge2)) { if (edge1 != null) { g.RemoveEdge(edge1); } } else { if (edge2 != null) { g.RemoveEdge(edge2); } } } else //Heuristica dos pixels sobrepostos { Pixel p1 = VertexSearch(edge1.Source.x, edge1.Source.y, g); Pixel p2 = VertexSearch(edge2.Source.x, edge2.Source.y, g); //Pixel p3 = VertexSearch(edge1.Target.x, edge1.Target.y, g); //Pixel p4 = VertexSearch(edge2.Target.x, edge2.Target.y, g); Color c1 = p1.color; Color c2 = p2.color; int sumC1 = 0, sumC2 = 0; //Inicializa x e y com -4 posicoes para verificar 3 pixeis em ambas direções int xs = p1.x - 4; int ys = p1.y - 4; while (xs <= p1.x + 3) { while (ys <= p1.y + 3) { Pixel pixel = VertexSearch(x, y, g); if (pixel.color == c1) { sumC1++; } else if (pixel.color == c2) { sumC2++; } ys++; } xs++; } //A cor em maior quantidade representa o fundo, e deve se manter os detalhes conectados if (sumC1 > sumC2) //Remove a cor em menor quantidade { g.RemoveEdge(edge1); } else { g.RemoveEdge(edge2); } } } } } } } SvgVector svg = new SvgVector { Height = Height, Width = Width }; //svg.DrawValence = true; return(svg.ToImageSVG(g, "AmbiguitiesSolved.svg")); }