一点背景;这个程序最初是为了与USB摄像头配合使用而设计的 - 但是由于摄像机需要的位置和计算机的位置之间的设置,切换到通过网络运行的摄像机更有意义。现在我正在尝试转换程序以实现这一目标,但到目前为止我的努力都遇到了糟糕的结果。我也在OpenCV forums上问了同样的问题。帮我监视我的邻居! (当然,这是他们的许可!):D
我正在使用:
我正在尝试通过OpenCV访问DLink相机的视频源。
我可以通过浏览器的IP地址访问相机,没有任何问题。 Unfourtunately;我的计划不太合作。尝试访问摄像机时,程序会给出OpenCV生成的错误:
警告:打开文件时出错(../../ modules / highgui / src / cap_ffmpeg_impl.hpp:529)
我尝试的所有内容都会发生此错误,但不会以某种方式生成更多问题。
供参考 - 第529行OpenCV的cap_ffmpeg_impl.hpp中的代码如下:
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'我可以将其缩小到第38行:“cv_cap_IP.open(videoFeedAddress);”
我为videoFeedAddress变量输入的值似乎没有得到不同的结果。我发现THIS网站列出了许多可能连接到它的地址。由于列表中没有任何地方存在7100&amp;考虑到安装标记为“DCS-7010L”,我使用了DCS-7010L列表旁边的地址。当试图访问相机时,大部分都可以通过浏览器到达,确认它们到达相机 - 但是当我在videoFeedAddress变量中使用它们时,它们似乎不会影响结果。
我尝试过很多有或没有用户名:密码,端口号(554)以及最后的。.mjpg(格式)变体。
我四处搜索并发现了许多不同的“可能”答案 - 但它们似乎都不适合我。他们中的一些确实给了我包含上述用户名:密码等内容的想法,但它似乎没有什么区别。当然,可能的组合数量当然相当大 - 所以我当然没有尝试过所有这些组合(这里有更多的方向值得赞赏)。以下是我发现的一些链接:
感谢您阅读此内容。我意识到我在问一个有点具体的问题 - 尽管我很感激您对OpenCV&amp; amp;网络摄像机甚至相关主题。
TLDR: 网络摄像头和OpenCV没有合作。我不确定是否 这是我用来将程序导向相机或地址的地址 命令我正在使用 - 但我做的调整似乎没有改善 超出我已经做过的结果!现在,我的邻居将无人看管!
答案 0 :(得分:1)
有很多方法可以获取视频。尽管ffmpeg最方便,但并不是唯一的方法。要诊断ffmpeg是否能够读取流,您应该使用独立的ffmpeg / ffplay来尝试打开该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,mux=raw,dst=127.0.0.1:9080/frame.mjpg}"
之后使用http://127.0.0.1:9080/frame.mjpg
使用opencv VideoCapture抓取帧。这只需要你有一个转码器程序,可以将传入的流转换为mjpeg。
您也可以通过编程方式直接使用vlc api。下面的代码使用vlc来抓取帧。编译的相关信息
码
#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;
}