Проблемы с видеообработчиком OpenCV и детектором Alturos.Yolo
В данный момент работаю над программой распознования блоков с использованием библиотеки OpenCV (в качестве видеообработчика с использованием класса VideoCapture) и библиотеки детектора Alturos.Yolo (Использующим веса Yolov3).
Во время разработки модумя видеосчитывания возникла проблема, связанная с утечками памяти (картинка 1) , которые я не могу определить (недостаток знаний/проблемы внутри библиотеки).
Так же проблемы происходят при самой детекции, метод Alturos.Yolo.Detect() занимает от 181мс до 525мс (картинка 2), что очень замедляет картинку на выходе. Вопросы в следующем:
1)В чем может быть причина утечки? (Код прилагаю, пытался переписывать архитектуру и проводить Dispose() свойства pictureBox.Image, это снижало утечку, но:
- при изменении размера выдавало постоянно ошибку
- при увеличении окна утечка продолжалась)
2)Почему альторус (при использовании GPU) съедает 2-3 гб при инициализации и при детекции занимает ресурс процессора на 200-525 мс? Это проблема библиотеки или я что-то делаю не так по архитектуре?
3)Насколько имеет уничтожать ресурсы picturebox с помощью Dispose()?
4)Есть ли возможность выводить сначала картинку с видеообработчика и параллельно в другом потоке вести обработку? И насколько это может, в теории, исправить ситуацию?
Вот код:
//Flags
private string _videoPath;
//Video data
private VideoCapture _capture;
private Thread _altorusThread;
private YoloWrapper _wrapper;
private int _fps;
private void _startVideo_Click(object sender, EventArgs e)
{
if(_videoPath != null)
{
#region LegacyThreadAltorus
//Проверкан на существование потока с Altorus
if (_altorusThread == null)
{
_altorusThread = new Thread(() =>
{
while (true)
{
if (_videoBox.InvokeRequired)
{
MethodInvoker mi = new MethodInvoker(() =>
{
_videoBox.Image = DetectFrame(StartVideo(_videoPath));
/*_videoBox.Image = BitmapConverter.ToBitmap(StartVideo(_videoPath));*/
});
mi.Invoke();
}
Cv2.WaitKey(_fps);
}
})
{
IsBackground = true,
Name = "Altorus Thread"
};
}
if(_altorusThread.ThreadState == (ThreadState.Background | ThreadState.Suspended))
{
_altorusThread.Resume();
}
else if(_altorusThread.ThreadState == (ThreadState.Background | ThreadState.Unstarted))
{
_altorusThread.Start();
}
#endregion
}
else
{
MessageBox.Show("Видео еще не загружено!");
};
}
private Bitmap DetectFrame(Mat mat)
{
//Конвертация и подготовка средств отрисовки
Bitmap finalImage = BitmapConverter.ToBitmap(mat);
Graphics graphics = Graphics.FromImage(finalImage);
Font font = new Font("Consolas", 18, FontStyle.Bold);
SolidBrush brush = new SolidBrush(Color.White);
Pen pen = new Pen(Color.Aqua, 2);
//Детекция и отрисовка
try
{
List<YoloItem> items = _wrapper.Detect(mat.ToBytes()).ToList();
foreach (YoloItem item in items)
{
Point rectPoint = new Point(item.X, item.Y);
Size rectSize = new Size(item.Width, item.Height);
Rectangle rect = new Rectangle(rectPoint, rectSize);
graphics.DrawRectangle(pen, rect);
graphics.DrawString(item.Type, font, brush, rectPoint);
}
items.Clear();
}
catch(Exception e)
{
MessageBox.Show($"Error Altorus: {e}");
}
return finalImage;
}
private Mat StartVideo(string path)
{
if(_capture == null)
{
if(path != null)
{
_capture = new VideoCapture(path);
_fps = (int)(1000 / _capture.Fps);
}
else
{
MessageBox.Show("Вы не выбрали видео!");
}
}
Mat mat = new Mat();
_capture.Read(mat);
if (!mat.Empty())
{
/*_videoBox.Image = BitmapConverter.ToBitmap(mat);*/
/*_videoBox.Image = DetectFrame(mat);*/
return mat;
}
else
{
MessageBox.Show("Что-то пошло не так с загрузкой видео");
return null;
}
}
UPD1: Добавил глобальные переменные
UPD2: Ссылка на проект: https://dropmefiles.com/HzA4a
UPD3: Проблема с обработкой видео решилась (Спасибо, aepot), но altorus.yolo все еще съедает большую часть процессорного времени

