Reconocer objetos en la imagen [cerrado]
-
26-09-2019 - |
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;
}
}
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.
??
(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