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();
    }
  }
}
相关推荐
省钱兄--zs13 分钟前
24小时自助健身房系统软件开发实战:从架构设计到部署全指南
java·数据仓库·spring boot·系统架构·需求分析
IT研究室17 分钟前
最新计算机毕业设计选题推荐-基于spring boot的智慧教学资源管理与互动交流平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
蜗牛互联网19 分钟前
Java HttpClient 调用 Gemini 图像理解与金额字段校验
java·开发语言·人工智能·后端·python
开开心心就好19 分钟前
视频里的图片怎么提取?双击一下就导出
java·前端·人工智能·spring·智能手机·intellij-idea·excel
蜗牛互联网20 分钟前
Python Responses API视觉输入与本地金额校验最小实现
java·开发语言·人工智能·后端·python
程序猿_极客23 分钟前
【免费】分享一套优质的基于Java的智慧养老院管理系统的设计与实现(带可视化),源码+文档+视频详解(讲解)
java·spring boot·后端·养老院管理系统
ly768933 分钟前
从 TF-IDF 到 BM25:Elasticsearch 相关性评分的字段长度归一化与 boost 调参边界
java·elasticsearch·query dsl·bm25·相关性评分
程序猿_极客37 分钟前
【免费】分享一套优质的基于SpringBoot的旅游管理系统的设计与实现(带智能推荐算法功能),源码+文档+视频详解(讲解)
java·spring boot·课程设计·旅游管理系统·计算机专业项目
Wang's Blog40 分钟前
Java 中间件之 RabbitMQ 快速入门: RabbitMQ 介绍与安装部署
java·中间件·java-rabbitmq
VidDown40 分钟前
自动给视频挑一张能看的封面:帧评分、构图与批量生成
python·ffmpeg·音视频·视频