我之前编写过USB网络摄像头,其唯一目的是从摄像头获取实时帧并在窗口中显示。我为此目的使用了cvCaptureFromCAM,它适用于USB Camera(请参阅下面的代码)。
我想知道如何从千兆以太网相机中捕获帧?我想我需要使用一些API从一些默认IP地址捕获帧。有人能指出我正确的方向吗?
我将在Intel i3处理器上的Windows 7上使用C ++和OpenCV。
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
// A Simple Camera Capture Framework
int main() {
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
if ( !capture ) {
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
// Create a window in which the captured images will be presented
cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );
// Show the image captured from the camera in the window and repeat
while ( 1 ) {
// Get one frame
IplImage* frame = cvQueryFrame( capture );
if ( !frame ) {
fprintf( stderr, "ERROR: frame is null...\n" );
getchar();
break;
}
cvShowImage( "mywindow", frame );
// Do not release the frame!
// If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
// remove higher bits using AND operator
if ( (cvWaitKey(10) & 255) == 27 ) break;
}
// Release the capture device housekeeping
cvReleaseCapture( &capture );
cvDestroyWindow( "mywindow" );
return 0;
}
更新
所以现在我可以在供应商提供的软件GUI中显示实时图像。但我仍然希望使用相机的IP地址显示图像(可能还有视频)。
当我知道摄像机的IP地址时,为什么我无法访问摄像机发送的数据(图像)并在浏览器上显示?我尝试在我的浏览器(192.169.2.4)上键入摄像机的IP地址(即192.169.2.3),但它说“找不到页面”。这是什么意思?
答案 0 :(得分:7)
您可以使用genIcam API执行此操作。 genIcam是相机的通用接口(USB,GigE,CameraLink等)。它由多个模块组成,但您最关心的是GenTL(传输层)。您可以阅读有关GenTL文档HERE的更多信息。为了简化流程,我建议使用Basler API或Baumer API,它们是GenTL消费者(生产者和消费者在GenTL文档中有描述)。我使用了堡盟API,但两者都有效。
注意:我正在使用堡盟HXG20单声道相机。
可以下载和安装
使用CAMERA EXPLORER测试相机
最好通过使用Camera Explorer程序检查您的网络接口卡(NIC)和GigE相机是否正常工作并使用相机。您可能需要在NIC上启用Jumbo Packets。您也可以使用IPconfig程序配置摄像机IP。我使用DHCP设置,但您也可以为相机和NIC使用静态IP。
设置可视化工作室
Baumer GAPI SDK程序员指南(第4章)介绍了设置系统环境变量和配置Visual Studio的步骤,该指南位于以下目录中
C:\Program Files\Baumer\Baumer GAPI SDK\Docs\Programmers_Guide
检查您是否具有以下系统变量(如果使用64位版本),或者根据需要创建变量(请参阅程序员指南中的第4.3.1节)。
GENICAM_GENTL64_PATH
C:\Program Files\Baumer\Baumer GAPI SDK\Components\Bin\x64\
在visual Studios中,创建一个新的C ++项目并更新以下属性(请参阅程序员指南中的第4.4.1节)。
C:\Program Files\Baumer\Baumer GAPI SDK\Components\Dev\C++\Inc
C:\Program Files\Baumer\Baumer GAPI SDK\Components\Dev\C++\Lib\x64
bgapi2_genicam.lib
copy "C:\Program Files\Baumer\Baumer GAPI SDK\Components\Bin\x64"\*.* .\
创建.CPP文件以在OPENCV窗口中显示图像流
最简单的入门方法是使用堡盟GAPI SDK中提供的示例代码之一并对其进行修改以添加openCV功能。要使用的示例代码是005_PixelTransformation,它位于此处
C:\Program Files\Baumer\Baumer GAPI SDK\Components\Examples\C++\src\0_Common\005_PixelTransformation
将此.cpp文件复制并粘贴到项目源目录中,并确保可以构建和编译。它应该捕获8个图像,并从每个图像的前6行打印出前6个像素值。
将这些#include
语句添加到.cpp源文件中:
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\video\video.hpp>
在main()
函数
// OPENCV VARIABLE DECLARATIONS
cv::VideoWriter cvVideoCreator; // Create OpenCV video creator
cv::Mat openCvImage; // create an OpenCV image
cv::String videoFileName = "openCvVideo.avi"; // Define video filename
cv::Size frameSize = cv::Size(2048, 1088); // Define video frame size (frame width x height)
cvVideoCreator.open(videoFileName, CV_FOURCC('D', 'I', 'V', 'X'), 20, frameSize, true); // set the codec type and frame rate
在原始的005_PixelTransformation.cpp文件中,第569行有一个for
循环,循环超过8个图像,即for(int i = 0; i < 8; i++)
。我们想要改变它以持续运行。我这样做是通过将其更改为while
循环来说明
while (pDataStream->GetIsGrabbing())
在我们新的while
循环中,有一个if
语句,用于检查Pixel格式是否为“Mono”(灰度)或颜色。在原始文件中,它从第619行开始,到692结束。在if
和else
语句括号关闭之后,在pImage->Release();
语句之前,我们需要添加openCV将图像显示到窗口的部分。添加以下代码行
} // This is the closing brace for the 'else color' statement
// OPEN CV STUFF
openCvImage = cv::Mat(pTransformImage->GetHeight(), pTransformImage->GetWidth(), CV_8U, (int *)pTransformImage->GetBuffer());
// create OpenCV window ----
cv::namedWindow("OpenCV window: Cam", CV_WINDOW_NORMAL);
//display the current image in the window ----
cv::imshow("OpenCV window : Cam", openCvImage);
cv::waitKey(1);
需要注意的一点是openCvImage
对象中的像素格式。我的相机是单声道8位,所以我需要指定CV_8U
。如果您的相机是RGB或10位像素,则需要提供正确的格式(请参阅openCV文档HERE)。
您可以参考调整相机参数的其他示例。
现在一旦你构建和编译,你应该打开一个openCV窗口,显示相机图像!
为了更多人的投票而大吵大闹!!!! (这需要花很多时间才能开始工作,所以请联系我!)
答案 1 :(得分:3)
如果没有运行Web服务器,您将无法访问相机上的图像(检查其doco)。 尝试在命令提示符下键入:
telnet 192.169.2.3 80
如果telnet超时,则相机未在默认端口80上运行服务器。
另请参阅此问题:C++ code Capturing image from IP / Ethernet Cameras (AXIS Cam)
答案 2 :(得分:0)
添加到mark jay的答案(我可以使用堡盟-GAPI2 2.8.1和VC10编译器以及堡盟TXG06摄像机确认在Win32程序中的Win7x64上工作)。如果相机设置为抓取Mono8
并且您打算抓取相同格式CV_8UC1
的图像,那么在005_PixelTransformation.cpp
示例中,您可以避免创建BGAPI2::Image* pTransformImage
和BGAPI2::Image* pImage
一起使用缓冲区内存指针构建cv::Mat
,如下面GigE_cam
类的摘录:
bool GigE_cam::operator>>(cv::Mat& out_mat)
{
bool success(false);
try
{
_p_buffer_filled = _p_data_stream->GetFilledBuffer(static_cast<bo_uint64>(_timeout_ms));
if(_p_buffer_filled != 0)
{
if(_p_buffer_filled->GetIsIncomplete())
{
_p_buffer_filled->QueueBuffer();
}
else
{
if(_p_buffer_filled->GetPixelFormat() == "Mono8")
{
_image_out_buffer = cv::Mat(static_cast<int>(_p_buffer_filled->GetHeight()),
static_cast<int>(_p_buffer_filled->GetWidth()),
CV_8UC1,
static_cast<uchar*>(_p_buffer_filled->GetMemPtr()));
if(_image_out_buffer.data)
{
_image_out_buffer.copyTo(out_mat);
success = true;
}
}
else if(_p_buffer_filled->GetPixelFormat() == "Mono10")
{
// Todo transform to BGR8 etc. not implemented
}
_p_buffer_filled->QueueBuffer(); // Queue buffer after use
}
}
}
catch(BGAPI2::Exceptions::IException& ex)
{
_last_BGAPI2_error_str = ex.GetType();
}
return success;
}
此代码以66.5 fps的速度从相机(776 X 582像素)获取全帧,即使数据表仅声称64.0 fps。我很想知道他们的API在Debian上的行为是否相同。