2014-07-03 31 views
5

Mi piacerebbe leggere un file Mp4 in java8-64bit fotogramma per fotogramma e scrivere ogni fotogramma come jpg sul mio disco rigido. il mio primo tentativo è stato quello di utilizzare il lettore multimediale JavaFX 2.2 per riprodurre il file su un componente View. Ho pensato che forse ci sarebbe stata un'opzione per registrare un osservatore per ottenere un evento ogni volta che un nuovo frame è stato caricato e pronto per essere dipinto sulla superficie del componente, ma sembra che non ci sia un tale metodo. sarebbe sufficiente prendere solo quei frame/pixel che sono stati dipinti sul componente.Come leggere un video fotogramma per fotogramma?

È possibile farlo utilizzando il lettore multimediale? il motivo per cui utilizzo il lettore multimediale è che è stata la soluzione più semplice a cui ho lavorato. Ho provato vlcj, solo a 32 bit, e gstreamer ma senza fortuna :(

quello che ho ottenuto finora:

public class VideoGrabber extends extends JFrame { 

// code for scene setup omitted 

final MediaView view = createMediaView(...) 

// some other stuff happens here 

// now start the video 
view.getMediaPlayer().seek(Duration.ZERO); 
view.getMediaPlayer().play(); 
view.getMediaPlayer().setOnEndOfMedia(new Runnable() 
{ // save image when done 
    BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_BGR 
    view.paint(img.getGraphics()); 
    ImageIO.write(img, "JPEG", new File("pic-"+System.currentTimeMillis()+".jpg")); 
}); 

// somewhere else to create 
private MediaView createMediaView(String url) 
{ 
    final Media clip = new Media(url); 
    final MediaPlayer player = new MediaPlayer(clip); 
    final MediaView view = new MediaView(player); 
    view.setFitWidth(VID_WIDTH); 
    view.setFitHeight(VID_HEIGHT); 
    return view; 
} 

c'è in qualche modo un modo per effettuare le seguenti operazioni:

player.setOnNextFrameReady(final Event evt) { writeImage(evt.getFrame()) }; 

Grazie!

risposta

3

Marvin Framework fornisce metodi per elaborare i file multimediali fotogramma per fotogramma. Di seguito viene mostrato un semplice esempio di elaborazione video che evidenzia il percorso di una palla da biliardo.

enter image description here

verso sinistra il video viene riprodotto fotogramma per fotogramma ad intervalli di 30 ms tra i fotogrammi. A destra il video viene riprodotto fotogramma per fotogramma, ma mantenendo tutte le posizioni della pallina bianca attraverso un semplice approccio di elaborazione delle immagini.

Il codice sorgente può essere controllato here e il video here.

sotto il codice fonte essenziale per richiedere telai file multimediale utilizzando la Marvin:

public class MediaFileExample implements Runnable{ 

    private MarvinVideoInterface videoAdapter; 
    private MarvinImage    videoFrame; 

    public MediaFileExample(){ 
     try{ 
      // Create the VideoAdapter used to load the video file 
      videoAdapter = new MarvinJavaCVAdapter(); 
      videoAdapter.loadResource("./res/snooker.wmv"); 

      // Start the thread for requesting the video frames 
      new Thread(this).start(); 
     } 
     catch(MarvinVideoInterfaceException e){e.printStackTrace();} 
    } 

    @Override 
    public void run() { 
     try{ 
      while(true){ 
       // Request a video frame 
       videoFrame = videoAdapter.getFrame(); 
      } 
     }catch(MarvinVideoInterfaceException e){e.printStackTrace();} 
    } 

    public static void main(String[] args) { 
     MediaFileExample m = new MediaFileExample(); 
    } 
} 
+0

molto bello, farò un tentativo. – Chris

1

I framework come ffmpeg sono dotati di strumenti da riga di comando per dividere un video in singoli fotogrammi (ad esempio immagini in una cartella)

Vedere questa domanda: ffmpeg split avi into frames with known frame rate

Le risposte contengono collegamenti a framework Java che racchiudono ffmpeg.

+0

grazie per la risposta. dopo aver ottenuto il frame dal video in java voglio fare ulteriore elaborazione su richiesta e poi salvarlo. posso ffmpeg creare un flusso di immagini che posso in qualche modo aprire in jave per elaborarlo, senza scrivere tutti i dati sul disco? – Chris

+0

Puoi provare 'https: // code.google.com/p/jjmpeg /'. Non è consigliabile utilizzare la riga di comando per estrarre fotogramma per fotogramma in una pipe poiché la ricerca nel flusso video sarà troppo costosa. –

+0

grazie ancora. sfortunatamente usare jjmpeg significherebbe che dovrò dedicare più tempo a fare il reverse engineering per sapere come usarlo (nessuna documentazione disponibile) piuttosto che dedicare del tempo ai compiti reali che devo eseguire. forse qualche altra risposta apparirà con soluzioni interessanti. ma grazie! – Chris

7

È possibile utilizzare l'istantanea() di MediaView. Prima connettere un mediaPlayer a un componente MediaView, quindi utilizzare mediaPlayer.seek() per cercare la posizione del video. E quindi è possibile utilizzare il seguente codice per estrarre il frame dell'immagine:

int width = mediaPlayer.getMedia().getWidth(); 
    int height = mediaPlayer.getMedia().getHeight(); 
    WritableImage wim = new WritableImage(width, height); 
    MediaView mv = new MediaView(); 
    mv.setFitWidth(width); 
    mv.setFitHeight(height); 
    mv.setMediaPlayer(mediaPlayer); 
    mv.snapshot(null, wim); 
    try { 
     ImageIO.write(SwingFXUtils.fromFXImage(wim, null), "png", new File("/test.png")); 
    } catch (Exception s) { 
     System.out.println(s); 
    } 
+0

Risposta molto sottovalutata. Grazie. – Smig

Problemi correlati