c++ - OpenCV:如何从以太网摄像头捕获帧

标签 c++ opencv ethernet ip-camera

我之前对 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),但它说“找不到页面”。这是什么意思?

最佳答案

您可以使用 genIcam API 执行此操作。 genIcam 是相机(USB、GigE、CameraLink 等)的通用接口(interface)。它由多个模块组成,但我们将专注于 GenTL(传输层)。您可以阅读有关 GenTL 文档的更多信息 HERE .我建议使用 Basler API 或 Baumer API,它们是 GenTL 消费者(生产者和消费者在 GenTL 文档中进行了描述)。我使用了 Baumer API,但两者都应该可以工作。
注意:我使用的是堡盟 HXG20 单声道。
需要下载和安装的东西

  • Visual Studios 社区版(我使用的是 2015 LINK)
  • 堡盟 GAPI SDK,LINK
  • openCV(这里是为 C++ 构建 openCV 3 的 youtube 教程)HERE

  • 带相机浏览器的测试相机
    最好在 Camera Explorer 程序中验证您的网络接口(interface)卡 (NIC) 和相机是否正常工作和播放。您可能需要在 NIC 上启用 Jumbo Packets。您也可以使用 IPconfig 程序(DHCP 或静态 IP)配置摄像机 IP。
    设置视觉工作室
    堡盟 GAPI SDK 程序员指南(第 4 章)中介绍了设置环境变量和配置 Visual Studios,位于以下目录中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 窗口中显示图像流
    最简单的入门方法是使用堡盟 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 行结束。直接在 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 窗口打开,显示相机图像!
    表示赞许,满意,胜利!!!!
    THUMBS UP FOR MORE UP VOTES!!!!!

    关于c++ - OpenCV:如何从以太网摄像头捕获帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11009452/

    相关文章:

    c++ - 无法使用 strcpy 对命令行参数进行排序

    c++ - 如何用 C++ 编写 'pass reference by value' 包装器?

    opencv - 逆透视映射 -> 何时不失真?

    algorithm - 如何在此图中找到三个六边形的交点?

    node.js - 在不同的机器上运行客户端和服务器

    c++ - 有人可以解释参数 void(*pfn)(void*) 吗?

    C++链表节点存储通用对象

    c++ - dip::EuclideanSkeleton不起作用(未处理的异常)

    vhdl - 并行 Crc-32 计算 以太网 10GE MAC

    macos - 为什么在 Mac OS X 上 Wi-Fi 像以太网一样被称为 en0?