my goal is to capture a frame from a rtmp stream every second, and process it using OpenCV. I'm using FFmpeg version N-71899-g6ef3426 and OpenCV 2.4.9 with the Java interface (but I'm first experimenting with Python).
For the moment, I can only take the simple and dirty solution, which is to capture images using FFmpeg, store them in disk, and then read those images from my OpenCV program. This is the FFmpeg command I'm using:
ffmpeg -i "rtmp://antena3fms35livefs.fplive.net:1935/antena3fms35live-live/stream-lasexta_1 live=1" -r 1 capImage%03d.jpg
This is currently working for me, at least with this concrete rtmp source. Then I would need to read those images from my OpenCV program in a proper way. I have not actually implemented this part, because I'm trying to find a better solution.
I think the ideal way would be to capture the rtmp frames directly from OpenCV, but I cannot find the way to do it. This is the code in Python I'm using:
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)
Instead of read() function, I'm also trying with grab() and retrieve() functions without any good result. The read() function is being executed every time, but no "img" or "err" is received.
Is there any other way to do it? or maybe there is no way to get frames directly from OpenCV 2.4.9 from a stream like this?
I've read OpenCV uses FFmpeg to do this kind of tasks, but as you can see, in my case FFmpeg is able to get frames from the stream while OpenCV is not.
In the case I could not find the way to get the frames directly from OpenCV, my next idea is to pipe somehow, FFmpeg output to OpenCV, which seems harder to implement.
Any idea,
thank you!
UPDATE 1:
I'm in Windows 8.1. Since I was running the python script from Eclipse PyDev, this time I run it from cmd instead, and I'm getting the following warning:
warning: Error opening file (../../modules/highgui/src/cap_ffmpeg_impl.hpp:545)
This warning means, as far as I could read, that either the file-path is wrong, or either the codec is not supported. Now, the question is the same. Is OpenCV not capable of getting the frames from this source?
Actually I have spent more that one day to figure out how to solve this issue. Finally I have solved this problem with the help of this link.
Here is client side code.
#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;
}
}
Note: In this case I have created a android application to get real time video and send it to rtmp server wowza which is deployed in PC.So that is where I created this c++ implementation for real time video processing.
python -c "import cv2; print(cv2.getBuildInformation())"
check build opencv with ffmpeg。If it is correct, your code should be fine。
If not, rebuild opencv with ffmpeg。
Under osx
brew install opencv --with-ffmpeg
Related
I have a problem seemingly caused by OpenCV 3.xx - the problem does not manifest in OpenCV 2.xx
The issue is reading video files. I've set my code up as follows:
>#include <opencv2\opencv.hpp>
>#include <opencv2\core\core.hpp>
>#include <opencv2\highgui\highgui.hpp>
>#include <opencv2\imgproc\imgproc.hpp>
>#include <opencv2\features2d\features2d.hpp>
>int main()
> cv::VideoCapture cap;
> cv::Mat frame;
> if(!cap.open("Myfile.avi"))
> std::cout << "Open failed" << std::endl;
> else
> cap.read(frame);
>
> cv::imshow("Frame", frame);
> cv::waitKey(5000);
> return 0;
Now the problem is when the code gets to "cap.read(frame)" I get a "vector subscript is out of range" error with OpenCV 3.40 and this does not happen with my build of OpenCV 2.4.9. The format of the file is in avi, its not some weird codec, and clearly it works in previous versions of OpenCV.
I've tried other OpenCV 3.xx builds and I get the same or similar problems with simply reading a file in.
My question is twofold:
How do I get OpenCV 3.xx to work with reading video files (or do I need to regress to 2.xx?)
Why has the major revision change completely screwed up video file reading? That doesn't make any sense for a computer vision API.
As a guess it will be something to do with the FFMPEG implementation because various searches have turned up other people having issues with this.
Any help is much appreciated.
Thanks
I've managed to resolve it myself, it turns out that in OpenCV 3.xx I have to force the VideoCapture::open to use the FFMPEG library by doing this:
>cap.open("Myfile.avi", cv::CAP_FFMPEG)
where the latter parameter is the flags to identify which VideoCapture API backend to use. The list can be found here for any one else interested:
https://docs.opencv.org/3.3.0/d4/d15/group__videoio__flags__base.html
I'm trying to work with Opencv CUDA module, specially refer to cv::cuda::log function.
First, I'll give to details Opencv compilation.
I compiled Opencv with WITH_CUDA flag on, took the libs and dlls from the compilation, however I copied the headers files from the downloaded opencv folder, since the compilation folder does't include headers by default.
I wonder, whether is this the right thing to do ?
Second, I tried to use the cv::cuda:: function.
I include the cuda.hpp header
#include "opencv2/core/cuda.hpp"
cv::cuda::GpuMat source, dest;
GpuMat compiles great for me, However I don't know which file should I include in order to work with the log function. when I write the following line
cv::cuda::log(source, dest);
I kept on getting the error message:
error: C2039: log in not a member of cv::cuda
Windows 7, Visual studio 2013, Opencv 3.0.0, platform: 64 bit, CUDA toolkit 6.5
Third, I'd like to know about Opencv CUDA implementation, does it utilize npp functionality? Opencv vs npp, which one is better to use ?
I could easly write my code using npp, however I'd like to know the opencv CUDA module.
Thanks
After couple days of searching, I'd like to share my knowledge
First thing I was doing wrong, was taking the headers from Opencv compilation, the right thing to do is taking the header from all the Opencv modules (each module individually).
Second, After Opencv compilation with CUDA flag everything worked great.
Third, Several opencv CUDA functions does utilize NPP
Forth, Use github
This code should work for OpenCV 3.1:
#include <opencv2/opencv.hpp>
#include <opencv2/cudaarithm.hpp>
int main()
{
cv::Mat img = cv::imread("img.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat img_32f;
img.convertTo(img_32f, CV_32F);
//To avoid log(0) that is undefined
img_32f += 1.0f;
cv::cuda::GpuMat gpuImg, gpuImgLog;
gpuImg.upload(img_32f);
cv::cuda::log(gpuImg, gpuImgLog);
cv::Mat imgLog, imgLog_32f;
gpuImgLog.download(imgLog_32f);
double min, max;
cv::minMaxLoc(imgLog_32f, &min, &max);
imgLog_32f.convertTo(imgLog, CV_8U, 255.0/(max-min), -255.0*min/(max-min));
cv::imshow("img", img);
cv::imshow("imgLog", imgLog);
cv::waitKey(0);
return 0;
}
I'm using cmake to build my project with opencv. There are two sub-projects, A and B, under the top directory. A has no opencv function while B uses VideoCapture to get image from webcam. There is no problem at first.
However, after I add the code from B to A, B can still capture image from webcam, but A cannot do the same thing, the error is below:
HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV
VIDIOC_STREAMON: Inappropriate ioctl for device
It is strange, and I find that VideoCapture cannot get image in A, the code is below
VideoCapture cam;
cam.open(0);
if(!cam.isOpened()){
cout << "Failed to open webcam" << endl;
return false;
}
Mat Image;
cam >> Image;
if(Image.empty())
cout<<"Image empty"<<endl;
"Image empty" is always in console, which means it just cannot capture the image at all!!
I followed some suggestions such as install "v4l2ucp", but there is no folder under "/usr/lib/" named "libv4l", so LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so dose not work.
I will very appreciate it if someone could give me some help to solve the problem in project A.
The file might not necessarily be there. Try find / -name "*v4l1compat.so*" 2>/dev/null or find / -name "*libv4l*" 2>/dev/null. It should succeed since your project B captures frames just fine. Then try to export found file to LD_PRELOAD.
If it won't succeed - check out your libv4l installation.
And make sure you trying to open() the correct camera which is not already in use.
It had to happen, I'm stuck in the last phase of my project, when I want to use my code which works like a charm on my webcam, on an IP camera. The URL works perfectly in my browser, but nothing comes out with OpenCV...
Here is my code:
#include <opencv/highgui.h>
using namespace cv;
int main(int argc, char *argv[])
{
Mat frame;
namedWindow("video", 1);
VideoCapture cap("http://192.168.1.99:99/videostream.cgi?resolution=32&rate=0&user=admin&pwd=password&.mjpg");
while ( cap.isOpened() )
{
cap >> frame;
if(frame.empty()) break;
imshow("video", frame);
if(waitKey(30) >= 0) break;
}
return 0;
}
And the compiler settings :
//Added to the .pro file of QtCreator
INCLUDEPATH += C:\\OpenCV243\\release\\include
LIBS += -LC:\\OpenCV243\\release\\lib \
-lopencv_core243.dll \
-lopencv_highgui243.dll
I've tested opening a .avi file with the same code and it works... But a public IP camera URL like http://66.184.211.231/mjpg/video.mjpg doesn't ! What's the matter then ?
Removed by edit: I had considered FFMPEG to be an issue, but v2.4.3. has built-in FFMPEG support and .avi files work although I don't have any FFMPEG library installed (care to explain?)
Thanks in advance,
Regards,
Mister Mystère
Solved it by copying opencv_ffmpeg.dll from the build\x86\mingw\bin folder of the sources and pasting it next to built DLLs (bin folder accessible through PATH): I have no idea why, but the opencv_ffmpeg_64.dll had been produced instead.
Since you can connect and grab frames from a web camera I think that your library is set up correctly and you should be able to connect to IP cameras. I believe that the issue is with the supplied URL address of the camera.
Try logging into the camera and disable its password protection. Remove login and password fields from the URL, so it'll be something like "http://192.168.1.99:99/videostream.cgi?resolution=32&.mjpg". Also, you can log into the camera and check it's resolution. I noticed you have resolution=32 but I think it should be something like resolution=704x480.
Hope this helps.
Recently I migrated to OpenCV 2.4.3 from OpenCV 2.4.1.
My program which worked well with 2.4.1 version now encounters problem with 2.4.3.
The problem is related to VideoCapture that can not open my video file.
I saw a similar problem while searching the internet, but I couldn't find a proper solution for this. Here is my sample code:
VideoCapture video(argv[1]);
while(video.grab())
{
video.retrieve(imgFrame);
imshow("Video",ImgFrame);
waitKey(1);
}
It's worth mentioning that capturing video from webcam device works well, but I want to grab stream from file.
I'm using QT Creator 5 and I compiled OpenCV with MinGW. I'm using Windows.
I tried several different video formats and I rebuilt OpenCV with and without ffmpeg, but the problem still persists.
Any idea how to solve the problem?
Try this:
VideoCapture video(argv[1]);
int delay = 1000.0/video.get(CV_CAP_PROP_FPS);
while(1)
{
if ( !video.read(ImgFrame)) break;
imshow("Video",ImgFrame);
waitKey(delay);
}
In my experience with OpenCV I struggled using IP cams until my mentor discovered how to get them to work, don't forget to plug your IP address in otherwise it won't work!
import cv2
import numpy as np
import urllib.request
# Sets up the webcam and connects to it and initalizes a variable we use for it
stream=urllib.request.urlopen('http://xx.x.x.xx/mjpg/video.mjpg')
bytes=b''
while True:
# Takes frames from the camera that we can use
bytes+=stream.read(16384)
a = bytes.find(b'\xff\xd8')
b = bytes.find(b'\xff\xd9')
if a!=-1 and b!=-1:
jpg = bytes[a:b+2]
bytes= bytes[b+2:]
frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
img = frame[0:400, 0:640] # Camera dimensions [0:WIDTH, 0:HEIGHT]
# Displays the final product
cv2.imshow('frame',frame)
cv2.imshow('img',img)
# Hit esc to kill
if cv2.waitKey(1) ==27:
exit(0)