2016-08-09 3 views
1

Я делаю некоторые тесты с библиотекой AForge. Я пытаюсь читать данные, поступающие с моей USB-камеры (фреймы). Он работает очень хорошо, но единственной проблемой является ОЗУ. Он просачивается. Кажется, что фрейм занимает ~ 30 КБ, но используемая память продолжает расти.Использование ОЗУ при чтении кадров с камеры

Вот мой код:

Imports AForge 
Imports AForge.Controls 
Imports AForge.Video 
Imports AForge.Video.DirectShow 
Imports System.Threading 
Imports System.IO 
Imports System.Collections.Concurrent 
Imports System.ComponentModel 

Public Class Form1 
    Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice) 
    Dim WithEvents device As VideoCaptureDevice 
    Dim count As Long, bit As Bitmap 
    Dim read As New Thread(AddressOf read_que) 
    Dim pic_que As New ConcurrentQueue(Of Bitmap) 


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
     For Each cam As FilterInfo In sources 
      ComboBox1.Items.Add(cam.Name) 
     Next 
    End Sub 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString) 
     AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame) 

     device.WaitForStop() 
     device.Start() 
    End Sub 

    Sub frame(obj As Object, args As NewFrameEventArgs) 
     If bit IsNot Nothing Then 
      bit.Dispose() 
      bit = Nothing 
     End If 
     bit = New Bitmap(args.Frame) 

     If PictureBox1.Image IsNot Nothing Then 
      PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose())) 
     End If 

     PictureBox1.Image =bit ' or ... = Imaging.Image.Clone(args.Frame) 

    End Sub 
End Class 

Я пытался даже поставить все кадры в параллельной очереди, а затем в отдельном потоке, чтобы прочитать его (я опубликовал упрощенную версию, которая, кажется, взять наименьшее количество памяти барана). Но есть еще одна проблема (это не так важно): когда я запускаю приложение, картинка представляет собой blanck, а используемый ram - 16 МБ (постоянный, поэтому он не работает).

Только когда я вхожу в диспетчер задач, и я нажимаю End Process (без фактического закрытия), он начинает показывать кадры. Я думаю, что это связано с графическим интерфейсом (когда я нажимаю End Process, возможно, он запускает событие, которое запускает класс чтения кадров?). enter image description here

только в случайные моменты времени, кажется, работает с первого раза (это правда, что это может быть проблемой камеры, потому что он старый и работает только на XP, так что я должен был использовать .NET Framework 4).

Где проблема (приоритетом является просачивание плунжера)?

+0

ли устройство подъема те 'NewFrameEvents' в другом потоке? Похоже, вы выбираете, какой из них, так они все делают? Если вы вызываете «Утилизировать старое изображение», почему вы устанавливаете новое изображение напрямую? Он не выглядит как Option Strict. – Plutonix

+1

Coud проблема с этим не начинается из-за вызова device.WaitForStop(). – FloatingKiwi

+0

@Plutonix прав, что с вашей резьбой что-то не так. Утилизируйте растровое изображение только на нити ui, чтобы вы могли быть уверены, что в данный момент это не отображается в окне изображения. Также вы можете проверить, нужно ли устанавливать args.Frame. – FloatingKiwi

ответ

0

решаемые его. Спасибо за вашу помощь, но я знал, что мой код работает (я использовал перед делегатом рисовать на ящике с изображением, чтобы он был потокобезопасным - код, который я предоставил, был «быстрым и грязным»). Проблема была ... VM. Я тестировал код на виртуальной машине. Он работает на обычном ПК.

код теперь выглядит так:

Imports AForge 
Imports AForge.Controls 
Imports AForge.Video 
Imports AForge.Video.DirectShow 
Imports System.Threading 
Imports System.IO 
Imports System.Collections.Concurrent 
Imports System.ComponentModel 

Public Class Form1 
    Dim sources As New FilterInfoCollection(FilterCategory.VideoInputDevice) 
    Dim device As VideoCaptureDevice 
    Delegate Sub lp(ByRef pic As Bitmap) 
    Delegate Sub lpp(nr As Integer, nr2 As Integer) 
    Delegate Sub slp() 
    Dim count As Long, bit As Bitmap 
    Dim read As New Thread(AddressOf read_que) 
    Dim pic_que As New ConcurrentQueue(Of Bitmap) 


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
     For Each cam As FilterInfo In sources 
      ComboBox1.Items.Add(cam.Name) 
     Next 
    End Sub 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     device = New VideoCaptureDevice(sources(ComboBox1.SelectedIndex).MonikerString) 
     AddHandler device.NewFrame, new Video.NewFrameEventHandler(AddressOf frame) 

     'device.WaitForStop() 
     device.Start() 

     'read.IsBackground = True 
     'read.Start() 
    End Sub 

    Sub frame(obj As Object, args As NewFrameEventArgs) 
     'If bit IsNot Nothing Then 
     ' bit.Dispose() 
     ' bit = Nothing 
     'End If 
     'bit = New Bitmap(args.Frame) 

     If PictureBox1.Image IsNot Nothing Then 
      PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image.Dispose())) 
     End If 

     PictureBox1.Invoke(New MethodInvoker(Sub() PictureBox1.Image = Imaging.Image.Clone(args.Frame))) 'Imaging.Image.Clone(args.Frame) ' or ...=bit 
    End Sub 
End Class 
1

Попробуйте использовать это:

Sub frame(obj As Object, args As NewFrameEventArgs) 
    If Me.InvokeRequired Then 
     Me.BeginInvoke(Sub() frame(obj, args)) 
    Else 
     Dim oldImage = PictureBox1.Image 

     Dim bitmap = New Bitmap(args.Frame) 
     args.Frame.Dispose() 'Not sure if it has a Dispose 
     PictureBox1.Image = bitmap 

     If oldImage IsNot Nothing Then oldImage.Dispose() 

    End If 
End Sub 
+1

Если 'args.Frame' можно использовать для создания нового изображения, это, безусловно, необходимо будет утилизировать. OP, по-видимому, забыл о значении UpVotes («полезный, полезный»), хотя они используют 2 ключевых элемента, которые вы предложили, так что +1, поскольку они не могут быть обеспокоены – Plutonix