OpenCV и сетевые камеры -или- Как шпионить за соседями?


Немного контекста; Эта программа изначально была разработана для работы с USB-камерами, но из-за установки между тем, где камеры должны находиться, и тем, где находится компьютер, имеет смысл переключиться на камеры, работающие по сети. Сейчас я пытаюсь преобразовать программу для достижения этой цели, но мои усилия пока что дали плохие результаты. Я также задал этот же вопрос на Форумы OpenCV. Помоги мне шпионить за соседями! (Это с их разрешения, конечно!): D


Я использую:

  • OpenCV v2.4.6.0
  • C ++
  • Облачная камера D-Link 7100 (Установщик DCS-7010L, согласно инструкции.)

Я пытаюсь получить доступ к видео с камеры 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 (формат) в конце.

Я искал вокруг и наткнулся на несколько разных «возможных» ответов, но ни один из них, похоже, не работает для меня. Некоторые из них дали мне идею включить вышеупомянутое имя пользователя: пароль и т. Д., Но, похоже, это не имеет значения. Конечно, число возможных комбинаций, конечно, довольно велико, поэтому я, конечно, не пробовал все из них (здесь хотелось бы получить больше информации). Вот некоторые из ссылок, которые я нашел:

  1. это это одна из первых конфигураций, в которой был мой код. Никаких кубиков.
  2. это говорят о файлах, а не о камерах. В нем также упоминаются кодеки — но я бы не смог посмотреть его в веб-браузере, если бы это было проблемой, верно? (Поправьте меня, если я здесь не прав …)
  3. это один имеет неправильный код ошибки / указывает на неправильную строку кода!
  4. это один упоминает компиляцию OpenCV с поддержкой ffmpeg — но я считаю, что 2.4.6.0 уже поставляется с этим, все готово и готово! В остальном это не так уж отличается от того, что я уже пробовал.
  5. Сейчас ЭТОТ один, кажется, очень похож на то, что у меня есть, но единственное предложенное решение не очень помогает, так как я уже нашел список соединений. Я не верю, что это дубликат, потому что согласно ЭТОТ Мета-обсуждение У меня было намного больше информации, и поэтому я не чувствовал себя комфортно, принимая чужой вопрос — особенно если мне нужно добавить даже больше информация позже.

Спасибо, что прочитали это далеко. Я понимаю, что задаю несколько конкретный вопрос — хотя я был бы признателен за любые советы, которые вы можете придумать в отношении OpenCV & сетевые камеры или даже связанные темы.


TLDR: Сетевая камера и OpenCV не сотрудничают. Я не уверен, если
это адрес, который я использую, чтобы направить программу на камеру или
Я использую команду — но никакая настройка, которую я делаю, кажется, не улучшает
результат за то, что я уже сделал! Теперь мои соседи останутся без присмотра!

5

Решение

Есть несколько способов получить видео. 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 работает.

способ 1

я предполагаю, что вы можете по крайней мере открыть 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,m‌​ux=raw,dst=127.0.0.1:9080/frame.mjpg}"

после этого использования http://127.0.0.1:9080/frame.mjpg чтобы захватить кадр, используя OpenCV VideoCapture. это просто требует наличия транскодерной программы, которая может конвертировать входящий поток в mjpeg.

способ 2

Вы также можете напрямую использовать 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:[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;
}
1

Другие решения


По вопросам рекламы [email protected]