Pregunta

Hola estoy en el proceso de hacer un proyecto de la escuela, donde tenemos un robot de conducción en el suelo entre las placas del flamenco. Necesitamos crear un algoritmo que puede identificar las ubicaciones de estas placas, por lo que podemos crear caminos alrededor de ellos (Estamos utilizando una estrella para eso).

Hasta el momento tiene que trabajamos con AForged Biblioteca y hemos creado la siguiente clase, el único problema con esto es que cuando se crean los rectángulos dosis que no toma en cuenta que las placas no son siempre paralelas con el borde de la cámara, y que ese caso tendrá que acaba de crear un rectángulo que cubre toda la placa. Así que tenemos que encontrar alguna manera la rotación en el objeto, u otra forma de identificar esto. Tengo crear una imagen que podría ayudar a explicar este

Imagen al describir el problema: http://img683.imageshack.us/img683/ 9835 / imagerectangle.png

Cualquier ayuda sobre cómo puedo hacer esto sería muy apreciado.

Cualquier otra información o ideers son siempre bienvenidos.

public class PasteMap
{
    private Bitmap image;
    private Bitmap processedImage;
    private Rectangle[] rectangels;

    public void initialize(Bitmap image)
    {
        this.image = image;
    }

    public void process()
    {
        processedImage = image;
        processedImage = applyFilters(processedImage);
        processedImage = filterWhite(processedImage);
        rectangels = extractRectangles(processedImage);
        //rectangels = filterRectangles(rectangels);
        processedImage = drawRectangelsToImage(processedImage, rectangels);
    }

    public Bitmap getProcessedImage
    {
        get
        {
            return processedImage;
        }
    }

    public Rectangle[] getRectangles
    {
        get
        {
            return rectangels;
        }
    }

    private Bitmap applyFilters(Bitmap image)
    {
        image = new ContrastCorrection(2).Apply(image);
        image = new GaussianBlur(10, 10).Apply(image);
        return image;
    }

    private Bitmap filterWhite(Bitmap image)
    {
        Bitmap test = new Bitmap(image.Width, image.Height);

        for (int width = 0; width < image.Width; width++)
        {
            for (int height = 0; height < image.Height; height++)
            {
                if (image.GetPixel(width, height).R > 200 &&
                    image.GetPixel(width, height).G > 200 &&
                    image.GetPixel(width, height).B > 200)
                {
                    test.SetPixel(width, height, Color.White);
                }
                else
                    test.SetPixel(width, height, Color.Black);
            }
        }
        return test;
    }

    private Rectangle[] extractRectangles(Bitmap image)
    {
        BlobCounter bc = new BlobCounter();
        bc.FilterBlobs = true;
        bc.MinWidth  = 5;
        bc.MinHeight = 5;
        // process binary image
        bc.ProcessImage( image );
        Blob[] blobs = bc.GetObjects(image, false);
        // process blobs
        List<Rectangle> rects = new List<Rectangle>();
        foreach (Blob blob in blobs)
        {
            if (blob.Area > 1000)
            {
                rects.Add(blob.Rectangle);
            }
        }

        return rects.ToArray();
    }

    private Rectangle[] filterRectangles(Rectangle[] rects)
    {
        List<Rectangle> Rectangles = new List<Rectangle>();
        foreach (Rectangle rect in rects)
        {
            if (rect.Width > 75 && rect.Height > 75)
                Rectangles.Add(rect);
        }

        return Rectangles.ToArray();
    }

    private Bitmap drawRectangelsToImage(Bitmap image, Rectangle[] rects)
    {
        BitmapData data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        foreach (Rectangle rect in rects)
            Drawing.FillRectangle(data, rect, Color.Red);
        image.UnlockBits(data);
        return image;
    }
}
¿Fue útil?

Solución

Es necesario analizar las manchas un poco más para encontrar las esquinas, como se ha dicho @kigurai. La biblioteca AForge le permite hacer esto, vea la sección Finding convexa casco en esta página para obtener más información. La captura de pantalla a continuación (de la página) muestra una pequeña muestra de lo que el casco convexo es.

texto alternativo ??
(fuente: aforgenet.com )

¿Quieres echar un vistazo a la GetBlobsLeftAndRightEdges función y la GrahamConvexHull clase.

Otros consejos

Si alguien está interesado, ésta es la manera que lo hice.

Blobsprocessing:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.Textures;
using AForge.Math.Geometry;

namespace CDIO.Library
{
    public class Blobsprocessing
    {
        Bitmap image;
        BlobCounter BlobCounter;
        Blob[] blobs;
        List<Polygon> hulls;

        public Blobsprocessing(Bitmap image)
        {
            this.image = image; 
        }

        public void Process()
        {
            BlobCounter = new BlobCounter();

            processBlobs();
            extractConvexHull();
        }
        public List<Polygon> getHulls()
        {
            return hulls;
        }

        private void processBlobs()
        {
            BlobCounter.FilterBlobs = true;
            BlobCounter.MinWidth = 5;
            BlobCounter.MinHeight = 5;
            // set ordering options
            BlobCounter.ObjectsOrder = ObjectsOrder.Size;
            // process binary image
            BlobCounter.ProcessImage(image);

            blobs = BlobCounter.GetObjectsInformation();
        }

        private void extractConvexHull()
        {
            GrahamConvexHull hullFinder = new GrahamConvexHull();

            // process each blob
            hulls = new List<Polygon>();
            foreach (Blob blob in blobs)
            {
                List<IntPoint> leftPoints, rightPoints, edgePoints;
                edgePoints = new List<IntPoint>();

                // get blob's edge points
                BlobCounter.GetBlobsLeftAndRightEdges(blob,
                    out leftPoints, out rightPoints);

                edgePoints.AddRange(leftPoints);
                edgePoints.AddRange(rightPoints);

                // blob's convex hull
                List<IntPoint> hull = hullFinder.FindHull(edgePoints);
                hulls.Add(new Polygon(hull));
            }
        }
    }
}

