8

我之前编写了 USB 网络摄像头,其唯一目的是从摄像头获取实时帧并显示在窗口中。为此,我使用了 cvCaptureFromCAM,它适用于 USB 相机(参见下面的代码)。

我想知道如何从千兆以太网摄像机捕获帧?我想我需要使用一些 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),但显示“找不到页面”。这是什么意思?

4

3 回答 3

10

您可以使用 genIcam API 做到这一点。genIcam 是相机的通用接口(USB、GigE、CameraLink 等)。它由多个模块组成,但我们将专注于 GenTL(传输层)。您可以在此处阅读有关 GenTL 文档的更多信息。我建议使用作为 GenTL 消费者的 Basler API 或 Baumer API(生产者和消费者在 GenTL 文档中进行了描述)。我使用了 Baumer API,但两者都应该可以工作。

注意:我使用的是 Baumer HXG20 单声道。

下载和安装的东西

  1. Visual Studios 社区版(我使用 2015 LINK
  2. 堡盟 GAPI SDK,链接
  3. openCV(这里是为 c++ 构建 openCV 3 的 youtube 教程)这里

使用 CAMERA EXPLORER 测试相机

最好在 Camera Explorer 程序中验证您的网络接口卡 (NIC) 和相机是否正常工作和玩耍。您可能需要在 NIC 上启用巨型数据包。您也可以使用 IPconfig 程序配置摄像机 IP(DHCP 或静态 IP)。

设置视觉工作室

堡盟 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/C++ > 常规 > 附加包含目录 =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 窗口中显示图像流

最简单的入门方法是使用 Baumer 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语句检查像素格式是“单色”(灰度)还是彩色。在原始文件中,它从第 619 行开始,到 692 行结束。紧接在ifandelse语句大括号之后,在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 文档)。

您可以参考其他示例来调整相机参数。

现在,一旦您构建和编译,您应该打开一个显示相机图像的 openCV 窗口!

表示赞许,满意,胜利!!!!

为更多的投票点赞!!!!!!

于 2016-12-28T20:14:14.667 回答
3

如果没有运行网络服务器,您将无法访问相机上的图像(检查其文档)。尝试在命令提示符下键入:

telnet 192.169.2.3 80

如果 telnet 超时,您的摄像机未在默认端口 80 上运行服务器。

另请参阅此问题:C++ 代码从 IP / 以太网摄像机 (AXIS Cam) 捕获图像

于 2013-04-15T12:30:31.297 回答
1

添加到标记 jay的答案(我可以确认使用 Baumer-GAPI2 2.8.1 和 VC10 编译器和 Baumer TXG06 相机在 Win32 程序中的 Win7x64 上工作)。如果相机设置为抓取Mono8并且您打算抓取相同格式的图像,CV_8UC1那么在005_PixelTransformation.cpp示例中您可以完全避免创建BGAPI2::Image* pTransformImageandBGAPI2::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 上发挥同样的作用。

传入图像

于 2017-11-06T03:19:40.660 回答