我正在开发一个应用程序,我希望使用IP camera
来显示视频流以及IP Camera
捕获的图像上的其他一些主要操作。
相机捕获中使用的库 对于相机捕捉:Emgu.CV库
以下是我在C#中使用的代码。
变量声明
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
处理图像的代码
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)
{
}
}
现在,问题是在一段时间后QueryFrame()
提供null
值并且相机停止流式传输。
任何人都可以告诉我为什么会这样吗? 我怎么解决这个问题? 如果需要更多信息,请告诉我。
先谢谢。
答案 0 :(得分:2)
对于延迟感到抱歉,但我提供了一个适用于多个公共IP摄像机的示例。它需要EMGU引用替换为您当前的版本,目标构建目录应设置为“EMGU Version \ bin”或者将其提取到示例文件夹中。
http://sourceforge.net/projects/emguexample/files/Capture/CameraCapture%20Public%20IP.zip/download
它不使用旧的QueryFrame()方法,而是使用RetrieveBgrFrame()方法。它工作得相当好,我没有空例外。但是,如果你用这样的
替换ProcessFrame()方法如果返回的帧是Image是一个可以为空的字段,则不应该尝试进行任何操作,如果_capture.RetrieveBgrFrame(),则不应该有问题;如果出现问题则返回null,则存在更大的问题。
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());
}
}
另请注意,您的评论“继续循环播放其他Ip相机”可能会导致多个问题。您应该为正在使用的每个摄像头摄像头配备一个新的 Capture 构造函数。你用了多少台相机?您正在使用什么公共IP摄像头,所以我可以尝试复制这个问题?单独的构造函数的原因是ip camera需要一段时间来协商连接并且不断地处理原始构造并替换它将对垃圾收集器造成严重破坏,并且如果时间问题则不会引入。
干杯
克里斯
[编辑]
如果您的相机在超时时间后返回空帧,那么我会检查设置是否存在问题,或者您的连接速度很慢,它会断开连接以减少对其他人的延迟,但有多种原因但这是不是代码问题。您可以单独使用c#将数据获取到位图,然后将其传递给Image类型变量。这里有一篇很棒的文章:
http://www.codeproject.com/Articles/15537/Camera-Vision-video-surveillance-on-C
我已经对此进行了调整,因此您可以使用HttpWebRequest作为最终检查,以查看流是否仍然存在,尽管此处仍会生成空的异常:
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
}
要显示多个网络摄像头,您需要创建一个类来处理Capture构造和processframe事件。理想情况下,您将引发一个专用的事件调用,其中包含一个摄像机标识符,因为frameready事件调用不会调用它。我必须更容易创建一个带有MDI父级的表单,并打开一个对象来管理捕获变量和帧就绪事件。 Alpha版本可在此处获取: