Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

c# - IP Camera stop streaming after some time

I am working on one application where I want to use IP camera for displaying video streaming and and some other major operations on image captured by the IP Camera.

Libraries used in Camera capture For Camera Capture : Emgu.CV Library

Below is the code which I am using in C#.

Variable Declaration

    private Capture capture;        //takes images from camera as image frames
    private Emgu.CV.UI.ImageBox img; // Dynamic Picture Controls
    private int nCam;               // no of cameras   

Code for Processing Image

  private void ProcessFrame(object sender, EventArgs arg)
  {
    try
          {                
      // Live Streaming Display
     Image<Bgr, Byte> ImageFrame = capture.QueryFrame();

    // If Ip camera try to reinitialize the IP camera
    if(ImageFrame == null)
   {
       capture.Dispose();
       capture = new Capture(URL);                              
        ImageFrame = capture.QueryFrame();
     }                
      ImageFrame = ImageFrame.Resize(img.Width, img.Height, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR); 

     img.Image = ImageFrame;

    // 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        

     }
      catch (NullReferenceException e)
       {
       }
    }

Now, The Problem is after some time the QueryFrame() provide null value and camera Stop streaming.

Can any one tell me why this is happening? How I can resolve this problem? If any more information is needed Please Let me know.

Thanks in Advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 Versionin" 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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...