OpenCV 不会从 RTMP 源捕获帧,而 FFmpeg 会
OpenCV won't capture frames from a RTMP source, while FFmpeg does
我的目标是每秒从 rtmp 流中捕获一个帧,并使用 OpenCV 对其进行处理。我正在使用 FFmpeg 版本 N-71899-g6ef3426 和带有 Java 接口的 OpenCV 2.4.9(但我首先尝试使用 Python)。
目前,我只能采取简单而肮脏的解决方案,即使用 FFmpeg 捕获图像,将它们存储在磁盘中,然后从我的 OpenCV 程序中读取这些图像。这是我正在使用的 FFmpeg 命令:
ffmpeg -i "rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1" -r 1 capImage%03d.jpg
这目前对我有用,至少对于这个具体的 rtmp 源是这样。然后我需要以正确的方式从我的 OpenCV 程序中读取这些图像。这部分我还没有实际实现,因为我正在寻找更好的解决方案。
我认为理想的方法是直接从 OpenCV 捕获 rtmp 帧,但我找不到实现它的方法。这是 Python 中的代码,我正在使用:
cv2.namedWindow("camCapture", cv2.CV_WINDOW_AUTOSIZE)
cap = cv2.VideoCapture()
cap.open('"rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1"')
if not cap.open:
print "Not open"
while (True):
err,img = cap.read()
if img and img.shape != (0,0):
cv2.imwrite("img1", img)
cv2.imshow("camCapture", img)
if err:
print err
break
cv2.waitKey(30)
我还尝试使用 grab() 和 retrieve() 函数,而不是 read() 函数,但没有任何好的结果。每次都在执行 read() 函数,但没有收到 "img" 或 "err"。
还有其他方法吗?或者也许没有办法从这样的流中直接从 OpenCV 2.4.9 获取帧?
我读过 OpenCV 使用 FFmpeg 来执行此类任务,但如您所见,在我的例子中,FFmpeg 能够从流中获取帧,而 OpenCV 则不能。
在我找不到直接从 OpenCV 获取帧的方法的情况下,我的下一个想法是以某种方式通过管道将 FFmpeg 输出到 OpenCV,这似乎更难实现。
任何想法,
谢谢!
更新 1:
我在 Windows 8.1。由于我是从 Eclipse PyDev 运行 宁 python 脚本,这次我从 cmd 运行 它,我收到以下警告:
warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:545)
据我所知,此警告意味着文件路径错误或不支持编解码器。现在,问题是一样的。 OpenCV 不能从这个来源获取帧吗?
实际上我花了一天多的时间来弄清楚如何解决这个问题。最后我在this link的帮助下解决了这个问题。
这是客户端代码。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int, char**) {
cv::VideoCapture vcap;
cv::Mat image;
const std::string videoStreamAddress = "rtmp://192.168.173.1:1935/live/test.flv";
if(!vcap.open(videoStreamAddress)) {
std::cout << "Error opening video stream or file" << std::endl;
return -1;
}
cv::namedWindow("Output Window");
cv::Mat edges;
for(;;) {
if(!vcap.read(image)) {
std::cout << "No frame" << std::endl;
cv::waitKey();
}
cv::imshow("Output Window", image);
if(cv::waitKey(1) >= 0) break;
}
}
注意:在这种情况下,我创建了一个 android 应用程序来获取实时视频并将其发送到部署在我创建的 PC.So 中的 rtmp 服务器 wowza这个用于实时视频处理的 C++ 实现。
python -c "import cv2; print(cv2.getBuildInformation())"
检查用ffmpeg构建opencv。如果是正确的,你的代码应该没问题。
如果没有,用ffmpeg重建opencv。
在 osx
下
brew install opencv --with-ffmpeg
我的目标是每秒从 rtmp 流中捕获一个帧,并使用 OpenCV 对其进行处理。我正在使用 FFmpeg 版本 N-71899-g6ef3426 和带有 Java 接口的 OpenCV 2.4.9(但我首先尝试使用 Python)。 目前,我只能采取简单而肮脏的解决方案,即使用 FFmpeg 捕获图像,将它们存储在磁盘中,然后从我的 OpenCV 程序中读取这些图像。这是我正在使用的 FFmpeg 命令:
ffmpeg -i "rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1" -r 1 capImage%03d.jpg
这目前对我有用,至少对于这个具体的 rtmp 源是这样。然后我需要以正确的方式从我的 OpenCV 程序中读取这些图像。这部分我还没有实际实现,因为我正在寻找更好的解决方案。
我认为理想的方法是直接从 OpenCV 捕获 rtmp 帧,但我找不到实现它的方法。这是 Python 中的代码,我正在使用:
cv2.namedWindow("camCapture", cv2.CV_WINDOW_AUTOSIZE)
cap = cv2.VideoCapture()
cap.open('"rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1"')
if not cap.open:
print "Not open"
while (True):
err,img = cap.read()
if img and img.shape != (0,0):
cv2.imwrite("img1", img)
cv2.imshow("camCapture", img)
if err:
print err
break
cv2.waitKey(30)
我还尝试使用 grab() 和 retrieve() 函数,而不是 read() 函数,但没有任何好的结果。每次都在执行 read() 函数,但没有收到 "img" 或 "err"。 还有其他方法吗?或者也许没有办法从这样的流中直接从 OpenCV 2.4.9 获取帧?
我读过 OpenCV 使用 FFmpeg 来执行此类任务,但如您所见,在我的例子中,FFmpeg 能够从流中获取帧,而 OpenCV 则不能。
在我找不到直接从 OpenCV 获取帧的方法的情况下,我的下一个想法是以某种方式通过管道将 FFmpeg 输出到 OpenCV,这似乎更难实现。
任何想法, 谢谢!
更新 1: 我在 Windows 8.1。由于我是从 Eclipse PyDev 运行 宁 python 脚本,这次我从 cmd 运行 它,我收到以下警告:
warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:545)
据我所知,此警告意味着文件路径错误或不支持编解码器。现在,问题是一样的。 OpenCV 不能从这个来源获取帧吗?
实际上我花了一天多的时间来弄清楚如何解决这个问题。最后我在this link的帮助下解决了这个问题。 这是客户端代码。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int, char**) {
cv::VideoCapture vcap;
cv::Mat image;
const std::string videoStreamAddress = "rtmp://192.168.173.1:1935/live/test.flv";
if(!vcap.open(videoStreamAddress)) {
std::cout << "Error opening video stream or file" << std::endl;
return -1;
}
cv::namedWindow("Output Window");
cv::Mat edges;
for(;;) {
if(!vcap.read(image)) {
std::cout << "No frame" << std::endl;
cv::waitKey();
}
cv::imshow("Output Window", image);
if(cv::waitKey(1) >= 0) break;
}
}
注意:在这种情况下,我创建了一个 android 应用程序来获取实时视频并将其发送到部署在我创建的 PC.So 中的 rtmp 服务器 wowza这个用于实时视频处理的 C++ 实现。
python -c "import cv2; print(cv2.getBuildInformation())"
检查用ffmpeg构建opencv。如果是正确的,你的代码应该没问题。
如果没有,用ffmpeg重建opencv。 在 osx
下brew install opencv --with-ffmpeg