IP Camera stop streaming after some time

送分小仙女□ 提交于 2019-11-28 14:49:59

Sorry about the delay but I have provide an example that works with several public IP cameras. It will need the EMGU reference replacing with your current version and the target build directory should be set to "EMGU Version\bin" alternatively extract it to the examples folder.

http://sourceforge.net/projects/emguexample/files/Capture/CameraCapture%20Public%20IP.zip/download

Rather than using the older QueryFrame() method it uses the RetrieveBgrFrame() method. It has worked reasonably well and I have had no null exceptions. However if you do replace the ProcessFrame() method with something like this

You should not be attempting to do any operations if the frame returned is Image is a nullable field and should not have a problem if _capture.RetrieveBgrFrame(); returns null if there is a problem then there is a bigger issue.

private void ProcessFrame(object sender, EventArgs arg)
{
    //If you want to access the image data the use the following method call
    //Image<Bgr, Byte> frame = new Image<Bgr,byte>(_capture.RetrieveBgrFrame().ToBitmap());

    if (RetrieveBgrFrame.Checked)
    {
        Image<Bgr, Byte> frame = _capture.RetrieveBgrFrame();
        //because we are using an autosize picturebox we need to do a thread safe update
        if(frame!=null)
        { 
             DisplayImage(frame.ToBitmap());
             Image<Bgr, Byte> ImageFrame = frame.Resize(img.Width, img.Height,  Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR); 

             // Here I am doing some other operations like 
             // 1. Save Image captured from the IP Camera
             // 2. Detect faces in Image 
             // 3. Draw Face markers on Image
             // 4. Some database based on result of Face Detection
             // 4. Delete image File 
             // continue Looping for other Ip Cameras  
        }
        //else do nothing as we have no image
    }
    else if (RetrieveGrayFrame.Checked)
    {
        Image<Gray, Byte> frame = _capture.RetrieveGrayFrame();
        //because we are using an autosize picturebox we need to do a thread safe update
        if (frame != null) DisplayImage(frame.ToBitmap());
    }
}

On a separate note your comment 'continue Looping for other Ip Cameras' may cause several issues. You should have a new Capture constructor for each camera camera you are using. How many camera are you using? and what public ip camera are you using so I can attempt to replicate the issue? The reason for the separate constructor is that ip cameras take a while to negotiate connections with and constantly Disposing of the original construct and replacing it will play havoc with the garbage collector and introduce no end if timing issues.

Cheers

Chris

[EDIT]

If your camera is returning null frames after a timeout period then I would check to see if there is an issue with the setup or maybe your connection is so slow it disconnects you to reduce lag to others there are various causes but this is not a code problem. You can use c# alone to acquire the data to a bitmap and then pass this to an Image type variable. There is a great article here:

http://www.codeproject.com/Articles/15537/Camera-Vision-video-surveillance-on-C

I've adapted this so you can use a HttpWebRequest as a final check to see if the stream is alive although there are still null exceptions that will be produced here:

using System.Net;
using System.IO;

string url;

    private void ProcessFrame(object sender, EventArgs arg)
    {
        //***If you want to access the image data the use the following method call***/
        //Image<Bgr, Byte> frame = new Image<Bgr,byte>(_capture.RetrieveBgrFrame().ToBitmap());

        if (RetrieveBgrFrame.Checked)
        {
            Image<Bgr, Byte> frame = _capture.RetrieveBgrFrame();
            //because we are using an autosize picturebox we need to do a thread safe update
            if (frame != null)
            {
                DisplayImage(frame.ToBitmap());

            }
            else
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                // get response
                WebResponse resp = req.GetResponse();
                //get stream
                Stream stream = resp.GetResponseStream();
                if (!stream.CanRead)
                {
                    //try reconnecting the camera
                    captureButtonClick(null, null); //pause
                    _capture.Dispose();//get rid
                    captureButtonClick(null, null); //reconnect
                }
            }
        }
        else if (RetrieveGrayFrame.Checked)
        {
            Image<Gray, Byte> frame = _capture.RetrieveGrayFrame();
            //because we are using an autosize picturebox we need to do a thread safe update
            if (frame != null) DisplayImage(frame.ToBitmap());
        }
    }

    private void captureButtonClick(object sender, EventArgs e)
    {
        url = Camera_Selection.SelectedItem.ToString(); //add this
        ... the rest of the code
    }

To display multiple webcams you would create a class to handle the Capture construct and processframe event. Ideally you would raise an purpose built event call that would include a camera identifier as the frameready event call does not call this. I have to make things easier created a form with as a MDI parent and opened an object to manage the capture variables and frame ready event. The Alpha version is available here:

http://sourceforge.net/projects/emguexample/files/Capture/CameraCapture%20Public%20IP%20Multipl%20Display%20Alpha.zip/download

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!