Преобразование изображения в c#
Edit: решено! пожалуйста, смотрите мой ответ ниже для деталей. Я не смог найти ответа на исходный вопрос, но я нашел альтернативное решение
этот вопрос может быть задан где-то еще, но я искал несколько дней и не могу найти ничего, что помогает.
вопрос: мне нужно преобразовать "поток" в " изображение (bgr, байт)" за один раз, есть ли способ / команда для преобразования непосредственно из Система.Рисунок.Изображение.FromStream в Эмгу.Резюме.Образ(Бгр байт) без конверсии поток to изображения to точечный to изображение (bgr, байт)?
информация: я кодирую на c# в Visual Studio 2010 как часть моего диссертационного проекта. Я беру поток изображений с IP-камеры в сети и применяю множество алгоритмов для обнаружения лиц/извлечения черт лица и распознавания лиц лица. На моя локальная камера для ноутбуков я могу достичь FPS около 25~ (плюс-минус), включая алгоритмы, потому что мне не нужно конвертировать изображение. Для потока IP-камеры мне нужно преобразовать его много раз, чтобы достичь желаемого формата, и результат составляет около 5-8fps.
(Я знаю, что мой текущий метод чрезвычайно неэффективен, поэтому я здесь, я фактически конвертирую изображение в 5 раз (даже серое масштабирование тоже), фактически используя только половину памяти моих процессоров (i7, 8GB RAM)). Он должен be image (bgr, byte), поскольку это единственный формат, с которым будут работать алгоритмы.
код, который я использую для получения изображения:
//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();
у меня есть много вещей в фоновом режиме управления соединениями, данными, безопасностью и т. д., которые я сократил до вышеуказанного кода. Мой текущий код для скрытия изображения до желаемого вывода:
//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>();
Я понимаю, что есть способ сохранить изображение локально временно, но мне нужно было бы избежать этого в целях безопасности. Я глядя больше для прямого преобразования, чтобы помочь сэкономить вычислительную мощность. Я что-то упускаю? Вся помощь приветствуется.
Спасибо за чтение. (Я обновлю это, если кто-нибудь запросит более подробную информацию) - Дэйв!--7-->
3 ответов
У вас есть несколько потенциальных узких мест, не последним из которых является то, что вы, вероятно, jpeg декодирование потока в изображение, а затем преобразование его в растровое изображение, а затем в изображение openCV.
один из способов обойти это-полностью обойти образ .NET. Это будет включать в себя попытку использовать libjpeg напрямую. Есть Свободный порт здесь В C# и IIRC вы можете подключиться к нему, чтобы получить вызов на основе каждой строки для заполнения буфер.
недостатком является то, что вы декодируете данные JPEG в управляемом коде, который будет работать по крайней мере на 1.5 X медленнее, чем эквивалентный C, хотя, честно говоря, я ожидал бы, что скорость сети значительно уменьшится.
OpenCV должен иметь возможность читать изображения jpeg напрямую (хотите угадать, что они используют под капотом? Опрос говорит: libjpeg), что означает, что вы можете буферизировать весь поток и передать его OpenCV и полностью обойти слой .NET.
Я считаю, что нашел ответ на мою проблему. Я баловался, используя Майсурадзеидея обработки в памяти, которая улучшила fps крошечный запас (не сразу заметный без тестирования). А также благодаря цоколи ответ у меня есть понимание многопоточности, и я могу оптимизировать это по мере продвижения, поскольку я могу разделить алгоритмы на работу параллельно.
то, что я думаю, моя причина-скорость сети! не фактическая задержка алгоритма. Как отметил Вано с секундомером, чтобы найти скорость, алгоритмы на самом деле не потребляли так много. Таким образом, с алгоритмами и без них скорость примерно одинакова, если я оптимизирую использование потоков, поэтому следующий кадр собирается по мере завершения обработки предыдущего.
Я сделал некоторое тестирование на некоторых физических маршрутизаторах Cisco и получил тот же результат, если немного медленнее возиться с тактовой частотой и шириной полосы, что было заметно. Так что мне нужно найти из способа получить кадры по сетям быстрее, очень большое спасибо всем, кто ответил, кто помог мне лучше понять!
вывод:
- многопоточность для оптимизации
- обработка в памяти вместо преобразования постоянно
- лучшие сетевые решения (более высокая пропускная способность и скорость)
Edit: код для извлечения изображения и процесса в памяти для тех, кто находит это ищет помогите!--5-->
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
вы можете сохранить несколько изображений в памяти (буфер), а затем начать обработку из буфера.
что-то вроде этого:
//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...
}
}
но обратите внимание, что вам понадобится достаточно ОЗУ для хранения изображений в памяти, а также вы должны настроить размер буфера на мясо ваши требования.