Click here to Skip to main content
15,889,889 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am using EmguCV 2.3.0 and am querying frames at random intervals from a Capture to be saved to hard drive. The problem is when I call the Capture.QueryFrame() or Capture.QuerySmallFrame() it is delayed by a frame. To make this more clear: I start the program and query a frame pointed at my face. My face appears in the .jpeg. I then point the camera away from my face and query another frame, and my face appears in the .jpeg again. I then point it back at my face once more, query a frame and the .jpeg contains the image pointed away from my face. There appears to be a 1 frame delay in a query. Is there some underlying buffer? What is causing this? And most importantly: how can I solve this problem without querying multiple frames for a single captured image?

Another question I have is that when I set the webcam resolution to 1600x1200, the program and computer begins to lag - even without making use of the images or querying frames. Is that caused only because I create a Capture and keep it in memory? Is there a way to lessen the affects of this?
Posted
Updated 29-Sep-11 8:34am
v2

1 solution

Hi
(I'm the same person who gave you this answer on Stackoverflow in case you think I'm copying :), this is just in case others stumble across this question)

Well the problem you have is that your not disposing of your old capture so when you send of for another it will always return the old one and then get another. The following code adjusted from the Web camera example should do the trick.

C#
_capture = new Capture();
Image<Bgr, Byte> frame = _capture.QueryFrame();

Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>();
Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown();
Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp();
Image<Gray, Byte> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60));

captureImageBox.Image = frame;
grayscaleImageBox.Image = grayFrame;
smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
cannyImageBox.Image = cannyFrame;
_capture.Dispose();


It is the _capture.Dispose(); that is the important bit.

As for your 1600x1200 yes your right it is because you have a large amount of data in memory. First of start by efficiently 'using' the memory stream and disposing of it when where done with it. This is done with the 'using' statement which automatically creates the object at the start and calls its .Dispose function at the end, just so you don't have to. Note the copy procedure else a pointer is passed and when you exit the using code you will dispose of frame as well. You should also practice the 'using' statement when using images. But the above code will now look like this:

C#
Image<Bgr, Byte> frame;
using (Capture capture = new Capture())
{
    frame = capture1.QueryFrame().Copy(); //You must copy else frame will be disposed off
}
Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>();
Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown();
Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp();
Image<<gray,> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60));

grayscaleImageBox.Image = grayFrame;
smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
cannyImageBox.Image = cannyFrame;


Second of all you can resize the captured image using .Resize(scale, Interpolation Method). Large images are usually passed from a camera using a dedicated frame grabber so system dependency is avoided obviously this is no longer the case with HD USB web cams.

You can resize your input image like so and with your 'using' statements efficiently your final code will look like this:

C#
Image<Bgr, Byte> frame;
using (Capture capture1 = new Capture())
{
    frame = capture1.QueryFrame().Resize(0.5, Emgu.CV.CvEnum.INTER.CV_INTER_AREA).Copy();
    captureImageBox.Image = frame;
}

using (Image<Gray, Byte> grayFrame = frame.Convert<Gray, Byte>())
{
    grayscaleImageBox.Image = grayFrame;
    using (Image<Gray, Byte> smallGrayFrame = grayFrame.PyrDown())
    {
        using (Image<Gray, Byte> smoothedGrayFrame = smallGrayFrame.PyrUp())
        {
            smoothedGrayscaleImageBox.Image = smoothedGrayFrame;
            using (Image<Gray, Byte> cannyFrame = smoothedGrayFrame.Canny(new Gray(100), new Gray(60)))
            {
                cannyImageBox.Image = cannyFrame;
            }
        }
    }
}


Cheers
Chris
 
Share this answer
 
v2
Comments
Member 12393426 18-Apr-16 15:36pm    
instead of capturing frame from the camera, i want to use my own image(taken earlier) so in the same code i wanna work with image, can you please help me out. I am new to C# and EmguCv. Or may give a link for the code. Thankyou!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900