gpt4 book ai didi

c++ - OpenCV 和网络摄像机 - 或者 - 如何监视邻居?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:19 24 4
gpt4 key购买 nike

一些上下文;该程序最初是为与 USB 相机配合使用而构建的 - 但由于需要在相机所在的位置和计算机所在的位置之间进行设置,因此切换到通过网络运行的相机更有意义。现在我正在尝试转换该程序以完成此任务,但迄今为止我的努力结果不佳。我也在 OpenCV forums 上问过同样的问题.帮我监视我的邻居! (当然,这是经过他们的许可!):D

我正在使用:

  • OpenCV v2.4.6.0
  • C++
  • D-Link Cloud Camera 7100(根据说明,安装程序为 DCS-7010L。)


  • 我正在尝试通过 OpenCV 访问 DLink 摄像机的视频源。

    我可以使用浏览器通过它的 IP 地址访问摄像机,没有任何问题。不幸的是;我的程序不太合作。尝试访问相机时,程序会给出 OpenCV 生成的错误:

    warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:529)



    这个错误发生在我尝试的几乎所有不会以某种方式产生更多问题的事情中。

    供引用 - OpenCV 的 cap_ffmpeg_impl.hpp 中第 529 行附近的代码如下:
    522    bool CvCapture_FFMPEG::open( const char* _filename )
    523 {
    524 unsigned i;
    525 bool valid = false;
    526
    527 close();
    528
    529 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
    530 int err = avformat_open_input(&ic, _filename, NULL, NULL);
    531 #else
    532 int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
    533 #endif
    ...
    616 }

    ...我不知道我在看什么。它似乎在寻找 ffmpeg 版本 - 但我已经在那台计算机上安装了最新的 ffmpeg,所以这应该不是问题。

    这是我根据 Sebastian Schmitz 的建议尝试使用的编辑过的版本:
     1    #include <fstream>                            // File input/output
    2 #include <iostream> // cout / cin / etc
    3 #include <windows.h> // Windows API stuff
    4 #include <stdio.h> // More input/output stuff
    5 #include <string> // "Strings" of characters strung together to form words and stuff
    6 #include <cstring> // "Strings" of characters strung together to form words and stuff
    7 #include <streambuf> // For buffering load files
    8 #include <array> // Functions for working with arrays
    9 #include <opencv2/imgproc/imgproc.hpp> // Image Processor
    10 #include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
    11 #include <opencv2/highgui/highgui.hpp> // OpenCV window I/O
    12 #include "opencv2/calib3d/calib3d.hpp"
    13 #include "opencv2/features2d/features2d.hpp"
    14 #include "opencv2/opencv.hpp"
    15 #include "resource.h" // Included for linking the .rc file
    16 #include <conio.h> // For sleep()
    17 #include <chrono> // To get start-time of program.
    18 #include <algorithm> // For looking at whole sets.
    19
    20 #ifdef __BORLANDC__
    21 #pragma argsused
    22 #endif
    23
    24 using namespace std; // Standard operations. Needed for most basic functions.
    25 using namespace std::chrono; // Chrono operations. Needed getting starting time of program.
    26 using namespace cv; // OpenCV operations. Needed for most OpenCV functions.
    27
    28 string videoFeedAddress = "";
    29 VideoCapture videoFeedIP = NULL;
    30 Mat clickPointStorage; //Artifact from original program.
    31
    32 void displayCameraViewTest()
    33 {
    34 VideoCapture cv_cap_IP;
    35 Mat color_img_IP;
    36 int capture;
    37 IplImage* color_img;
    38 cv_cap_IP.open(videoFeedAddress);
    39 Sleep(100);
    40 if(!cv_cap_IP.isOpened())
    41 {
    42 cout << "Video Error: Video input will not work.\n";
    43 cvDestroyWindow("Camera View");
    44 return;
    45 }
    46 clickPointStorage.create(color_img_IP.rows, color_img_IP.cols, CV_8UC3);
    47 clickPointStorage.setTo(Scalar(0, 0, 0));
    48 cvNamedWindow("Camera View", 0); // create window
    49 IplImage* IplClickPointStorage = new IplImage(clickPointStorage);
    50 IplImage* Ipl_IP_Img;
    51
    52 for(;;)
    53 {
    54 cv_cap_IP.read(color_img_IP);
    55 IplClickPointStorage = new IplImage(clickPointStorage);
    56 Ipl_IP_Img = new IplImage(color_img_IP);
    57 cvAdd(Ipl_IP_Img, IplClickPointStorage, color_img);
    58 cvShowImage("Camera View", color_img); // show frame
    59 capture = cvWaitKey(10); // wait 10 ms or for key stroke
    60 if(capture == 27 || capture == 13 || capture == 32){break;} // if ESC, Return, or space; close window.
    61 }
    62 cv_cap_IP.release();
    63 delete Ipl_IP_Img;
    64 delete IplClickPointStorage;
    65 cvDestroyWindow("Camera View");
    66 return;
    67 }
    68
    69 int main()
    70 {
    71 while(1)
    72 {
    73 cout << "Please Enter Video-Feed Address: ";
    74 cin >> videoFeedAddress;
    75 if(videoFeedAddress == "exit"){return 0;}
    76 cout << "\nvideoFeedAddress: " << videoFeedAddress << endl;
    77 displayCameraViewTest();
    78 if(cvWaitKey(10) == 27){return 0;}
    79 }
    80 return 0;
    81 }

    使用添加的 'cout's 我能够将其缩小到第 38 行:“cv_cap_IP.open(videoFeedAddress);”

    我为 videoFeedAddress 变量输入的任何值似乎都没有得到不同的结果。我找到了 THIS列出了许多可能的地址以连接到它的站点。由于列表中的任何地方都不存在 7100 并且考虑到安装标记为“DCS-7010L”,因此我使用了 DCS-7010L 列表旁边的地址。当尝试访问相机时,大多数可以通过浏览器访问,确认它们到达相机 - 但当我在 videoFeedAddress 变量中使用它们时,它们似乎不会影响结果。

    我已经尝试了很多有和没有用户名:密码、端口号 (554) 和 ?.mjpg (格式)最后的变体。

    我四处搜索,发现了许多不同的“可能”答案——但似乎没有一个对我有用。他们中的一些人确实让我想到了包含上述用户名:密码等内容,但似乎并没有什么不同。当然,可能的组合数量肯定相当多——所以我当然没有尝试过所有的组合(这里有更多的方向将不胜感激)。以下是我找到的一些链接:
  • This是我的代码所在的第一个配置之一。没有骰子。
  • This一个是在谈论文件 - 而不是相机。它还提到了编解码器 - 但如果这是问题所在,我将无法在网络浏览器中观看它,对吧? (如果我错了,请纠正我...)
  • This一个有错误的错误代码/指向错误的代码行!
  • This有人提到使用 ffmpeg 支持编译 OpenCV - 但我相信 2.4.6.0 已经准备好了!否则它与我已经尝试过的没有什么不同。
  • 现在 THIS一个似乎与我所拥有的非常相似,但唯一提出的解决方案并没有真正帮助,因为我已经找到了一个连接列表。我不相信这是重复的,因为根据 THIS元讨论 我有更多的信息,所以不喜欢接听别人的问题——尤其是如果我以后需要添加更多信息。

  • 感谢您阅读到这里。我意识到我在问一个有点具体的问题 - 尽管我很感激你能想到的关于 OpenCV 和网络摄像机甚至相关主题的任何建议。

    TLDR: Network Camera and OpenCV are not cooperating. I'm unsure if it's the address I'm using to direct the program to the camera or the command I'm using - but no adjustment I make seems to improve the result beyond what I've already done! Now my neighbors will go unwatched!

    最佳答案

    有多种方法可以获取视频。 ffmpeg 不是唯一的方法,尽管它最方便。要诊断 ffmpeg 是否能够读取流,您应该使用独立的 ffmpeg/ffplay 尝试打开 url。如果能直接打开,可能是url格式的一些小问题,比如双斜线(rtsp://IPADDRESS:554/live1.sdp而不是rtsp://IPADDRESS:554//live1.sdp)。如果它不能直接打开它,它可能需要一些额外的命令行开关才能使其工作。然后,您需要修改 opencv 的 ffmpeg 实现@第 529 行以将选项传递给 avformat_open_input .这可能需要进行相当多的调整,然后才能获得工作程序。

    您还可以通过查阅手册来检查相机是否提供 http mjpeg 流。我没有你正在使用的相机。所以我在这方面帮不上什么忙。

    或者,我在下面有两个建议,由于您提到 vlc 正在运行,它们可能会帮助您相对快速地启动和运行。

    方法一

    我假设您至少可以使用现有的 opencv/ffmpeg 组合打开 mjpeg url。由于 vlc 正在工作,只需使用 vlc 将视频转码为 mjpeg,例如
    vlc.exe --ignore-config -I dummy rtsp://admin:admin@10.10.204.111 --sout=#transcode"{vcodec=MJPG,vb=5000,scale=1,acodec=none}:std{access=http,m‌​ux=raw,dst=127.0.0.1:9080/frame.mjpg}"
    之后使用 http://127.0.0.1:9080/frame.mjpg使用 opencv VideoCapture 抓取帧。这只需要您有一个转码器程序,可以将传入的流转换为 mjpeg。

    方法二

    您也可以直接以编程方式使用 vlc api。以下代码使用 vlc 来抓取帧。编译的相关信息

  • C:\Program Files (x86)\VideoLAN\VLC\sdk\include
  • C:\Program Files (x86)\VideoLAN\VLC\sdk\lib
  • libvlc.lib,libvlccore.lib

  • 代码
    #include "opencv2/highgui/highgui.hpp"
    #include <windows.h>
    #include <vlc/vlc.h>

    using namespace cv;

    struct ctx
    {
    Mat* image;
    HANDLE mutex;
    uchar* pixels;
    };
    bool isRunning=true;

    Size getsize(const char* path)
    {
    libvlc_instance_t *vlcInstance;
    libvlc_media_player_t *mp;
    libvlc_media_t *media;

    const char * const vlc_args[] = {
    "-R",
    "-I", "dummy",
    "--ignore-config",
    "--quiet",

    };
    vlcInstance = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
    media = libvlc_media_new_location(vlcInstance, path);
    mp = libvlc_media_player_new_from_media(media);

    libvlc_media_release(media);
    libvlc_video_set_callbacks(mp, NULL, NULL, NULL, NULL);
    libvlc_video_set_format(mp, "RV24",100,100, 100 * 24 / 8); // pitch = width * BitsPerPixel / 8
    libvlc_media_player_play(mp);

    Sleep(2000);//wait a while so that something get rendered so that size info is available
    unsigned int width=640,height=480;
    libvlc_video_get_size(mp,0,&width,&height);


    if(width==0 || height ==0)
    {
    width=640;
    height=480;
    }
    libvlc_media_player_stop(mp);
    libvlc_release(vlcInstance);
    libvlc_media_player_release(mp);
    return Size(width,height);
    }


    void *lock(void *data, void**p_pixels)
    {
    struct ctx *ctx = (struct ctx*)data;
    WaitForSingleObject(ctx->mutex, INFINITE);
    *p_pixels = ctx->pixels;
    return NULL;

    }

    void display(void *data, void *id){
    (void) data;
    assert(id == NULL);
    }

    void unlock(void *data, void *id, void *const *p_pixels)
    {

    struct ctx *ctx = (struct ctx*)data;
    Mat frame = *ctx->image;
    if(frame.data)
    {
    imshow("frame",frame);
    if(waitKey(1)==27)
    {
    isRunning=false;
    //exit(0);
    }
    }
    ReleaseMutex(ctx->mutex);
    }


    int main( )
    {
    string url="rtsp://admin:admin@10.10.204.111";
    //vlc sdk does not know the video size until it is rendered, so need to play it a bit so that size is known
    Size sz = getsize(url.c_str());

    // VLC pointers
    libvlc_instance_t *vlcInstance;
    libvlc_media_player_t *mp;
    libvlc_media_t *media;

    const char * const vlc_args[] = {
    "-R",
    "-I", "dummy",
    "--ignore-config",
    "--quiet",
    };
    vlcInstance = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
    media = libvlc_media_new_location(vlcInstance, url.c_str());
    mp = libvlc_media_player_new_from_media(media);

    libvlc_media_release(media);

    struct ctx* context = ( struct ctx* )malloc( sizeof( *context ) );
    context->mutex = CreateMutex(NULL, FALSE, NULL);
    context->image = new Mat(sz.height, sz.width, CV_8UC3);
    context->pixels = (unsigned char *)context->image->data;

    libvlc_video_set_callbacks(mp, lock, unlock, display, context);
    libvlc_video_set_format(mp, "RV24", sz.width, sz.height, sz.width * 24 / 8); // pitch = width * BitsPerPixel / 8

    libvlc_media_player_play(mp);
    while(isRunning)
    {
    Sleep(1);
    }

    libvlc_media_player_stop(mp);
    libvlc_release(vlcInstance);
    libvlc_media_player_release(mp);
    free(context);

    return 0;
    }

    关于c++ - OpenCV 和网络摄像机 - 或者 - 如何监视邻居?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23529620/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com