How to write *.mp4 video with OpenCV-C++? - c++

My name is Toan. Currently, I'm using OpenCV-C++ to write video *.mp4 type. I can write video .avi type but It's take a lot of storage. About 1Mb/1s with 640x480 resolution and 15 FPS. I'm using iMX6UL-EVK board(Linux).
I built without error but no output .mp4 file. And in python code (OpenCV-Python), this board can write .mp4 video with "mp4v".
I tried with "mp4v", "xvid", "divx", "h264", "x264" but not working. So what can I do now? Or may you show me others type of video which not take much of storage ?
This is my code:
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
cout << "Built with OpenCV " << CV_VERSION << endl;
Mat image;
Mat src;
VideoCapture capture;
capture.open(2);
capture >> src;
bool isColor = (src.type() == CV_8UC3);
VideoWriter writer;
int codec = VideoWriter::fourcc('M', 'P', '4', 'V');
double fps = 15.0;
string filename = "live.mp4";
Size sizeFrame(640,480);
writer.open(filename, codec, fps, sizeFrame, isColor);
cout << "Started writing video... " << endl;
for (int i = 0 ; i < 60 ; i ++)
{
capture >> image;
Mat xframe;
resize(image,xframe,sizeFrame);
writer.write(xframe);
// imshow("Sample", image);
// char c = (char)waitKey(1);
// if(c == 27) break;
}
cout << "Write complete !" << endl;
capture.release();
writer.release();
return 0;
}
Thank you so much,
Toan

VideoWriter::fourcc('a', 'v', 'c', '1')
work fine for me to write mp4 file.

Related

Is it possible to crop raw video before extracting all the frames using OpenCV and C++?

