Как я могу получить образец кадра (jpeg) из видео (mov)

Я хочу получить образец кадра (jpeg) из видеофайла (mov) с java. Есть ли простой способ сделать это. Когда я ищу в google все, что я могу найти, это сделать mov из нескольких jpgs. Я не знаю, может быть, я не могу найти правильные ключевые слова.

6 ответов


Я знаю, что исходный вопрос решен, тем не менее, я публикую этот ответ на случай, если кто-то еще застрял, как я.

со вчерашнего дня, я пробовал все, и я имею в виду все это делать. Все доступные библиотеки Java либо устарели, либо больше не поддерживаются или не имеют какой-либо полезной документации (серьезно??!?!)

Я пробовал JFM (старый и бесполезный), JCodec (никакой документации вообще), JJMpeg (выглядит многообещающе, но очень сложно и громоздко использовать из-за отсутствия документации Java-класса), OpenCV auto-Java строит и несколько других библиотек, которые я не могу вспомнить.

наконец, я решил взглянуть на JavaCV ' s (ссылка Github) классы и вуаля! Он содержит привязки FFMPEG с подробной документацией.

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.0</version>
</dependency>

оказывается, есть очень простой способ, чтобы извлечь кадры из видео файла BufferedImage и расширение файла JPEG. Класс FFmpegFrameGrabber можно легко использовать для захвата отдельных кадров и преобразования их в BufferedImage. Пример кода выглядит следующим образом:

FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();

for (int i = 0 ; i < 50 ; i++) {
    ImageIO.write(g.grab().getBufferedImage(), "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}

g.stop();

в основном, этот код сбрасывает первые 50 кадров видео и сохраняет их в виде файла PNG. Хорошо, что функция внутреннего поиска работает на реальных кадрах, а не на ключевых кадрах (проблема, которая у меня была с JCodec)

вы можете обратиться к домашней странице JavaCV, чтобы узнать больше о других классах, которые могут быть использованы для захвата кадры с веб-камер и т. д. Надеюсь, этот ответ поможет : -)


Xuggler выполняет эту работу. Они даже дают пример кода, который делает именно то, что мне нужно. Ссылка ниже

http://xuggle.googlecode.com/svn/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/demos/DecodeAndCaptureFrames.java

и я изменил код в этой ссылке такого, что он сохраняет только первый кадр видео.

import javax.imageio.ImageIO;

import java.io.File;

import java.awt.image.BufferedImage;

import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.xuggler.Global;

/**
 *  * @author aclarke
 *    @author trebor
 */

public class DecodeAndCaptureFrames extends MediaListenerAdapter
{
  private int mVideoStreamIndex = -1;
  private boolean gotFirst = false;
  private String saveFile;
  private Exception e;
  /** Construct a DecodeAndCaptureFrames which reads and captures
   * frames from a video file.
   * 
   * @param filename the name of the media file to read
   */

  public DecodeAndCaptureFrames(String videoFile, String saveFile)throws Exception
  {
    // create a media reader for processing video
    this.saveFile = saveFile;
    this.e = null;
     IMediaReader reader = ToolFactory.makeReader(videoFile);

    // stipulate that we want BufferedImages created in BGR 24bit color space
    reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);


    // note that DecodeAndCaptureFrames is derived from
    // MediaReader.ListenerAdapter and thus may be added as a listener
    // to the MediaReader. DecodeAndCaptureFrames implements
    // onVideoPicture().

    reader.addListener(this);

    // read out the contents of the media file, note that nothing else
    // happens here.  action happens in the onVideoPicture() method
    // which is called when complete video pictures are extracted from
    // the media source

      while (reader.readPacket() == null && !gotFirst);

      if (e != null)
          throw e;
  }



  /** 
   * Called after a video frame has been decoded from a media stream.
   * Optionally a BufferedImage version of the frame may be passed
   * if the calling {@link IMediaReader} instance was configured to
   * create BufferedImages.
   * 
   * This method blocks, so return quickly.
   */

  public void onVideoPicture(IVideoPictureEvent event)
  {
    try
    {
      // if the stream index does not match the selected stream index,
      // then have a closer look

      if (event.getStreamIndex() != mVideoStreamIndex)
      {
        // if the selected video stream id is not yet set, go ahead an
        // select this lucky video stream

        if (-1 == mVideoStreamIndex)
          mVideoStreamIndex = event.getStreamIndex();

        // otherwise return, no need to show frames from this video stream

        else
          return;
      }

      ImageIO.write(event.getImage(), "jpg", new File(saveFile));
      gotFirst = true;

    }
    catch (Exception e)
    {
      this.e = e;
    }
  }
}

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;

public class Read{
    public static void main(String []args) throws IOException, Exception
    {
        FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
        frameGrabber.start();
        IplImage i;
        try {

            i = frameGrabber.grab();
            BufferedImage  bi = i.getBufferedImage();
            ImageIO.write(bi,"png", new File("D:/Img.png"));
            frameGrabber.stop();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }
}

возможно, это поможет вам:

Buffer buf = frameGrabber.grabFrame();
// Convert frame to an buffered image so it can be processed and saved
Image img = (new BufferToImage((VideoFormat) buf.getFormat()).createImage(buf));
buffImg = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB);
//TODO saving the buffImg

дополнительные сведения:

как делать одиночные снимки с веб-камеры?


ниже показан необходимый код для запроса кадров из медиафайлов.

для полного исходного кода и демонстрации видео:
"Обработка Медиафайлов" пример использования Марвин Рамках..

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();
    }
}

вот как с BoofCV:

String fileName = UtilIO.pathExample("tracking/chipmunk.mjpeg");

MediaManager media = DefaultMediaManager.INSTANCE;

ConfigBackgroundBasic configBasic = new ConfigBackgroundBasic(30, 0.005f);
ImageType imageType = ImageType.single(GrayF32.class);
BackgroundModelMoving background = FactoryBackgroundModel.movingBasic(configBasic, new PointTransformHomography_F32(), imageType);

SimpleImageSequence video = media.openVideo(fileName, background.getImageType());

ImageBase nextFrame;
while(video.hasNext()) {
    nextFrame = video.next();

    // Now do something with it...
}