C语言、OpenCV——通过IP访问摄像头JPG图像

6

我已经阅读了许多关于在OpenCV 2.3.1中通过IP流传输图像的线程,但我仍然无法使我的程序正常工作。

我从https://market.android.com/details?id=com.pas.webcam&hl=en下载了Android上的IP摄像头,并最近学习了OpenCV,以从我的Android手机相机中检索图像。

它内置的说明说,手机相机的图像可以位于http://the.phone.ip.address:8080/shot.jpg。我已经从浏览器打开它几次,并且它总是看起来很好。我还手动构建了支持FFmpeg的OpenCV。

到目前为止,我尝试过:

CvCapture* webcam = cvCaptureFromFile("http://192.168.1.220:8080/shot.jpg");

但是它返回了 NULL 并输出。
[image2 @ 0xd701e0]Could not find codec parameters (Video: mjpeg, yuv420p)

我也尝试将http替换为rtsp,但仍然不起作用。我还尝试将url替换为其他一些图像url(一个直接链接到Google Images的随机图像,以及本地主机上的一个图像),但它总是崩溃并出现段错误。

这是我的完整源代码。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>

int main(int argc, char* argv[])
{ 
  CvCapture* webcam = cvCaptureFromFile("http://192.168.1.220:8080/shot.jpg");
  if(!webcam)
    {
      fprintf(stderr, "cannot open webcam\n");
      return 1;
    }

  IplImage* img = cvQueryFrame(webcam);
  if(!img)
    {
      fprintf(stderr, "cannot get image\n");
      return 1;
    }

  cvNamedWindow("test", CV_WINDOW_AUTOSIZE);
  cvShowImage("test", img);
  cvWaitKey(0);
  cvReleaseImage(&img);
  /**/ cvReleaseCapture(&webcam); /**/
  cvDestroyWindow("test");
  return 0;
}

OpenCV真的可以通过网络读取图像吗?还是我错过了什么?

你得到答案了吗? - wolvorinePk
我尝试过 rtsp://192.168.1.104:8080/videofeed 但是也失败了。 - krzych
3个回答

4

虽然我不是专门熟悉 openCV,但是在查看文档后,有两点需要注意:

首先,你并没有处理真正的视频流:你的安卓应用只是提供当前的 JPEG 抓取,并且需要不断地重新采样。因为这是图像而不是视频,所以应该使用 cvLoadImage() 来处理。

第二,你传递的是 URL 而不是文件名。你需要一种方法使用 HTTP 将图像获取到本地文件中,然后再使用 openCV 打开它。

我建议你从浏览器中保存 JPEG 文件的快照,然后尝试让代码与该文件配合工作。一旦从本地文件中使其工作正常,尝试添加 HTTP 获取操作。


还有应用程序提供的视频流怎么办?例如,这个问题https://dev59.com/sXRB5IYBdhLWcg3wH0SW解释了它是可能的。 - krzych

2
虽然如果支持这个功能会非常棒,但它似乎并不被支持。请注意,操作系统处理文件和URL的打开方式是不同的(显然),因此默认情况下不支持这种方式 - 你不能用fopen()打开一个URL。如果OpenCV特别支持它,那么这是可能的,但我有一些证据表明他们不支持: 以下是你可以做的:
  • 以其他方式下载图像 - 可以通过使用system()调用wget,或使用库将文件下载到内存中等方式。
  • 至少有一种方法称可以使用Processing的loadImage()从URL加载图像。

那么为什么它能识别出它是MJPEG格式的,而且还是某种特定的格式呢?我提供了一些限制条件,因为我想通过任何可能的方式访问这个应用程序的视频源。但我的问题编辑被拒绝了。所以当OpenCV与ffmpeg编译时,应该能够处理这个应用程序的视频源。 - krzych
这很令人惊讶。可能只是默认设置的问题,因为我所读的所有内容都表明OpenCV无法处理从互联网读取的数据。虽然我怀疑这不会解决你的问题,但你应该使用VideoCapture来读取视频,对吧? - Dan
阅读有时是不够的。我不想解释OpenCV中如何完成,但你可以在源代码中看到。我知道这应该是可能的,但不知道足够使其工作。个人而言,我不喜欢仅通过搜索某些内容并呈现结果来回答问题,尤其是当问题是这样的时。 - krzych
1
@krzych,“无法找到编解码器参数”是一个非常误导性的信息。这并不意味着它将您的文件检测为mjpeg,只是“文件名”以“.jpeg”结尾。尝试将URL更改为http://somenonsenseurl.com/rubbish.jpeg”,看看是否收到相同的消息。请参见:https://dev59.com/p2865IYBdhLWcg3wl_s3 - Roddy
@krzych,所以你已经做了研究表明OpenCV的代码支持这个,但你不想分享它。然而,你希望有人为你做这件事。很奇怪。 - Prof. Falken

0

进一步查看Roddy的答案,让我成功地解决了问题。

不幸的是,这不是一个好的、仅限于Windows的解决方案。但是从这个应用程序获取jpg的唯一方法是以某种方式获取http。有许多库可以帮助,例如libcurl、boost::asio。我使用了urlmon.lib来解决我的问题:

#inlcude <opencv2\opencv.hpp>
#include <UrlMon.h>
#include <tchar.h>
#pragma comment(lib,"urlmon.lib")

int main()
{
        for(;;)
        {
              HRESULT hr = URLDownloadToFile(NULL,_T("http://192.168.1.104:8080/shot.jpg"),
                                             _T("D:/test.jpg"),0,NULL);
              IplImage *test = cvLoadImage("D:/test.jpg");
              cvShowImage("test",test);
              cvWaitKey(30);
        }
}

这个应用程序也可以像我在评论中建议的那样流式传输mjpg。OpenCV VideoStream似乎有选项可以从中读取,如建议的{{link1:从localhost端口(http://192.168.1.1:8080)实时流式传输视频}}和{{link2:使用网络摄像头的OpenCV}}。 我也尝试了这个解决方案,但出现了mp3 header missing错误。我希望有人能提供一些使用此应用程序的视频源的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接