Немного контекста; Эта программа изначально была разработана для работы с USB-камерами, но из-за установки между тем, где камеры должны находиться, и тем, где находится компьютер, имеет смысл переключиться на камеры, работающие по сети. Сейчас я пытаюсь преобразовать программу для достижения этой цели, но мои усилия пока что дали плохие результаты. Я также задал этот же вопрос на Форумы OpenCV. Помоги мне шпионить за соседями! (Это с их разрешения, конечно!): D
Я использую:
Я пытаюсь получить доступ к видео с камеры DLink через OpenCV.
Я могу получить доступ к камере через ее IP-адрес с помощью браузера без каких-либо проблем. Unfourtunately; моя программа менее кооперативна При попытке получить доступ к камере программа выдает ошибку, сгенерированную OpenCV:
предупреждение: ошибка при открытии файла (../../modules/highgui/src/cap_ffmpeg_impl.hpp:529)
Эта ошибка возникает практически со всем, что я пытаюсь, но это не дает Больше проблемы.
Для справки — код в cap_ffmpeg_impl.hpp OpenCV вокруг строки 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 на этот компьютер, так что это не должно быть проблемой.
Это отредактированная версия, которую я пытался использовать в соответствии с рекомендацией Себастьяна Шмитца:
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, похоже, не дает другого результата. я нашел ЭТОТ сайт, который перечисляет несколько возможных адресов для подключения к нему. Так как нигде в списке нет 7100 & учитывая, что установка помечена как «DCS-7010L», я использовал адреса, найденные рядом со списками DCS-7010L. При попытке доступа к камере к большинству из них можно получить доступ через браузер, подтверждая, что они достигают камеры — но, похоже, они не влияют на результат, когда я использую их в переменной videoFeedAddress.
Я пробовал многие из них как с именем пользователя, так и без него: пароль, номер порта (554) и варианты? .Mjpg (формат) в конце.
Я искал вокруг и наткнулся на несколько разных «возможных» ответов, но ни один из них, похоже, не работает для меня. Некоторые из них дали мне идею включить вышеупомянутое имя пользователя: пароль и т. Д., Но, похоже, это не имеет значения. Конечно, число возможных комбинаций, конечно, довольно велико, поэтому я, конечно, не пробовал все из них (здесь хотелось бы получить больше информации). Вот некоторые из ссылок, которые я нашел:
Спасибо, что прочитали это далеко. Я понимаю, что задаю несколько конкретный вопрос — хотя я был бы признателен за любые советы, которые вы можете придумать в отношении OpenCV & сетевые камеры или даже связанные темы.
TLDR: Сетевая камера и OpenCV не сотрудничают. Я не уверен, если
это адрес, который я использую, чтобы направить программу на камеру или
Я использую команду — но никакая настройка, которую я делаю, кажется, не улучшает
результат за то, что я уже сделал! Теперь мои соседи останутся без присмотра!
Есть несколько способов получить видео. ffmpeg — не единственный способ, хотя он наиболее удобен. Чтобы определить, способен ли ffmpeg читать поток, вы должны использовать автономный ffmpeg / ffplay, чтобы попытаться открыть URL-адрес. Если он может открываться напрямую, это могут быть незначительные вещи, такие как форматирование URL, например, двойная косая черта (rtsp://IPADDRESS:554/live1.sdp
вместо rtsp://IPADDRESS:554//live1.sdp
). Если он не может открыть его напрямую, ему могут потребоваться дополнительные ключи командной строки, чтобы он работал. Тогда вам нужно будет изменить реализацию openfv ffmpeg @ line 529, чтобы передать опции avformat_open_input
, Это может потребовать немного доработки, прежде чем вы сможете получить работающую программу.
Вы также можете проверить, обеспечивает ли камера поток http mjpeg, обратившись к ее руководству. У меня нет камеры, которую вы используете. Так что я не могу сильно помочь в этом.
В качестве альтернативы, у меня есть два предложения ниже, которые могут помочь вам начать работу относительно быстро, так как вы упомянули, что vlc работает.
я предполагаю, что вы можете по крайней мере открыть URL-адрес mjpeg с вашей существующей комбинацией opencv / ffmpeg. поскольку vlc работает, просто используйте vlc для перекодирования видео в mjpeg, например
vlc.exe --ignore-config -I dummy rtsp://admin:[email protected] --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:[email protected]";
//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;
}