I’m trying to use OpenCV to write a video file. I have a simple program that loads frames from a video file then accepts to save them
At first the cvCreateVideoWrite always return NULL. I got a answer from your group saying it returns separate images and to try to change the file name to test0001.png, this worked.
But now the cvWriteFrame function always fails, the code is
CString path;
path="d:\\mice\\Test_Day26_2.avi";
CvCapture* capture = cvCaptureFromAVI(path);
IplImage* img = 0;
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 25; // or 30
int frameW = 640; // 744 for firewire cameras
int frameH = 480; // 480 for firewire cameras
writer=cvCreateVideoWriter("d:\\mice\\test0001.png",CV_FOURCC('P','I','M','1'),
fps,cvSize(frameW,frameH),isColor);
if (writer==0)
MessageBox("could not open writter");
int nFrames = 50;
for(int i=0;i<nFrames;i++){
if (!cvGrabFrame(capture))
MessageBox("could not grab frame");
img=cvRetrieveFrame(capture); // retrieve the captured frame
if (img==0)
MessageBox("could not retrive data");
if (!cvWriteFrame(writer,img) )
MessageBox("could not write frame");
}
cvReleaseVideoWriter(&writer);
Try CV_FOURCC('D', 'I', 'V', 'X'), CV_FOURCC('f', 'f', 'd', 's') (with *.avi filename) or CV_FOURCC_DEFAULT (with *.mpg). Video writing is still quite messy in opencv >_>
I've seen many issues with writing video as well in OpenCV. I found intel iYUV format worked well for what I needed.
Was your library built with HAVE_FFMPEG defined?
If it wasn't,you might need to recompile opencv with that option.You should see something like this in the configure step:
...
Video I/O--------------
Use QuickTime no
Use xine no
Use ffmpeg: yes
Use v4l yes
...
If you don't have ffmpeg,you can get it from here.
Related
So I have an archive that is loading the my .wav files into memory and I am trying to play a .WAV from a void* or handle in memory.
II cannot have all the .wav files in the directory and I have a function that is loading them into memory.
Here is some code that I am trying and I have tried many things , but a lot of it doesn't seem to work and I think that SDL libraries are looking for a physical file to load , but I cannot confirm that.
void *MusicTrack;
void Load_andPlay_music(ntrack){
OpenFileFromMPQ( MusicTracks[ntrack], &MusicTrack) // Opens Audio track from MPQ.
Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096);
music = Mix_LoadMUS(MusicTracks[ntrack]);
// I thought that once the file is loaded it might be available as part of $PATH. This is not the case.
Mix_PlayMusic(music, -1);
}
>
If I try this , ....
Mix_PlayMusic(MusicTrack, -1);
I am met with error
'int Mix_PlayMusic(Mix_Music *,int)': cannot convert argument 1 from 'void *' to 'Mix_Music *'
If you have a better solution using SDL2 then I am willing to look at that too.
Thanks.
Use the (oddly undocumented) Mix_LoadMUS_RW() with a SDL_RWops from SDL_RWFromMem().
I figured this out and it works fine
you can simply do something like this.
You of course might have to change the Mix_openAudio params to meet your needs.
void snd_init()
{
printf("SND INIT\n\n");
// Initialize SDL.
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
printf("ERROR : %s\n\n", SDL_GetError());
}
if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096) < 0) {
printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
}
SoundInited = 1;
}
//either some function or something to read the .WAV file into memory and have it gpbuffer point to it.
void * gpbuffer;
void playmusic(){
Mix_Chunk * Music = Mix_QuickLoad_WAV((Uint8* )gpbuffer);
Mix_PlayChannel(2, Music, 0);
}
EDIT I ran into Other problems with this and channels overlapping. So try this out if you need SFX and Music running at the same times.
Mix_OpenAudio(22050, AUDIO_S8, 1, 1024);
SDL_RWops* rw = SDL_RWFromMem(buffer, bytestoread);
Mix_Music* Song = Mix_LoadMUS_RW(rw,1);
Mix_PlayMusic(Song, -1);
I've been writing a program in C# that reads a .mov file. I'm able to parse through the entire thing, ignoring chunks I don't understand, and grabbing relevant info from chunks that I do.
What I'm trying to do is get the FPS from the file, but getting it hasn't been straightforward. I assume because the format can store many movies at different rates.
If someone could point me in the right direction, like which chunks (atoms) should I be looking at? I thought it was stts, but not all .mov files contain that chunk!
I was mistaken. The stts atom is always there, and that is where you get the information to calculate the FPS. The following code hasn't be thoroughly tested, but it did work with all the .mov files I have.
void ReadSTTS(BinaryReader reader)
{
int versionAndFlags = reader.ReadInt32(true);
int nEntries = reader.ReadInt32(true);
int sampleCount = 0;
int sampleDuration = 0;
for (int i = 0; i < nEntries; i++)
{
sampleCount += reader.ReadInt32(true);
sampleDuration += reader.ReadInt32(true);
}
FPS = (float)Math.Round((float)mediaTimeScale / ((float)mediaDuration / (float)sampleCount), 2);
}
mediaTimeScale and mediaDuration both come from the mvhd atom. ReadInt32(true) is an extension that changes the endianness, since I'm reading the .mov on a windows machine.
I'm working with OpenCV 2.4.11 in C on Code::Blocks, in particular through the O'Reilly book Learning OpenCV. The section on the watershed algorithm was a bit short, so I thought I'd play with it a bit to see how exactly it works. However, every time I call the function I get the following error:
OpenCV Error: Unsupported format or combination of formats (Only 32-bit, 1-chann
el output images are supported) in cvWatershed
My program so far is very simple:
int main(int arg, int arg2) {
//open windows
cvNamedWindow("Input", 1 );
cvNamedWindow("Markings", 1 );
//load images
IplImage* input = cvLoadImage("ActualDoorPhoto.jpg", CV_LOAD_IMAGE_COLOR);
assert(input != NULL);
IplImage* markingstemp = cvLoadImage("ActualMarkingTest.jpg", CV_LOAD_IMAGE_COLOR);
assert(markingstemp != NULL);
//prepare markings
IplImage* markings = cvCreateImage(cvGetSize(markingstemp), 32, 1);
CvMat* markmat = cvCreateMat(input->width, input->height, CV_32FC1);
cvWatershed(input, markmat);
cvShowImage("Input", input);
cvShowImage("Markings", markings);
cvWaitKey(0);
return 0;
}
I have tried putting both markings and markmat as the second argument for cvWatershed, as well as several other things (notably markings with the contours of markingstemp drawn onto it), but every time I get the same error. Can anyone tell me what I'm doing wrong?
You're inverting the dimensions of the output matrix. It should be:
CvMat* markmat = cvCreateMat(input->height, input->width, CV_32FC1);
The format should also probably be changed to CV_32SC1.
I am writing an improved Perlin noise (I don't really understand simplex noise) terrain generator for C, and I am practically finished with the alpha build. However, there is one thing holding me back: actually saving the stupid image. I recruited MagickWand to help me solve the problem of PNG creation, and it looks like a nice implementation on the whole, with tons of useful features etc., but there is very little documentation on the whole thing. No tutorials, really, just a bunch of lists of functions and some example programs. Here is my code so far, based on this:
EDIT: Cut out a bunch of irrelevant code.
#include <stdio.h>
#include <stdlib.h>
#include "mt.h"
#include "diamondsquare.h"
#include "/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers/wand/MagickWand.h"
int main () {
unsigned long seed = 0, x = 0, y = 0, initial = 0, range = 0;
int smooth = 0, fail = 1, index1 = 0, index2 = 0, exception = 0;
char flagchar1 = 'n';
// Some imperative code. Not relevant.
image *ConstituteImage(x, y, "I", IntegerPixel, grid, &exception);
write("image.png", image);
}
At the very least, I know that this is linked wrong (compiling returns an error inside wand.h that it can't find one of the headers). What's the proper way to go about creating an image from an array within a program using MagickWand for C?
Too much code, it could be summarized with:
image *ConstituteImage(x, y, "I", IntegerPixel, grid, &exception);
write("image.png", image);
But reading the MagickWand link you provided:
MagickWriteImageFile
MagickWriteImageFile() writes an image to an open file descriptor. The
format of the MagickWriteImageFile method is:
MagickBooleanType MagickWriteImageFile ( MagickWand *wand, FILE *file
); A description of each parameter follows:
wand: The magick wand. file: The file descriptor.
So it is clear you have to call:
MagickBooleanType MagickWriteImageFile ( MagickWand *wand, FILE *file );
that header almost definitely tries to include other headers so you need something like:
gcc -I"/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers"
or
gcc -I"/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers/wand"
i'm trying to create a simple Opencv program in C that creates a file capture from a .avi, and it plays it in a window highlighting faces. I'm running a self-compiled version of Opencv (i already tried the same with a jpeg image and it works).
Building goes well, no errors, no warning, but when i launch it this the console output this:
Unknown parameter encountered: "server role"
Ignoring unknown parameter "server role"
And the program simply stops
Previously it was complaining for a missing /home/#user/.smb/smb.conf file, so i tried installing samba ( even though i've still no idea what does samba have to do in all this )
here is my code:
main(){
printf("Ciao!");
cvNamedWindow("window", CV_WINDOW_AUTOSIZE);
cvWaitKey(0);
printf("ok");
CvCapture* capture = cvCreateFileCapture("monsters.avi");
CvHaarClassifierCascade* cascade = load_object_detector("haarcascade_frontalface_alt.xml");
CvMemStorage* storage = cvCreateMemStorage(0);
//List of the faces
CvSeq* faces;
while (0<10) {
CvArr* image = cvQueryFrame(capture);
double scale = 1;
faces = cvHaarDetectObjects(image,cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(1,1), cvSize(300,300));
int i;
for(i = 0; i < faces->total; i++ )
{
CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );
cvRectangle( image,
cvPoint(face_rect.x*scale,face_rect.y*scale),
cvPoint((face_rect.x+face_rect.width)*scale,(face_rect.y+face_rect.height)*scale),
CV_RGB(255,0,0) , 3, 8, 0);
}
cvReleaseMemStorage( &storage );
cvShowImage("window", image);
}
cvWaitKey(0);
printf("Ciao!");
}
I thank you for your answer, i switched to C++ for my trials. Now i did this:
int main(){
namedWindow("Video", CV_WINDOW_FREERATIO);
VideoCapture cap("sintel.mp4");
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
for(;;){
Mat frame;
cap>>frame;
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("Video", edges);
//cvWaitKey(0);
}
return(0);
}
Now it succesfully load the video and query a frame, evry time i press a key it obviously query another frame and everything works fine, but if i comment the waitkey() the program simply hangs for a bit and crashes if i try to close the window, i'm starting to think there is a problem with codecs or something like that...
There are so many potential problems in the code, most of them related to not coding defensively.
What is cvWaitKey(0); doing after cvNamedWindow()? It's unecessary, remove it!
What happens if the capture was unsucessful? Code defensively:
CvCapture* capture = cvCreateFileCapture("monsters.avi");
if (!capture)
{
// File not found, handle error and possibly quit the application
}
and you should use this technique for every pointer that you receive from OpenCV, ok?
One of the major problems, is that you allocate memory for CvMemStorage before the loop, but inside the loop you release it, which means that after the first loop iteration there will be no longer a valid CvMemStorage* storage, and that's a HUGE problem.
Either move the allocation procedure to the beginning of the loop, so on every iteration memory is allocated/deallocated, or move the cvReleaseMemStorage( &storage ); call out of the loop.
Now it works fine, i changed cvWaitKey() with this
if(waitKey(30) >= 0) break;
I don't understand exactly why but now everything works as it should :)