tutorial net libreria examples emgu c# image emgucv type-conversion

c# - net - opencv sharpdevelop



Convertir imagen en c# (3)

Puede guardar varias imágenes en la memoria (búfer) y luego comenzar a procesar desde el búfer.

Algo como esto:

//Convert stream to image then to bitmap Bitmap bmpImage = new Bitmap(System.Drawing.Image.FromStream(stream)); //Convert to emgu image (desired goal) currentFrame = new Emgu.CV.Image<Bgr, Byte>(bmpImage); //gray scale for later use gray = currentFrame.Convert<Gray, Byte>(); SaveToBuffer(gray); Queue<Emgu.CV.Image<Gray, Byte>> buffer = new Queue<Emgu.CV.Image<Gray, Byte>>(); bool canProcess = false; // ... private void SaveToBuffer(Emgu.CV.Image<Gray, Byte> img) { buffer.Enqueue(img); canProcess = buffer.Count > 100; } private void Process() { if(canProcess) { buffer.Dequeue(); // Processing logic goes here... } else { // Buffer is still loading... } }

Pero tenga en cuenta que necesitará suficiente memoria RAM para almacenar imágenes en la memoria y también debe ajustar el tamaño del búfer para satisfacer sus necesidades.

Editar: SOLUCIONADO Por favor, mira mi respuesta abajo para más detalles. No pude encontrar una respuesta a la pregunta original, pero encontré una solución alternativa

Esta pregunta puede hacerse en otro lugar pero he estado buscando por días y no encuentro nada que me ayude.

Pregunta: Necesito convertir "Stream" a "image (bgr, byte)" de una vez, ¿Hay una forma / comando para convertir directamente de System.Drawing.Image.FromStream a Emgu.CV.Image (Bgr, Byte) sin convertir de secuencia a imagen a mapa de bits a imagen (bgr, byte) ?

Información: estoy codificando en c # en Visual Studio 2010 como parte de mi proyecto de disertación. Estoy tomando una secuencia de imágenes de una cámara IP en una red y aplicando muchos algoritmos para detectar rostros / extraer rasgos faciales y reconocer el rostro de una persona. En mi cámara local de laptops puedo alcanzar un FPS de aproximadamente 25 ~ (dar o recibir) incluyendo algoritmos porque no tengo que convertir la imagen. Para una transmisión de cámara IP, necesito convertirla muchas veces para lograr el formato deseado y el resultado es alrededor de 5-8 fps.

(Sé que mi método actual es extremadamente ineficiente y por eso estoy aquí, en realidad estoy convirtiendo una imagen 5 veces en total (incluso escala de grises), en realidad solo usando la mitad de la memoria de mi procesador (i7, 8 gb RAM)). Tiene que ser imagen (bgr, byte) ya que es el único formato con el que funcionarán los algoritmos.

El código que estoy usando para obtener la imagen:

//headers using System.IO using System.Threading; using System.Net; //request a connection req = (HttpWebRequest)HttpWebRequest.Create(cameraUrl); //gives chance for timeout for errors to occur or loss of connection req.AllowWriteStreamBuffering = true; req.Timeout = 20000; //retrieve response (if successfull) res = req.GetResponse(); //image returned stream = res.GetResponseStream();

Tengo un montón de cosas en el fondo administrando conexiones, datos, seguridad, etc. que he acortado al código anterior. Mi código actual para ocultar la imagen al resultado deseado:

//Convert stream to image then to bitmap Bitmap bmpImage = new Bitmap(System.Drawing.Image.FromStream(stream)); //Convert to emgu image (desired goal) currentFrame = new Emgu.CV.Image<Bgr, Byte>(bmpImage); //gray scale for other uses gray = currentFrame.Convert<Gray, Byte>();

Entiendo que hay un método para guardar una imagen localmente de forma temporal, pero que debería evitar eso por razones de seguridad. Estoy buscando una conversión directa para ayudar a ahorrar potencia de procesamiento. ¿Estoy pasando por alto algo? Toda la ayuda es apreciada.

Gracias por leer. (Actualizaré esto si alguien solicita más detalles) -Dave


Tienes un par de cuellos de botella potenciales, uno de los cuales es que probablemente estés jpeg decodificando la transmisión en una imagen y luego convirtiéndola en un mapa de bits y luego en una imagen openCV.

Una forma de evitar esto es eludir por completo las imágenes .NET. Esto implicaría tratar de usar libjpeg directamente. Hay un puerto libre aquí en C #, y IIRC se puede enganchar para recibir llamadas por cada línea de escaneo para llenar un buffer.

La desventaja es que está decodificando datos JPEG en código administrado que se ejecutará al menos 1.5 veces más lento que el equivalente a C, aunque con toda franqueza, yo esperaría que la velocidad de la red empequeñeciera esto inmensamente.

OpenCV debería ser capaz de leer imágenes JPEG directamente (¿quieres adivinar lo que usan debajo del capó? La encuesta dice: libjpeg), lo que significa que puedes almacenar toda la secuencia y entregarla a OpenCV y omitir por completo la capa .NET.


Creo que encontré la respuesta a mi problema . He incursionado usando la idea de Vano Maisuradze de procesar en la memoria, lo que mejoró los fps un pequeño margen (no inmediatamente notificable sin pruebas). Y también gracias a la respuesta de Plinths tengo una comprensión de Multi-Threading y puedo optimizar esto a medida que avance, ya que puedo dividir los algoritmos para que funcionen en paralelo.

¡Lo que creo que es mi causa es la velocidad de la red! no el retraso del algoritmo real. Como lo señaló Vano con el cronómetro para encontrar la velocidad, los algoritmos en realidad no consumieron tanto. Por lo tanto, con y sin los algoritmos, la velocidad es casi la misma si optimizo el uso de subprocesos, por lo que el siguiente fotograma se recopilará cuando el anterior termine de procesarse.

Hice algunas pruebas en algunos enrutadores Cisco físicos y obtuve el mismo resultado si un poco más lento jugando con velocidades de reloj y anchos de banda que era notable. Así que tengo que encontrar una manera de recuperar cuadros en redes más rápido, ¡Muchísimas gracias a todos los que me respondieron y me ayudaron a comprender mejor!

Conclusión:

  • Multi-threading para optimizar
  • Procesamiento en memoria en lugar de convertir constantemente
  • Mejores soluciones de red (Mayor ancho de banda y velocidades)

Editar: el código para recuperar una imagen y procesar en la memoria para cualquier persona que encuentre esto en busca de ayuda

public void getFrames(object sender, EventArgs e) {//Gets a frame from the IP cam //Replace "IPADDRESS", "USERNAME", "PASSWORD" //with respective data for your camera string sourceURL = "http://IPADDRESS/snapshot.cgi?user=USERNAME&pwd=PASSWORD"; //used to store the image retrieved in memory byte[] buffer = new byte[640 * 480]; int read, total = 0; //Send a request to the peripheral via HTTP HttpWebRequest req = (HttpWebRequest)WebRequest.Create(sourceURL); WebResponse resp = req.GetResponse(); //Get the image capture after recieving a request //Note: just a screenshot not a steady stream Stream stream = resp.GetResponseStream(); while ((read = stream.Read(buffer, total, 1000)) != 0) { total += read; }//While End //Convert memory (byte) to bitmap and store in a picturebox pictureBox1.Image = (Bitmap)Bitmap.FromStream(new MemoryStream(buffer, 0, total)); }//getFrames End private void button1_Click(object sender, EventArgs e) {//Trigger an event to start running the function when possible Application.Idle += new EventHandler(getFrames); }//Button1_Click End