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
Related
I am working on a OCR project and I am in the training phase, so the goal is for my program to detect the characters as objects in an image and allow them to be classified.
The problem is that I cannot get it with the Ñ because it is formed by two objects (the N and the stick).
Do you know if there is any way to get it classified as a single object?
Here is the program:
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/ml/ml.hpp>
#include<iostream>
#include<vector>
// global variables
const int MIN_CONTOUR_AREA = 30;
const int RESIZED_IMAGE_WIDTH = 20;
const int RESIZED_IMAGE_HEIGHT = 30;
//////////////////////////////////////
int main() {
cv::Mat imgTrainingNumbers; // input image
cv::Mat imgGrayscale; //
cv::Mat imgBlurred; // declare various images
cv::Mat imgThresh; //
cv::Mat imgThreshCopy; //
std::vector<std::vector<cv::Point> > ptContours; // declare contours vector
std::vector<cv::Vec4i> v4iHierarchy; // declare contours hierarchy
cv::Mat matClassificationInts; // these are our training classifications, note we will have to perform some conversions before writing to file later
// these are our training images, due to the data types that the KNN object KNearest requires, we have to declare a single Mat,
// then append to it as though it's a vector, also we will have to perform some conversions before writing to file later
cv::Mat matTrainingImagesAsFlattenedFloats;
// possible chars we are interested in are digits 0 through 9 and capital letters A through Z, put these in vector intValidChars
std::vector<int> intValidChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'};
imgTrainingNumbers = cv::imread("caracteres_prueba.png"); // read in training numbers image
if (imgTrainingNumbers.empty()) { // if unable to open image
std::cout << "error: image not read from file\n\n"; // show error message on command line
return(0); // and exit program
}
cv::cvtColor(imgTrainingNumbers, imgGrayscale, CV_BGR2GRAY); // convert to grayscale
cv::GaussianBlur(imgGrayscale, // input image
imgBlurred, // output image
cv::Size(5, 5), // smoothing window width and height in pixels
0); // sigma value, determines how much the image will be blurred, zero makes function choose the sigma value
// filter image from grayscale to black and white
cv::adaptiveThreshold(imgBlurred, // input image
imgThresh, // output image
255, // make pixels that pass the threshold full white
cv::ADAPTIVE_THRESH_GAUSSIAN_C, // use gaussian rather than mean, seems to give better results
cv::THRESH_BINARY_INV, // invert so foreground will be white, background will be black
11, // size of a pixel neighborhood used to calculate threshold value
2); // constant subtracted from the mean or weighted mean
cv::imshow("imgThresh", imgThresh); // show threshold image for reference
imgThreshCopy = imgThresh.clone(); // make a copy of the thresh image, this in necessary b/c findContours modifies the image
cv::findContours(imgThreshCopy, // input image, make sure to use a copy since the function will modify this image in the course of finding contours
ptContours, // output contours
v4iHierarchy, // output hierarchy
cv::RETR_EXTERNAL, // retrieve the outermost contours only
cv::CHAIN_APPROX_SIMPLE); // compress horizontal, vertical, and diagonal segments and leave only their end points
for (int i = 0; i < ptContours.size(); i++) { // for each contour
if (cv::contourArea(ptContours[i]) > MIN_CONTOUR_AREA) { // if contour is big enough to consider
cv::Rect boundingRect = cv::boundingRect(ptContours[i]); // get the bounding rect
cv::rectangle(imgTrainingNumbers, boundingRect, cv::Scalar(0, 0, 255), 2); // draw red rectangle around each contour as we ask user for input
cv::Mat matROI = imgThresh(boundingRect); // get ROI image of bounding rect
cv::Mat matROIResized;
cv::resize(matROI, matROIResized, cv::Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT)); // resize image, this will be more consistent for recognition and storage
cv::imshow("matROI", matROI); // show ROI image for reference
cv::imshow("matROIResized", matROIResized); // show resized ROI image for reference
cv::imshow("imgTrainingNumbers", imgTrainingNumbers); // show training numbers image, this will now have red rectangles drawn on it
int intChar = cv::waitKey(0); // get key press
if (intChar == 27) { // if esc key was pressed
return(0); // exit program
}
else if (std::find(intValidChars.begin(), intValidChars.end(), intChar) != intValidChars.end()) { // else if the char is in the list of chars we are looking for . . .
matClassificationInts.push_back(intChar); // append classification char to integer list of chars
cv::Mat matImageFloat; // now add the training image (some conversion is necessary first) . . .
matROIResized.convertTo(matImageFloat, CV_32FC1); // convert Mat to float
cv::Mat matImageFlattenedFloat = matImageFloat.reshape(1, 1); // flatten
matTrainingImagesAsFlattenedFloats.push_back(matImageFlattenedFloat); // add to Mat as though it was a vector, this is necessary due to the
// data types that KNearest.train accepts
} // end if
} // end if
} // end for
std::cout << "training complete\n\n";
// save classifications to file ///////////////////////////////////////////////////////
cv::FileStorage fsClassifications("classifications.xml", cv::FileStorage::WRITE); // open the classifications file
if (fsClassifications.isOpened() == false) { // if the file was not opened successfully
std::cout << "error, unable to open training classifications file, exiting program\n\n"; // show error message
return(0); // and exit program
}
fsClassifications << "classifications" << matClassificationInts; // write classifications into classifications section of classifications file
fsClassifications.release(); // close the classifications file
// save training images to file ///////////////////////////////////////////////////////
cv::FileStorage fsTrainingImages("images.xml", cv::FileStorage::WRITE); // open the training images file
if (fsTrainingImages.isOpened() == false) { // if the file was not opened successfully
std::cout << "error, unable to open training images file, exiting program\n\n"; // show error message
return(0); // and exit program
}
fsTrainingImages << "images" << matTrainingImagesAsFlattenedFloats; // write training images into images section of images file
fsTrainingImages.release(); // close the training images file
return(0);
}
first you have an error in
int intChar = cv::waitKey(0);
it must be
char intChar = cv::waitKey(0);
try it and if ther are error tell me
I am using OpenCV 3 and Visual Studio.
The issue here is that I am unable to save video for any particular resolution other than default full camera resolution.
There is no error, but video file doesn't grow. It stays at 5.54kb.
Here is my code:
#include"opencv2\opencv.hpp"
using namespace cv;
using namespace std;
VideoCapture cap_cam1(0);
double Width = cap_cam1.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap_cam1.get(CV_CAP_PROP_FRAME_HEIGHT);
cv::Size frameSize(static_cast<int>(Width), static_cast<int>(Height));
string videoFileName = "D://current.avi";
VideoWriter cam1_write(videoFileName, CV_FOURCC('D', 'I', 'V', '3'), 10.0, frameSize, true);
Mat image;
int main()
{
while (true)
{
cap_cam1 >> image;
resize(image, image, Size(320, 240));
imshow("image", image);
cam1_write.write(image);
if (waitKey(33) == 27)break;
}
}
If I remove the resize function, then file size grows and frames are added.
I also tried adding below lines after VideoWriter definition
cap_cam1.set(CV_CAP_PROP_FRAME_WIDTH, 240);
cap_cam1.set(CAP_PROP_FRAME_HEIGHT,320);
I also tried changing resolution at VideoWriter definition, after everything file size remains at 5.54kb.
How to record video at custom resolution?
you are using
double Width = cap_cam1.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap_cam1.get(CV_CAP_PROP_FRAME_HEIGHT);
cv::Size frameSize(static_cast<int>(Width), static_cast<int>(Height));
VideoWriter cam1_write(videoFileName, CV_FOURCC('D', 'I', 'V', '3'), 10.0, frameSize, true);
which means you want to write a video with the VideoCapture image size.
Here you have to change to
cv::Size targetSize = cv::Size(320,240);
VideoWriter cam1_write(videoFileName, CV_FOURCC('D', 'I', 'V', '3'), 10.0, targetSize, true);
now in your loop use
resize(image, image, targetSize);
That means you have to decide what kind of output image size you want to have when creating the VideoWriter. That's because typical codecs assume constant (known) image resolution.
For setting resolution you have some typo:
cap_cam1.set(CV_CAP_PROP_FRAME_WIDTH, 240);
cap_cam1.set(CAP_PROP_FRAME_HEIGHT,320);
this would mean a resolution of cv::Size(240,320), so your code might work if you changed the order there to cv::Size(320,240). See comment of #MBo
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'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!