Bilder aus Video extrahieren



  • Also,

    der Dateityp ist ein avi-File. Ich suche, wenn möglich, per "using System.???" die Möglichkeit damit eine Datei vom Pfad einzulesen um dann aus dem Video einzelne Bilder zu generieren. Es sollte nach Möglichkeit kein externes Programm verwendet werden. Also nur standardmäßiges von Windows, Windows Media Player oder so.



  • Ok,

    ich werd mir erstmal folgendes durchlesen. Scheint ganz nützlich zu sein.

    http://www.codeproject.com/Articles/13237/Extract-Frames-from-Video-Files



  • Ok. Ich denke ich hab nun das gefunden, was ich suche:

    "IMediaDet Interface"

    http://msdn.microsoft.com/en-us/library/ms785892.aspx

    Problem: Wie includiere ich jetzt "Qedit.h" in csharp?



  • Coder2013 schrieb:

    http://www.codeproject.com/Articles/13237/Extract-Frames-from-Video-Files

    Hast du dir den kompletten Quellcode zu dem Artikel angesehen? Ich wette, da ist drin was du suchst. 😉



  • PuppetMaster2k schrieb:

    Coder2013 schrieb:

    http://www.codeproject.com/Articles/13237/Extract-Frames-from-Video-Files

    Hast du dir den kompletten Quellcode zu dem Artikel angesehen? Ich wette, da ist drin was du suchst. 😉

    Die Wette gewinnst du.



  • Ok, habe es hinbekommen.

    Hab aber nun ein neues Problem:

    Ich möchte gern die einzelnen Frames wieder hintereinander in einer picturebox ausgeben... funktioniert auch, aber die Methode "GetFrameFromVideo" ist sehr langsam...

    Wie kann ich dies denn beschleunigen?



  • Wie wärs wenn du erstmal rausfindest was genau langsam ist ?

    Und wie viele Frames bzw. wie schnell soll es denn sein ?
    Ein Frame pro Sekunde oder so sollte eigentlich problemlos machbar sein.
    Wenn du allerdins das Video in Echtzeit in einer PictureBox abspielen willst bekommst du Probleme..



  • Hi,

    na es sollten schon so 12 Frames pro Sekunde sein, das wäre quasi die Echtzeit. Kann das auch an der PictureBox liegen? An sowas hab ich gar nicht gedacht. Gibt es noch andere Standards außer der PictureBox?

    Am RAM oder CPU-Leistung liegt es auf jeden Fall nicht.

    Ich denke es muss im "FrameGrabber" an den folgenden Zeilen liegen:

    unsafe
                        {
                            Size s = getVideoSize(mediaType);
                            int bmpinfoheaderSize = 40; // equals to sizeof(CommonClasses.BITMAPINFOHEADER);
    
                            // get size for buffer
                            int bufferSize = (((s.Width * s.Height) * 24) / 8) + bmpinfoheaderSize;	//equals to mediaDet.GetBitmapBits(0d, ref bufferSize, ref *buffer, target.Width, target.Height);	
    
                            // allocates enough memory to store the frame
                            IntPtr frameBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(bufferSize);
                            byte* frameBuffer2 = (byte*)frameBuffer.ToPointer();
    
                            // gets bitmap, save in frameBuffer2
                            mediaDet.GetBitmapBits(Position, ref bufferSize, ref *frameBuffer2, target.Width, target.Height);
    
                            // now in buffer2 we have a BITMAPINFOHEADER structure followed by the DIB bits
    
                            Bitmap bmp = new Bitmap(target.Width, target.Height, target.Width * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, new IntPtr(frameBuffer2 + bmpinfoheaderSize));
    
                            bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
                            System.Runtime.InteropServices.Marshal.FreeHGlobal(frameBuffer);
    
                            return bmp;
                        }
    


  • Such dir mal nen .NET Profiler und schau mal was genau langsam ist.

    Und es wird zu 100% CPU oder RAM Geschwindigkeit sein, was macht dich so sicher dass es das nicht ist ?



  • Die IMediaDet Implementierung ist darauf hinprogrammiert/hinoptimiert dass man einzelne Bilder aus dem Video rauspicken will, und nicht viele aufeinanderfolgende.
    Ist also kein Wunder wenn sie dabei furchtbar langsam ist.

    Bilder hintereinander rausholen geht z.B. mit nem FilterGraph + SampleGrabber + NullRenderer. Ist aber auch nicht gerade das einfachste.
    Ich meine auch mal gelesen zu haben dass man dabei je nach CODEC nicht framegenau positionieren kann.

    ps: wie schnell es ohne PictureBox geht kannst du doch einfach probieren indem du das Updaten der PictureBox weglässt, und einfach nur die Timings ausgibst (Debug.WriteLine oder was auch immer).
    Die PictureBox wird nämlich sicher auch was bremsen, die ist ja auch überhaupt nicht dafür gemacht Videos anzuzeigen.



  • So, hab mal das folgende benutzt:

    http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library

    Ist aber auch leider langsam...

    Hab mal per Threads versucht die Arbeit des Extrahierens auf verschiedenen CPU-Kernen zu verteilen. Problem: es entstehen Artefakte im Video. Kommt das eventuell durch mehrere Zugriffe auf die eine Videodatei?


Anmelden zum Antworten