2

I am currently trying to record footage of a camera and represent it with matlab in a graphic window using the "image" command. The problem I'm facing is the slow redraw of the image and this of course effects my whole script. Here's some quick pseudo code to explain my program:

    figure
    while(true)
      Frame = AcquireImageFromCamera();  % Mex, returns current frame
      image(I);
    end

AcquireImageFromCamera() is a mex coming from an API for the camera. Now without displaying the acquired image the script easily grabbs all frames coming from the camera (it records with a limited framerate). But as soon as I display every image for a real-time video stream, it slows down terribly and therefore frames are lost as they are not captured.

Does anyone have an idea how I could split the process of acquiring images and displaying them in order to use multiple cores of the CPU for example? Parallel computing is the first thing that pops into my mind, but the parallel toolbox works entirely different form what I want here...

edit: I'm a student and in my faculty's matlab version all toolboxes are included :)

Potaito
  • 1,181
  • 2
  • 10
  • 32

3 Answers3

4

Running two threads or workers is going to be a bit tricky. Instead of that, can you simply update the screen less often? Something like this:

figure
count = 0;
while(true)
    Frame = AcquireImageFromCamera();  % Mex, returns current frame
    count = count + 1;
    if count == 5
        count = 0;
        image(I);
    end
end

Another thing to try is to call image() just once to set up the plot, then update pixels directly. This should be much faster than calling image() every frame. You do this by getting the image handle and changing the CData property.

h = image(I); % first frame only
set(h, 'CData', newPixels); % other frames update pixels like this

Note that updating pixels like this may then require a call to drawnow to show the change on screen.

shoelzer
  • 10,648
  • 2
  • 28
  • 49
  • +1. You can also use the `pause` function to update the screen less often. – am304 Aug 28 '13 at 15:33
  • That would indeed allow to capture more frames, but I really need to also display them with a high frame rate. – Potaito Aug 28 '13 at 15:36
  • @am304 I don't think `pause` will help here. It would stop data acquisition too. – shoelzer Aug 28 '13 at 15:37
  • @potAito My 2nd idea of updating just the pixels might allow you to do full frame rate. You'll just have to try it. – shoelzer Aug 28 '13 at 15:38
  • @shoelzer Are you sure? It seems like the data acquisition is done by `AcquireImageFromCamera` function call, which is done by the time you need to pause the execution. – am304 Aug 28 '13 at 16:17
  • @am304 using pause would reduce the amount of acquired image AND the frame rate :) – Potaito Aug 28 '13 at 16:29
  • @shoeizer updating new pixels is a very interesting idea. With efficient algorithms this should be the fastest method. After all that's how many video codecs work. This just leaves the question how I determine the changed pixels.. – Potaito Aug 28 '13 at 16:29
  • @potAito You don't have to determine changed pixels. Simply assign a full array to CData on every frame. Calling image() results in a lot of work to figure out how to display the pixels, but changing pixel values is very efficient. – shoelzer Aug 28 '13 at 17:47
  • @shoelzer That's perfect, thanks! Now I understand. For some reason though h.CData = newPixels is not working. But RyanD's solution with set(h,'cdata',newPixels) works. I don't know why. – Potaito Aug 29 '13 at 06:14
  • @potAito Glad it works. I wrote the code without testing. RyanD did it correctly. – shoelzer Aug 29 '13 at 13:16
2

Matlab has a video player in Computer vision toolbox, which would be faster than using image().

player = vision.VideoPlayer
while(true)
  Frame = AcquireImageFromCamera();  % Mex, returns current frame
  step(player, Frame);
end
Prashanth
  • 1,252
  • 2
  • 13
  • 28
  • Thanks a lot, looks promising! I'll install the toolbox asap. Do you know by any chance if there are other play functions supporting a step-wise playback, maybe implay() ? – Potaito Aug 28 '13 at 15:37
  • You can use OpenCV library to achieve [this](http://stackoverflow.com/questions/6984447/how-to-play-a-video-file-from-my-disk-using-opencv) To use openCV in Matlab you would need [this](http://www.cs.stonybrook.edu/~kyamagu/mexopencv/). This approach is more complicated, but can prove to be more efficient. I haven't tried it! :) – Prashanth Aug 28 '13 at 15:53
2

I'm not sure how precise your pseudo code is, but creating the image object takes quite a bit of overhead. It is much faster to create it once and then just set the image data.

figure
himg = image(I)
while(true)
  Frame = AcquireImageFromCamera();  % Mex, returns current frame
  set(himg,'cdata',Frame);
  drawnow; %Also make sure the screen is actually updated.
end
RyanD
  • 116
  • 1
  • 4