Ask Your Question
0

Videowriter and capturing - memory leak ?

asked 2014-11-23 02:28:40 -0600

Hi all, this is my first posting here. I am using OSX 10.10 and OpenCV 2.4.9. I am currently trying to capture long movies from a webcam at 25 frames/second.. The frame rates I get are okay at the beginning - then the frame rate starts dropping and the memory which is used goes up. I have replicated this on four machines and the offending program line is the videowriter.write(frame) part. Apparently there is a memory leak which I can observer in the memory usage. When I stop and restart the writer it starts again with the higher frame rate and drops again. This is why it is not possible to record longer movies in real time (it does not matter so much if you simply write out processed images from movies). Can anybody help me, before I rewrite this using Apple Quicktime (which is hell) ?

Greetings Karl

edit retag flag offensive close merge delete

Comments

1

Hi, please post here your code, from webcam opening to video writing. I don't have such problem here...

petititi gravatar imagepetititi ( 2014-11-23 12:46:44 -0600 )edit

I have a couple of students with exactly the same problem. They get memory leaks also when capturing a large amount of frames. Someone should look into this and provide a fix through a PR.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-11-26 08:20:59 -0600 )edit

Somehow my posting has not made it - I had the Python code and some graphs on the behavior of the videowriter posted - I will try again this afternoon

grammer gravatar imagegrammer ( 2014-11-27 01:50:03 -0600 )edit

Be patient, my moderator panel is broken for the moment so I cannot access the topics. The hosting is moving in a small week and then we get an updated Q&A forum which will work again like the old days.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-11-27 05:54:54 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2014-11-25 04:07:47 -0600

This is part of a bigger project, so I had to peel the source code out of it - its dirty but it makes my point. The goal is an application which records a video and sends time stamps to various other machines and a PowerLab. WxPython is in the game because theres a lot of GUI and other processes. In the source code I left the video in its original size - because the effect comes earlier. (I know it would be a solution to make the video as small as possible but then the effect would simply occur later).

The capturing and writing out the frames is done by a wxpython timer. And theres no change if I remove the wxpython stuff. Thats the source code:

!/usr/bin/env python

import wx import time import cv, cv2 import sys from pylab import *

class MyFrame(wx.Frame): def __init__(self, args, *kwds):

      ############################################################################ initialize camera and capturing
      self.capture = cv2.VideoCapture(0) 
      ret, self.frame = self.capture.read()
      self.cwidth=int(self.capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH))
      self.cheight=int(self.capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT))


      self.capSize=(self.cwidth,self.cheight)
      self.fps=12.5
      self.frames=0
      self.iterations=2000 ###################### number of frames to capture
      self.frame_rate_data=[]
      self.frame_data=[]

      print 'Camera loaded',self.cwidth,self.cheight,self.capSize

      ######################################################################## wxpython
      wx.Frame.__init__(self, *args, **kwds)
      mainSizer = wx.BoxSizer(wx.VERTICAL)

      videoWarper = wx.StaticBox(self, label="Video",size=(self.cwidth,self.cheight))
      videoBoxSizer = wx.StaticBoxSizer(videoWarper, wx.VERTICAL)
      self.videoPanel = wx.Panel(self, -1,size=(self.cwidth,self.cheight))
      videoBoxSizer.Add(self.videoPanel,0)
      mainSizer.Add(videoBoxSizer,0)
      self.Show()
      self.SetSizerAndFit(mainSizer)

      ######################################################################## convert frame to bmp for wx python
      self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
      self.bmp = wx.BitmapFromBuffer(self.cwidth, self.cheight, self.frame)

      ######################################################################## initialize videowriter
      self.fourcc = cv2.cv.CV_FOURCC('m', 'p', '4', 'v') 
      self.vout = cv2.VideoWriter() ################################################### open videowriter 
  self.outmovie='test'+'.mov'
      success = self.vout.open(self.outmovie,self.fourcc,self.fps,self.capSize,True)

      ####################################################################### initialize timer
      self.timer = wx.Timer(self.videoPanel)
      self.videoPanel.Bind(wx.EVT_PAINT, self.OnPaint)
      self.videoPanel.Bind(wx.EVT_TIMER, self.NextFrame)
      self.t0 =time.time()
      self.timer.Start(int(1000.0/self.fps))

 def OnPaint(self, event):           
                dc = wx.BufferedPaintDC(self.videoPanel)
                dc.DrawBitmap(self.bmp, 0, 0)

 def NextFrame(self, event):
                 ret, self.frame = self.capture.read()
                 if ret:  
                               self.xtime= time.time() - self.t0 
                               self.frames=self.frames+1
                               self.vout.write(self.frame) ######################### this is the offending line !!!   videowriter on - off             

                               xtime= time.time() - self.t0 
                               fpa= self.frames/xtime      
                               #print  self.frames, self.xtime, fpa
                               self.frame_rate_data.append (fpa)
                               self.frame_data.append (self.frames)

                               self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
                               self.bmp.CopyFromBuffer(self.frame)
                               self.Refresh()

                               if self.frames ==self.iterations: ################### plot and quit
                                    plot(self.frame_data,self.frame_rate_data)
                                    grid(True)
                                    savefig("test.png")
                                    show()
                                    self.Destroy()
                                    sys.exit()

if __name__ == "__main__":

    app=wx.App(False)
    frame_1 = MyFrame(None, wx.ID_ANY, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

Ok - thats the ... (more)

edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-11-23 02:28:40 -0600

Seen: 2,033 times

Last updated: Nov 25 '14