开发者

EmguCV 2.3.0 in C# QueryFrame returns the previous queried frame

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?

Note: This solution is not sufficient for quick acquisition of frames, the question continues here: System.TypeInitializationException using Emgu.CV in C#


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.

_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:

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, Byte> 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:

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


I mean as stupid as it sounds, just query the frame twice. I know that is not the "state-of-the-art"-way to solve Problems but i had the same issue and i could solve it that way.

Here is my Capture-Method

public void Capture_Image()
    {
        try
        {
            capture.Start();
            capture.Pause();

            tempImg = capture.QueryFrame().Bitmap;//Capture twice here
            tempImg = capture.QueryFrame().Bitmap;
            tempImg.Save("C:/FHT59N3/Bildanalyse_Projekt/image.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }
        catch (NullReferenceException)
        {
            string message = "No Camera found";
            string title = "Please connect Camera";
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            MessageBox.Show(message, title, buttons, MessageBoxIcon.Warning);
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