MapFilters:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.Textures;
using AForge.Math.Geometry;

namespace CDIO.Library
{
    public class MapFilters
    {
        private Bitmap image;
        private Bitmap processedImage;
        private Rectangle[] rectangels;

        public void initialize(Bitmap image)
        {
            this.image = image;
        }

        public void process()
        {
            processedImage = image;
            processedImage = applyFilters(processedImage);
            processedImage = filterWhite(processedImage);
        }

        public Bitmap getProcessedImage
        {
            get
            {
                return processedImage;
            }
        }

        private Bitmap applyFilters(Bitmap image)
        {
            image = new ContrastCorrection(2).Apply(image);
            image = new GaussianBlur(10, 10).Apply(image);
            return image;
        }

        private Bitmap filterWhite(Bitmap image)
        {
            Bitmap test = new Bitmap(image.Width, image.Height);

            for (int width = 0; width < image.Width; width++)
            {
                for (int height = 0; height < image.Height; height++)
                {
                    if (image.GetPixel(width, height).R > 200 &&
                        image.GetPixel(width, height).G > 200 &&
                        image.GetPixel(width, height).B > 200)
                    {
                        test.SetPixel(width, height, Color.White);
                    }
                    else
                        test.SetPixel(width, height, Color.Black);
                }
            }
            return test;
        }
    }
}

Polígono:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.Textures;
using AForge.Math.Geometry;

namespace CDIO.Library
{
    public class Polygon
    {
        List<IntPoint> hull;
        public Polygon(List<IntPoint> hull)
        {
            this.hull = hull;
        }

        public bool inPoly(int x, int y)
        {
            int i, j = hull.Count - 1;
            bool oddNodes = false;

            for (i = 0; i < hull.Count; i++)
            {
                if (hull[i].Y < y && hull[j].Y >= y
                || hull[j].Y < y && hull[i].Y >= y)
                {
                    try
                    {
                        if (hull[i].X + (y - hull[i].X) / (hull[j].X - hull[i].X) * (hull[j].X - hull[i].X) < x)
                        {
                            oddNodes = !oddNodes;
                        }
                    }
                    catch (DivideByZeroException e)
                    {
                        if (0 < x)
                        {
                            oddNodes = !oddNodes;
                        }
                    }
                }
                j = i;
            }
            return oddNodes;
        }

        public Rectangle getRectangle()
        {
            int x = -1, y = -1, width = -1, height = -1;
            foreach (IntPoint item in hull)
            {
                if (item.X < x || x == -1)
                    x = item.X;
                if (item.Y < y || y == -1)
                    y = item.Y;


                if (item.X > width || width == -1)
                    width = item.X;
                if (item.Y > height || height == -1)
                    height = item.Y;


            }
            return new Rectangle(x, y, width-x, height-y);
        }
        public Bitmap drawRectangle(Bitmap image)
        {
            Rectangle rect = getRectangle();

            Bitmap clonimage = (Bitmap)image.Clone();
            BitmapData data = clonimage.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
            Drawing.FillRectangle (data, rect, getRandomColor());
            clonimage.UnlockBits(data);
            return clonimage;
        }

        public Point[] getMap()
        {
            List<Point> points = new List<Point>();
            Rectangle rect = getRectangle();
            for (int x = rect.X; x <= rect.X + rect.Width; x++)
            {
                for (int y = rect.Y; y <= rect.Y + rect.Height; y++)
                {
                    if (inPoly(x, y))
                        points.Add(new Point(x, y));
                }
            }
            return points.ToArray();
        }

        public float calculateArea()
        {
            List<IntPoint> list = new List<IntPoint>();
            list.AddRange(hull);
            list.Add(hull[0]);

            float area = 0.0f;
            for (int i = 0; i < hull.Count; i++)
            {
                area += list[i].X * list[i + 1].Y - list[i].Y * list[i + 1].X;
            }
            area = area / 2;
            if (area < 0)
                area = area * -1;
            return area;
        }

        public Bitmap draw(Bitmap image)
        {
            Bitmap clonimage = (Bitmap)image.Clone();
            BitmapData data = clonimage.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
            Drawing.Polygon(data, hull, Color.Red);
            clonimage.UnlockBits(data);
            return clonimage;
        }

        static Random random = new Random();
        int Color1, Color2, Color3;
        public Color getRandomColor()
        {
            Color1 = random.Next(0, 255);
            Color2 = random.Next(0, 255);
            Color3 = random.Next(0, 255);
            Color color = Color.FromArgb(Color1, Color2, Color3);
            Console.WriteLine("R: " + Color1 + " G: " + Color2 + " B: " + Color3 + " = " + color.Name);
            return color;
        }
    }
}

La solución más directa es probablemente para encontrar las esquinas de cada burbuja detectada y luego calcular geométricamente cuyo punto pares componen los diferentes lados de los cuadrados. Esto supone que la cámara está mirando hacia abajo de tal manera que un cuadrado es en realidad un cuadrado en la imagen (sin perspectiva de distorsión).

Sin embargo, estoy un poco curioso por qué necesita saber la rotación de los rectángulos. En todas las imágenes de ejemplo los rectángulos están más o menos alineados con los bordes de la imagen, por lo que un cuadro delimitador de una burbuja rectángulo sería muy cerca de lo que está tratando de encontrar. Por lo menos, debe ser lo suficientemente bueno para la búsqueda de ruta.

Usted debe estar utilizando redes neuronales. Ver: http://en.wikipedia.org/wiki/Neural_network

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top