I want to crop a certain area of my raw video before extracting the frames. I don't want to use external cropping video software because I need the video to be raw for processing. Is it possible to crop a certain area before extraction ? I read about ROI for images, is it possible for video too ?
Here's my extraction code that's already working :
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <sstream>
using namespace cv;
using namespace std;
int c = 0;
string int2str(int &);
int main(int argc, char **argv) {
string s;
VideoCapture cap("test_video.mov");
if (!cap.isOpened())
{
cout << "Cannot open the video file" << endl;
return -1;
}
double fps = cap.get(CV_CAP_PROP_FPS);
cout << "Frame per seconds : " << fps << endl;
namedWindow("MyVideo", CV_WINDOW_NORMAL);
resizeWindow("MyVideo", 600, 600);
while (1)
{
Mat frame;
Mat Gray_frame;
bool bSuccess = cap.read(frame);
if (!bSuccess)
{
cout << "Cannot read the frame from video file" << endl;
break;
}
s = int2str(c);
//cout<<("%d\n",frame )<<endl;
c++;
imshow("MyVideo", frame);
imwrite("frame" + s + ".jpg", frame);
if (waitKey(30) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
string int2str(int &i) {
string s;
stringstream ss(s);
ss << i;
return ss.str();
}
Still need to crop the video, any advice ?

Extract all video frame from mp4 video using OpenCV and C++

I'm following a tutorial to extract video frames. I've read this question, it doesn't work, also queationfrom Open CV Answer, but the solution is for capturing current frame. I have a 120fps video and want to extract all of them. Here's my code
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <sstream>
using namespace cv;
using namespace std;
int c = 0;
string int2str(int &);
int main(int argc, char **argv) {
string s;
VideoCapture cap("test.mp4"); // video
if (!cap.isOpened())
{
cout << "Cannot open the video file" << endl;
return -1;
}
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
namedWindow("MyVideo", CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
while (1)
{
Mat frame;
Mat Gray_frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess)
{
cout << "Cannot read the frame from video file" << endl;
break;
}
s = int2str(c);
//cout<<("%d\n",frame )<<endl;
c++;
imshow("MyVideo", frame); //show the frame in "MyVideo" window
imwrite("ig" + s + ".jpg", frame);
if (waitKey(30) == 27) //esc key
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
//int to string function
string int2str(int &i) {
string s;
stringstream ss(s);
ss << i;
return ss.str();
}
My problem is, I have a minute video at 120fps. I expected to be able to extract 120 frames. But the extraction went wrong, the video last for 1 minute but I got more than 200 frames stored in my folder. Did I do something wrong in my code ?

Grayscale video file corrupted in OpenCV3.3, MJPG codec

My setup is using a logitech c920, raspberry pi 3, and the latest opencv 3.3. I am showing in screen and writing in a file the camera stream. The only processing I am doing is converting video to grayscale. In the screen all show good, but the file is corrupted (see https://i.stack.imgur.com/QHrQb.png).
Noticeable, the video is well recorded in XVID, and also in MJPG if the original color image is selected instead.
UPDATE: I tested the same code in os-x and the same error happens, also with opencv3.3
Any advice welcome :)
This is the code:
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main() {
int FPS = 10;
int nframes;
double start, now;
VideoCapture vcap(0);
if(!vcap.isOpened()) {
cout << "Error opening video stream or file" << endl;
return 0;
}
vcap.set(CV_CAP_PROP_FOURCC,CV_FOURCC('M','J','P','G'));
int frame_width = vcap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
VideoWriter video("out.avi",CV_FOURCC('M','J','P','G'), FPS, Size(frame_width,frame_height), false);
namedWindow("Main",CV_WINDOW_AUTOSIZE); //create a window called
// Start time
start = (double)getTickCount();
for(;;) {
Mat frame, gray;
vcap >> frame;
cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
video << gray;
imshow("Main", gray);
char c = (char)waitKey(2);
if( c == 27 ) break;
++nframes;
if (nframes==100) {
now = (double)getTickCount();
cout << "FPS: " << ++nframes/(now-start)*getTickFrequency() << endl;
start = now;
nframes = 0;
}
}
video.release();
return 0;
}

videowriter function doesnt save the file with opencv-3.0.0

I am working with GigaE Camera and it is a grayscale image and I want to record the videos. So I have tried initially with webcam and below is my code:
#include "opencv2\highgui\highgui.hpp"
#include "iostream"
#include "opencv2/opencv.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/videoio/videoio.hpp"
#include<string>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap(0);
VideoWriter writer;
if (!cap.isOpened())
{
cout << "not opened" << endl;
return -1;
}
char* windowName = "Webcam Feed";
namedWindow(windowName, CV_WINDOW_AUTOSIZE);
string filename = "D:\videos\myVideo12.avi";
int fcc = CV_FOURCC('M', 'J', 'P', 'J');
int fps = 30;
Size frameSize(cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT));
bool isColor = false;
writer = VideoWriter(filename, fcc, fps, frameSize, isColor);
if (!writer.isOpened())
{
cout << "Error not opened" << endl;
getchar();
return -1;
}
while (1)
{
Mat frame;
bool bSuccess = cap.read(frame);
if (!bSuccess)
{
cout << "ERROR READING FRAME FROM CAMERA FEED" << endl;
break;
}
cvtColor(frame, frame, CV_BGR2GRAY);
writer.write(frame);
imshow(windowName, frame);
return 0;
}
There is no video created and I don't get any error too. But it works fine with OpenCV-2.4.10.
Most likely, the video is not written because of the codec. OpenCV tends to stay silent in case of encoding (and many other) problems. Try setting fcc to -1 to choose from a list of available codecs.
Solved! The error is in the giving the filename path where I used '\' instead of '/'. The codecs are MPEG or DIV3 for grayscale images.

How to install codecs for opencv?

I am trying to write a program that captures video from a webcam using this code:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat frame;
VideoCapture cap(1);
char key;
String outputName = "output.avi";
VideoWriter outputVideo;
Size size = Size(cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT));
outputVideo.open(outputName, CV_FOURCC('D', 'I', 'V', 'X'), cap.get(CV_CAP_PROP_FPS), size, true);
if (!outputVideo.isOpened())
{
cout << "Could not open the output video for write: " << outputName << endl;
return -1;
}
cout << "size " << size.width << " x " << size.height << endl;
namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display.
cap.set(CV_CAP_PROP_EXPOSURE, -8);
while (true){
bool success = cap.read(frame);
if (!success){
cout << "Cannot read frame from file" << endl;
return -2;
}
outputVideo.write(frame);
imshow("Display window", frame);
key = waitKey(1);
if (key == ' '){
cout << "Video ended due to key stroke" << endl;
return 1;
}
}
return 0;
}
The program doesn't seem to be able to open outputVideo since it always returns -1. I thought that I might not have the codec divx installed, but I have installed it from k-lite codec pack and divx and it still does not work.
Could anybody please tell me how to install codecs such that opencv recognizes them?
I am using OpenCV 2.4.10 on Windows 7 with Visual studio 2013.