Кажется, что простой веб-канал Emgucv пропускает память - PullRequest
0 голосов
/ 03 ноября 2018

Следующий код - это метод, с помощью которого я получаю кадры с веб-камеры в моем большом проекте:

Imports Emgu.CV
Imports Emgu.CV.CvEnum
Imports Emgu.CV.Structure
Imports Emgu.CV.UI
Imports Emgu.CV.Util

Public Class Form1

    Dim img As Mat
    Dim cam As VideoCapture

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Try
            cam = New VideoCapture(0)
        Catch ex As Exception
            'show error via message box
            MessageBox.Show("unable To read from webcam, error: " + Environment.NewLine + Environment.NewLine +
                                ex.Message + Environment.NewLine + Environment.NewLine +
                                "Try another")
            Return
        End Try

        AddHandler Application.Idle, New EventHandler(AddressOf Me.ProcessFrame)

    End Sub

    Sub ProcessFrame(sender As Object, arg As EventArgs)

        img = cam.QueryFrame()
        ImageBox1.Image = img

    End Sub

End Class

По сути, он берет кадр с веб-камеры и вставляет его в поле для изображений в форме. При запуске кода мое потребление памяти выглядит так:

https://i.imgur.com/PRGULG9.png

Из этого я заключаю, что что-то неправильно распределяется, но я не могу понять, что это такое. Чем больше MP у веб-камеры, тем выше всплеск памяти. То же самое при загрузке локальных видеофайлов.

Ответы [ 3 ]

0 голосов
/ 03 ноября 2018

Чтение кадров - одна из самых медленных частей обработки видео. Ваш минимальный пример недостаточен, чтобы помочь с утечкой памяти (если она действительно существует). Убедитесь, что вы не создаете объект видеозахвата повторно в цикле.

0 голосов
/ 03 ноября 2018

Класс Mat реализует IDisposable. Вызов Dispose() для старого изображения перед отображением нового может помочь минимизировать выбросы, но, как упоминал Лукас К, не все гарантированно освобождаются до тех пор, пока GC не запустится.

img = cam.QueryFrame()

'Dispose of the old image (if one exists).
If ImageBox1.Image IsNot Nothing Then ImageBox1.Image.Dispose()

ImageBox1.Image = img

Как правило, вы должны вызывать Dispose() для всех классов, которые реализуют IDisposable, когда вы закончите использовать их (или заключить их в Using блоков , где это применимо).

0 голосов
/ 03 ноября 2018

Как вы видите на связанном изображении, потребление памяти уменьшается только сборщиком мусора (GC), который выполняется на основе фиксированных временных циклов (следовательно, колебаний). Ваш код входит в ProcessFrame () без освобождения устройства захвата. Я предлагаю использовать [VideoCapture] .release () как подробно здесь для решения проблемы. Если вам нужна постоянная частота кадров, вы не сможете избежать этих скачков памяти.

...