encontrar un color en una imagen en c #
-
05-10-2019 - |
Pregunta
Me encontré con este video de youtube aquí http://www.youtube.com/watch?v = Ha5LficiSJM que demuestra que alguien está haciendo detección de color utilizando el marco AForge.NET. Me gustaría duplicar lo que el autor ha hecho, pero no estoy seguro de cómo hacer algo de procesamiento de imágenes.
Parece que el marco AForge.NET le permite arrastrar hacia abajo desde la fuente de vídeo de la imagen en un formato de mapa de bits. Mi pregunta es que me podría apuntar a nadie en la dirección o pueden servir de orientación sobre la forma de interrogar a un objeto de mapa de bits para encontrar colores específicos en ella? (Por ejemplo - si hay 'rojo' o 'púrpura' en la imagen de X segundos, me gustaría plantear un evento 'ColorDetected' o algo así ...)
¿Alguien tiene alguna sugerencia sobre dónde empezar?
Gracias,
-R.
EDIT: ¿Me necesidad de caminar todo el objeto de mapa de bits e interrogar a cada píxel para el color? De este modo: http://msdn.microsoft.com/ en-us / library / system.drawing.bitmap.getpixel.aspx
Solución
Bueno, siempre se puede utilizar el método de GDI +.
Bitmap b = new Bitmap( "some path" );
Color x = b.GetPixel( x, y );
Sin embargo, GetPixel es en realidad bastante lenta. Trate de esa manera en primer lugar, pero si usted necesita para escanear muchas imágenes relativamente grandes puede que no funcione para usted. En ese caso, utilice LockBits para obtener un puntero a un bloque de memoria contigua. A continuación, puede recorrer la imagen rápidamente, pero usted tiene que saber cómo manipular los punteros, aunque no es terriblemente complicado.
EDIT: Usando LockBits mirar a cada píxel:
Bitmap b = new Bitmap( "some path" );
BitmapData data = b.LockBits( new Rectangle( 0, 0, b.Width, b.Height ),
ImageLockMode.ReadOnly, b.PixelFormat ); // make sure you check the pixel format as you will be looking directly at memory
unsafe
{
// example assumes 24bpp image. You need to verify your pixel depth
// loop by row for better data locality
for( int y = 0; y < data.Height; ++y )
{
byte* pRow = (byte*)data.Scan0 + y * data.Stride;
for( int x = 0; x < data.Width; ++x )
{
// windows stores images in BGR pixel order
byte r = pRow[2];
byte g = pRow[1];
byte b = pRow[0];
// next pixel in the row
pRow += 3;
}
}
}
b.UnlockBits(data);
Si las imágenes se rellenan al final puede utilizar la propiedad BitmapData.Stride llegar al inicio de cada nueva fila (de lo contrario va a leer un poco de chatarra y sus compensaciones será chiflado).
Otros consejos
Además de respuesta Ed Swangren's con LockBits
puede evitar punteros todos juntos. Si está utilizando el WPF (o tiene acceso a) puede hacer algo como esto:
var bitmap = new BitmapImage(uri);
//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary
bitmap.CopyPixels(..size, pixels, fullStride, 0);
Y ahora sólo se puede hacer una matriz de búsqueda de virus con pixels
sin punteros. Este fragmento es un par de años y de un proyecto en el que he desarrollado mi propia solución AmbiLight lo que puede ser bastante rápido. Una vez más, se trata de unos pocos años, así como nuevas clases WriteableBitmap
etc., pueden ser mejor y evitar una matriz de copia. En mi inicialmente solución Solía ??punteros, pero cuando me di cuenta de que no era necesario que lo cambié.