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
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 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);
}
I want to store video after processing it with reduced size.Currently i am using the same size as the input video.I am working on open CV with c++.
If you aim to change video resolution then use resize() function to a matrix that stores your image:
Mat source, destination;
IplImage new_img;
int fps = 30;
// Apply resize
resize(source, destination, Size(640, 360), 1, 1, 1);
// Create writer
CvVideoWriter *new_writer = cvCreateVideoWriter("video.mp4",CV_FOURCC('M', 'P', '4', '2'), fps, destination.size(), 3);
new_img = destination.operator IplImage();
// 1-if image written or 0 if failed
int ret = cvWriteFrame(new_writer, (const IplImage*)&new_img);
printf("Written?: %d\n", ret);
// And finally release writer
cvReleaseVideoWriter(&new_writer);
If you aim to reduce video size on a disk then try to create VideoWriter with various codecs such as:
CV_FOURCC('P','I','M','1') = MPEG-1 codec
CV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
I'm following a OpenCV book's tutorial and the following code doesn't work:
#include <iostream>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace std;
int main() {
string arg1 = "new.mov";
string arg2 = "mov.mov";
CvCapture* capture = 0;
capture = cvCreateFileCapture(arg1.c_str());
if(!capture){
return -1;
}
IplImage *bgr_frame=cvQueryFrame(capture);
double fps = cvGetCaptureProperty (
capture,
CV_CAP_PROP_FPS
);
CvSize size = cvSize(
(int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH)
);
CvVideoWriter* writer = cvCreateVideoWriter(
arg2.c_str(),
CV_FOURCC('N', 'T', 'S', 'C'),
fps,
size
);
IplImage* logpolar_frame = cvCreateImage(
size,
IPL_DEPTH_8U,
3
);
while((bgr_frame=cvQueryFrame(capture)) != NULL){
cvLogPolar(
bgr_frame, logpolar_frame,
cvPoint2D32f(bgr_frame->width/2, bgr_frame->height/2),
40,
CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS
);
cvWriteFrame(writer, logpolar_frame);
}
cvReleaseVideoWriter(&writer);
cvReleaseImage(&logpolar_frame);
cvReleaseCapture(&capture);
return 0;
}
It doesn't give me an error when I run the code - instead the program outputs to the console:
WARNING: Could not create empty movie file container.
Followed by 100 or so lines of:
Didn't successfully update movie file.
What does this error (or whatever it's called) mean and what's causing it?
I don't know if this helps, but it used to give me an error about the codec (which in the book was MJPG) so I changed CV_FOURCC('M', 'J', 'P', 'G') to CV_FOURCC('N', 'T', 'S', 'C').
Try to change CV_FOURCC('N', 'T', 'S', 'C') to CV_FOURCC('D', 'I', 'V', 'X'). Here's manual for you.
Possible codecs:
CV_FOURCC('P','I','M','1') = MPEG-1 codec
CV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
NTSC isn't a valid codec fourcc so no video writer is being created
Came looking for solution to same message. In my case I use Mac/OSX and I DID use CV_FOURCC('M', 'J', 'P', 'G'). It came out that it failed when output file ended with ".mp4" and worked with ".avi".
I Have following source code to detect BLOB and i am using MS 2008 , OpenVC 2.1
#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
/*You may change the values of the sthreshold and hlower and hupper to get different results....*/
const int sthreshold=210;
const double hlower=178;
const double hupper=3;
int main(int argc, char* argv[]) {
int i,j,k;//for iterations
int height,width,step,channels;/*HSV means the frame after color conversion*/
int heightmono,widthmono,stepmono,channelsmono;/*mono means the frame which has the monochrome image*/
const char string1[]="monoimg.avi";/*This is the name of the video which would be the outcome of the blob detection program..*/
uchar *data,*datamono;
i=j=k=0;
IplImage *frame = 0;
int key = 0;/*Initializing the capture from the video...*/
CvCapture* capture = cvCreateFileCapture( "partofvideo3.avi" );
double fps = cvGetCaptureProperty (/*getting the capture properties......the frame rate..*/
capture,CV_CAP_PROP_FPS);
CvSize size = cvSize(
(int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT)
);
CvVideoWriter *writer=cvCreateVideoWriter(string1, CV_FOURCC('D', 'I', 'V', 'X') ,fps,size) ;
if(writer !=NULL)
printf("Loaded\n");
else
printf("Not Loaded\n");
/* always check */
if (!capture) {
fprintf (stderr, "Cannot open video file!\n");
return(1);
}
height = frame->height;
width = frame->width;
step = frame->widthStep;
channels = frame->nChannels;
data = (uchar *)frame->imageData;
cvNamedWindow("monoimage", CV_WINDOW_AUTOSIZE);
cvNamedWindow("original frame", CV_WINDOW_AUTOSIZE);
for (;;) {/*keep looping till we are out of frames...*/
if (!cvGrabFrame(capture)) {
break;
}
frame = cvRetrieveFrame(capture);
IplImage *colimgbot = cvCreateImage( cvGetSize(frame), 8, 3 );
IplImage *monoimgbot = cvCreateImage( cvGetSize(frame), 8, 1 );
cvCvtColor(frame,frame,CV_RGB2HSV);
for(i=0;i< (height);i++)
{
for(j=0;j<(width);j++)
{
if((data[(height-i)*step+j*channels]<=hlower) && (data[(height-i)*step+j*channels]>=hupper))
{
if((data[(height-i)*step+j*(channels)+1])>sthreshold)
/*"height-i" because if we use only "i" we were getting vertically inverted result...hence reinverting the same
would do the required....*/
datamono[i*stepmono+j*channelsmono]=255;
else
datamono[i*stepmono+j*channelsmono]=0;}
else datamono[i*stepmono+j*channelsmono]=0;
}
}
cvErode(monoimgbot,monoimgbot,0,14);
cvDilate( monoimgbot,monoimgbot,0,15);
cvWriteFrame(writer, monoimgbot);
cvShowImage("original frame", frame);
cvShowImage("monoimage", monoimgbot);
if( (cvWaitKey(10) & 255) == 27 ) break;
}
cvReleaseVideoWriter(&writer) ;
cvDestroyWindow("monoimage");
cvReleaseCapture(&capture);
return 0;
}
when i run the program i am getting following run time error
when following line encounters
CvVideoWriter* writer=cvCreateVideoWriter(string1, CV_FOURCC( ‘D’,'I’,'V’,'X’),fps,size) ;
Output #0 , avi , to ‘monoimg.avi’ :
Stream #0.0: Video mgeg4, yuv420p, q=2-31, 90k tbn
[mpeg4 # 0x37e5c0] framerate not set
OpenCV Error: Bad Argument (Could not open codec ‘mpeg 4′:Unspecified Error) in unknown function , file
C:\User\VP\ocv\opencv\src\highgui\cvcap_ffmpeg.cpp, line 1306
First off getCaptureProperties kinda sucks at actually getting anything, so you should check that fps actually has what you think it does. Some codecs can't encode at certain framerates so try just explicitly setting fps to 30 and see if it works.
otherwise you are missing the mpeg 4 codec as it says. I'd recommend:
1.) download some codecs and try again.
http://www.divx.com/en/software/divx-plus/codec-pack probably has what you're looking for.
2.) you can change the
CvVideoWriter *writer=cvCreateVideoWriter(string1, CV_FOURCC('D', 'I', 'V', 'X') ,fps,size) ;
line to use some other codec. I played around with a couple of codecs and put the amount of time for encoding a 7 min video on my system.
(\P,\I,\M,\1) ;= MPEG-1 codec (112913.386195 msecs) (104 MB)
(\M,\J,\P,\G) ;= motion-jpeg codec (crashed)
(\M,\P,\4,\2) ;= MPEG-4.2 codec (107184.186774 msecs) (82 MB)
(\D,\I,\V,\3) ;= MPEG-4.3 codec (118308.933328 msecs) (83 MB)
(\D,\I,\V,\X) ;= MPEG-4 codec (99037.738131 msecs) (85 MB)
(\U,\2,\6,\3) ;= H263 codec (101141.993551 msecs) (89 MB)
(\I,\2,\6,\3) ;= H263I codec (crashed)
(\F,\L,\V,\1) ;= FLV1 codec (104307.567802 msecs) (93 MB)
In particular I would recommend trying the FLV1 codec as I've had a lot of luck with that. So in summary try:
CvVideoWriter *writer=cvCreateVideoWriter(string1, CV_FOURCC('F', 'L', 'V', '1') ,fps,size) ;
Good luck!