I am trying to write the frame into my local machine in mp4 format. The frame is read from an existing
mp4 file. After running the following code, I was able to see the VideoOutput.mp4 file, but it is corrupted for some reason. Anyone knows why?
VideoCapture capture("videoSample.mp4");
if (capture.isOpened())
{
while (true)
{
capture >> frame;
}
VideoWriter video("somepath\\videoOutput.mp4", VideoWriter::fourcc('m', 'p', '4', 'v'), 10, Size(win_width, win_width * 2));
video.write(frame);
}
Related
I'm using OpenCV with ffmpeg support to read a RTSP stream coming from an IP camera and then to write the frames to a video. The problem is that the frame size is 2816x2816 at 20 fps i.e. there's a lot of data coming in.
I noticed that there was a significant delay in the stream, so I set the buffer size of the cv::VideoCapture object to 1, because I thought that the frames might just get stuck in the buffer instead of being grabbed and processed. This however just caused for frames to be dropped instead.
My next move was to experiment a bit with the frame size/fps and the encoding of the video that I'm writing. All of those things helped to improve the situation, but in the long run I still have to use a frame size of 2816x2816 and support up to 20 fps, so I can't set it lower sadly.
That's where my question comes in: given the fact that the camera stream is going to be either h264 or h265, which one would be read faster by the cv::VideoCapture object? And how should I encode the video I'm writing in order to minimize the time spent decoding/encoding frames?
That's the code I'm using for reference:
using namespace cv;
int main(int argc, char** argv)
{
VideoCapture cap;
cap.set(CAP_PROP_BUFFERSIZE, 1); // internal buffer will now store only 1 frames
if (!cap.open("rtsp://admin:admin#1.1.1.1:554/stream")) {
return -1;
}
VideoWriter videoWr;
Mat frame;
cap >> frame;
//int x264 = cv::VideoWriter::fourcc('x', '2', '6', '4'); //I was trying different options
int x264 = cv::VideoWriter::fourcc('M', 'J', 'P', 'G');
videoWr = cv::VideoWriter("test_video.avi", 0, 0, 20, frame.size(), true);
namedWindow("test", WINDOW_NORMAL);
cv::resizeWindow("test", 1024, 768);
for (;;)
{
cap >> frame;
if (frame.empty()) break; // end of video stream
imshow("test", frame);
if (waitKey(10) == 27) break;
videoWr << frame;
}
return 0;
}
I'm attempting to utilize OpenCV, C++, on my windows 10 system to record the screen as part of a larger program I am writing. I need the ability to record the display and save the recording for later review.
I was able to find this link on stackoverflow
How to capture the desktop in OpenCV (ie. turn a bitmap into a Mat)?
User john ktejik created a function that in essence completed exactly what I am looking to accomplish, short of saving the stream to file.
Now what I have always done in the past was once I've opened a connection to my webcam or a video file, I could simply create a VideoWriter Object and write the individual frames to file. I have attempted to do just that utilizing John's function to act as a video source.
int main (int argc, char **argv)
{
HWND hwndDesktop = GetDesktopWindow ();
int key = 0;
int frame_width = 1920;
int frame_height = 1080;
VideoWriter video ("screenCap.avi", CV_FOURCC ('M', 'J', 'P', 'G'), 15, Size (frame_width, frame_height));
while (key != 27)
{
Mat src = hwnd2mat (hwndDesktop);
video.write (src);
imshow ("Screen Capture", src);
key = waitKey (27);
}
video.release ();
destroyAllWindows ();
return 0;
}
What I'm seeing as the output, is the file labeled "screenCap.avi", however the file is empty of video. The file saves as 16KB storage space.
John's function is on point, as it displays the frames just fine via imshow(), but doesn't seem to allow me to save them.
So over the weekend I played with the software some more. And as I really don't have a firm grasp on it, I figured that there had to be a problem with settings between the screen capture and the file writer.
So I started looking at each of the lines in John's function. I came across
src.create(height, width, CV_8UC4);
It seems that the Mat object is being created as with 4 color channels. Did a bit more digging and I found a couple references that point to Videowriter expecting 3 channels.
So a simple change was to convert the output of Johns function from 4 channels to 3 channels. This fixed the problem and I can now write the frames to file.
int main (int argc, char **argv)
{
HWND hwndDesktop = GetDesktopWindow ();
int key = 0;
int frame_width = 1920;
int frame_height = 1080;
VideoWriter video ("screenCap.avi", CV_FOURCC ('M', 'J', 'P', 'G'), 15, Size
(frame_width, frame_height));
while (key != 27)
{
Mat src = hwnd2mat (hwndDesktop);
Mat dst;
cvtColor (src, dst, COLOR_BGRA2RGB);
video.write (dst);
imshow ("Screen Capture", dst);
key = waitKey (27);
}
video.release ();
destroyAllWindows ();
return 0;
}
I tried to write a video from a sequence of images created by OpenCV. However I cannot open the videos after writing them. I guess there is a codec issue. I find it extremely difficult where the error exactly comes from. Here is my code:
Size size = Size(vecOfMats[0].rows,vecOfMats[0].cols);
int codec = CV_FOURCC('D', 'I', 'V', 'X');
VideoWriter videoWriter;
videoWriter.open(outputFilename,codec,15.0,size,true);
for(int z=0; z < vecOfMats.size(); z++)
{
videoWriter.write(vecOfMats[z]);
}
videoWriter.release();
I also tried all of these codecs without success (either OpenCv could not find the codec or the video could not be opened):
int codec = CV_FOURCC('P','I','M','1'); // = MPEG-1 codec
int codec = CV_FOURCC('M','J','P','G'); // = motion-jpeg codec - cannot be played by VLC
int codec = CV_FOURCC('M', 'P', '4', '2');// = MPEG-4.2 codec - not found
int codec = CV_FOURCC('D', 'I', 'V', '3');// = MPEG-4.3 codec - not found
int codec = CV_FOURCC('D', 'I', 'V', 'X');// = MPEG-4 codec - cannot be played by VLC
int codec = CV_FOURCC('U', '2', '6', '3');// = H263 codec - must have w/h = 4
int codec = CV_FOURCC('I', '2', '6', '3');// = H263I codec - not found
I even took the codec of a video opened via OpenCV previously (without success):
string filename = "/path/to/the/video/myVideo.avi";
VideoCapture capture(filename);
int ex = static_cast<int>(capture.get(CV_CAP_PROP_FOURCC)); // Get Codec Type- Int form
char EXT[] = {(char)(ex & 0XFF) , (char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24), 0};// Transform from int to char via Bitwise operators
cout<<"Codec: "<<ex<<endl;
VideoWriter videoWriter;
videoWriter.open(outputFilename,ex,15.0,size,true);
I'm not even sure if the problem lies with my OpenCV or my Ubuntu :/.
(I tried to open them using the default video player and vlc)
Since I gave up on writing videos using Opencv I just want to mention how I resolved my problem. After saving every image as a png file, I'm using ffmpeg from linux command line to write the sequence of images as a video.
Pictures are named sequentially like this:
00001.png,
00002.png,
00003.png,
[…]
Then I use this command
ffmpeg -i %5d.png -vcodec mpeg4 test.avi
I am trying to create some video from a set of large raw images that I have.
The code is as follow:
int imageWidth=687;
int imageHeight=916;
int fps=3;
int ex=-1;
CvSize size = cvSize(imageWidth,imageHeight);
VideoWriter outputVideo;
outputVideo.open(MovieOutput, ex, fps, size, true);
if(outputVideo.isOpened())
{
cout << "error opening output video";
}
for(int frameNo=0;frameNo<58;frameNo++)
{
ostringstream outfilename;
outfilename << InputDir<< (frameNo+1)<<".jpg";
rawimages.Read(frameNo);
Mat image=rawimages.ToOpencvImage();
imwrite( outfilename.str(), image );
outputVideo <<image;
imshow("Image", image);
if(waitKey(30) >= 0) break;
}
I can see that images are shown on screen and also different jpg are saved on hard disk.
I can see that the output avi is created, but its size is zero.
What is the problem with this code?
some note:
The output size is very big. Can it generate movie with that size?
To summarize the comments: you pass the second parameter to the VideoWriter open command with a value of -1. This is supposed to open a codec selection dialogue in Windows, but as of OpenCV 2.4.5, the dialogue seems to be bugged - it appears, but I couldn't manage to write to a file afterwards.
Selecting a codec directly works fine and makes more sense in my opinion. More info about this command and available codecs can be found here.
outputVideo.open("example.avi", CV_FOURCC('M','J','P','G'), fps, size, true);
I'm trying to record a video with opencv the frame is 1920*180 with 25 frame/s, my Problem is that when I chose to write the frame unconpressed I don't get a video I get only one picture in avi format!! here my code :
using namespace cv;
int main (){
int key = 0;
Mat frame;
cv::VideoCapture cap(0);
cap>>frame;
cv::VideoWriter record("video.avi",-1, 25, frame.size(), true);
while(key!=27){
cap>>frame;
//cv::VideoWriter record("video.avi",-1, 25, frame.size(), true);
record<<frame;
imshow("",frame);
key=waitKey(1);
}
frame.release();
cv::destroyAllWindows();
return 0 ;
}
I'm use DeckLink SDI card to get the video, and when record the video with Media Express it works ? any Idea