JavaCV 进行视频操作

1、JavaCV实现将视频以帧方式抽取

java 复制代码
## JavaCV实现将视频以帧方式抽取

```java
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;

public class JavaCV {

  // the image's path;
  final static String imagePath = "/home/lance/abc.jpg/";
  // the vedio's path and filename;
  final static String vedioPath = "/home/lance/target-a/";
  final static String vedioName = "origin-a.mp4";


  public static void main(String[] args) throws Exception {
    smooth(imagePath);
    grabberFFmpegImage(vedioPath + vedioName, vedioPath
        , vedioName, 30);
  }

  // the method of compress image;
  public static void smooth(String fileName) {
    IplImage iplImage = cvLoadImage(fileName);
    if (iplImage != null) {
      cvSmooth(iplImage, iplImage);
      cvSaveImage(fileName, iplImage);
      cvReleaseImage(iplImage);
    }
  }

  // grab ffmpegImage from vedio;
  public static void grabberFFmpegImage(String filePath, String fileTargetPath
      , String fileTargetName, int grabSize) throws Exception{
    FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
    ff.start();
    for (int i = 0; i < grabSize; i++){
      Frame frame = ff.grabImage();
      doExecuteFrame(frame, filePath, fileTargetName, i);
    }
    ff.stop();
  }

  // grab frame from vedio;
  public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {
    if ( frame == null || frame.image == null) {
      return;
    }
    Java2DFrameConverter converter = new Java2DFrameConverter();
    String imageMat = "jpg";
    String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;
    BufferedImage bi = converter.getBufferedImage(frame);
    File output = new File(fileName);
    try{
      ImageIO.write(bi, imageMat, output);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

2、javaCV视频取

GitHub路径:

https://github.com/chenhua0915/FetchVideoFrameUtil.git

pom文件中的Maven配置:

xml 复制代码
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform  视频取帧-->
<dependency>
	<groupId>org.bytedeco</groupId>
	<artifactId>javacv-platform</artifactId>
	<version>1.4.4</version>
</dependency>

实例代码:

java 复制代码
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;


/**
 * Created with IDEA
 * 视频取帧,可设置间隔秒数或获取所有帧数
 *
 * @Author Chensj
 * @Date 2018/4/2 14:29
 * @Description
 * @Version 1.0
 */
public class FetchVideoFrameUtil {

    // 主函数
    public static void main(String[] args){
        try {
            String picPath = "D:\\demo\\pic\\";  // 提取得每帧图片存放位置
            String videoPath = "D:\\demo1.mp4";  // 原视频文件路径
            int second = 0; // 每隔多少帧取一张图,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
            // 开始视频取帧流程
            FetchVideoFrameUtil.fetchPic(new File(videoPath),picPath,second);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param file  源视频文件
     * @param picPath  截取帧的图片存放路径
     * @throws Exception
     */
    public static void fetchPic(File file, String picPath,int second) throws Exception{

        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件

        System.out.println(FetchVideoFrameUtil.getVideoTime(file)); // 显示视频长度(秒/s)

        ff.start(); // 调用视频文件播放
        int length = ff.getLengthInAudioFrames(); //视频帧数长度
        System.out.println(ff.getFrameRate());

        int i = 0; // 图片帧数,如需跳过前几秒,则在下方过滤即可
        Frame frame = null;
        int count = 0;
        while (i < length) {
            frame = ff.grabImage(); // 获取该帧图片流
            System.out.print(i + ",");
            if(frame!=null && frame.image!=null) {
                System.out.println(i);
                writeToFile(frame, picPath, count,second); // 生成帧图片
                count++;
            }
            i++;
        }
        ff.stop();
    }

    /**
     *
     * @param frame // 视频文件对象
     * @param picPath // 图片存放路径
     * @param count // 当前取到第几帧
     * @param second // 每隔多少帧取一张,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
     */
    public static void writeToFile(Frame frame, String picPath, int count, int second){
        if (second == 0) {
            // 跳过间隔取帧判断
        } else if (count % second != 0){ // 提取倍数,如每秒取一张,则: second = 20
           return;
        }
        File targetFile = new File(picPath + count + ".jpg");
        System.out.println("创建了文件:" + picPath + count + ".jpg");
        String imgSuffix = "jpg";

        Java2DFrameConverter converter =new Java2DFrameConverter();
        BufferedImage srcBi =converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH),0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取视频时长,单位为秒
     * @param file
     * @return 时长(s)
     */
    public static Long getVideoTime(File file){
        Long times = 0L;
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
            ff.start();
            times = ff.getLengthInTime()/(1000*1000);
            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return times;
    }
}

3、Java从视频内截取指定时间的图

此例子可用于:视频内截取某一帧作为封面图(可指定时间)、需要视频内某张图用作表情包。。。

java 复制代码
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;

public class VideoUtil {

    public static void main(String[] args) {
        try {
            getImgFromVideo("D:\\ffmpeg\\ffmpeg2016\\bin\\ffmpeg.exe", "d:\\ys\\StoryBrooke.mp4", "d:\\ys\\lain.jpg", 204, 140, 0, 0, 26);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取指定时间内的图片
     * @param ffmpegPath (ffmpeg路径)
     * @param videoPath (视频路径)
     * @param imgPath (图片存放路径)
     * @param width (图片宽度)
     * @param height (图片高度)
     * 以下为需要指定的时间
     * @param hour
     * @param min
     * @param sec
     * @return
     */
    public static boolean getImgFromVideo(String ffmpegPath, String videoPath, String imgPath, int width,
            int height, int hour, int min, float sec) {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-y",
                    "-i", videoPath, "-vframes", "1", "-ss", hour + ":" + min
                            + ":" + sec, "-f", "mjpeg", "-s", width + "*" + height,
                    "-an", imgPath);

            Process process = processBuilder.start();
            InputStream stderr = process.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            while ((br.readLine()) != null);
            process.waitFor();
            if (br != null)
                br.close();
            if (isr != null)
                isr.close();
            if (stderr != null)
                stderr.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

4、Javacv截取视频图片

java 复制代码
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;

public class JavaCV {

  // the image's path;
  final static String imagePath = "/home/lance/abc.jpg/";
  // the vedio's path and filename;
  final static String vedioPath = "/home/lance/target-a/";
  final static String vedioName = "origin-a.mp4";


  public static void main(String[] args) throws Exception {
    smooth(imagePath);
    grabberFFmpegImage(vedioPath + vedioName, vedioPath
        , vedioName, 30);
  }

  // the method of compress image;
  public static void smooth(String fileName) {
    IplImage iplImage = cvLoadImage(fileName);
    if (iplImage != null) {
      cvSmooth(iplImage, iplImage);
      cvSaveImage(fileName, iplImage);
      cvReleaseImage(iplImage);
    }
  }

  // grab ffmpegImage from vedio;
  public static void grabberFFmpegImage(String filePath, String fileTargetPath
      , String fileTargetName, int grabSize) throws Exception{
    FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
    ff.start();
    for (int i = 0; i < grabSize; i++){
      Frame frame = ff.grabImage();
      doExecuteFrame(frame, filePath, fileTargetName, i);
    }
    ff.stop();
  }

  // grab frame from vedio;
  public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {
    if ( frame == null || frame.image == null) {
      return;
    }
    Java2DFrameConverter converter = new Java2DFrameConverter();
    String imageMat = "jpg";
    String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;
    BufferedImage bi = converter.getBufferedImage(frame);
    File output = new File(fileName);
    try{
      ImageIO.write(bi, imageMat, output);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
相关推荐
m0_571957582 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟5 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity6 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天6 小时前
java的threadlocal为何内存泄漏
java
caridle7 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^7 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋37 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx