当前位置: 首页 > news >正文

javacv获取视频第一帧

第一种是用ffmpeg工具,不过还得安装客户端软件,于是放弃了,还有一种是javacv开源工具,所以选择第二种:

第一种:ffmpeg工具

需要安装ffmpeg软件,支持windows和linux,视频安装教程参考:https://www.cnblogs.com/rxbook/p/9652185.html

然后用以下代码:

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;

public class FirstFrameUtil {
    protected String ffmpegApp;
    public FirstFrameUtil(String ffmpegApp) {
        this.ffmpegApp = ffmpegApp;
    }
    @SuppressWarnings("unused")
    /****
     * 获取指定时间内的图片
     * @param videoFilename:视频路径
     * @param thumbFilename:图片保存路径
     * @param width:图片长
     * @param height:图片宽
     * @param hour:指定时
     * @param min:指定分
     * @param sec:指定秒
     * @throws IOException
     * @throws InterruptedException
     */
    public void getThumb(String videoFilename, String thumbFilename,  int hour, int min, float sec) throws IOException, InterruptedException {
            ProcessBuilder processBuilder = new ProcessBuilder(ffmpegApp, "-y", "-i", videoFilename, "-vframes", "1", "-ss", hour + ":" + min + ":" + sec, "-f", "mjpeg",  "-an",
                    thumbFilename);
        Process process = processBuilder.start();
        InputStream stderr = process.getErrorStream();
        InputStreamReader isr = new InputStreamReader(stderr);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null)
            ;
        process.waitFor();   
        if (br != null)
            br.close();
        if (isr != null)
            isr.close();
        if (stderr != null)
            stderr.close();
    }
    public static void main(String[] args) {
        String path = "D:\\config\\ffmpeg-win64\\bin\\ffmpeg.exe";

        FirstFrameUtil videoThumbTaker = new FirstFrameUtil(path);
        try {
            videoThumbTaker.getThumb("D:\\test2.mp4", "D:\\test\\result.png", 0, 0, 1);
            File ffmpegFile = new File("D:\\test\\result.png");
            FileInputStream input=new FileInputStream(ffmpegFile);
            
            System.out.println("over");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
View Code

即可获取第一帧图片

第二种javacv

直接上代码:(后边有介绍pom文件的引用)

import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.Frame;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class VideoTool {

    public static void main(String[] args) throws Exception {

       // randomGrabberFFmpegImage("http://101.132.110.90/group1/M00/00/05/rBN4LFq8p5SAJT0wA5k4vpHKf7Q325.mp4", "D:\\test", "test2");
        randomGrabberFFmpegImage("D:\\test2.mp4", "D:\\test", "test2");
        //randomGrabberFFmpegImage("C:/Users\\Administrator\\Desktop\\VID_20171229_162251.mp4", "G:\\test", "111");
    }

    public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName)
            throws Exception {
        //创建视频帧抓取工具
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        //获取旋转角度信息(90度)
        String rotate =ff.getVideoMetadata("rotate");
        //
        Frame f;
        //i可以控制获取第几帧
        int i = 0;
        while (i <5) {
            //一帧一帧去抓取视频图片,ff.grabImage();每次抓取下一帧
            f =ff.grabImage();
            IplImage src = null;
            //旋转图像并输出第29帧
            if(i==4){
                //手机录的视频有旋转角度,需要旋转处理
                if(null !=rotate &&rotate.length() > 1) {
                    OpenCVFrameConverter.ToIplImage converter =new OpenCVFrameConverter.ToIplImage();
                    src =converter.convert(f);
                    f =converter.convert(rotate(src, Integer.valueOf(rotate)));
                }
                //输出第几帧图片
                doExecuteFrame(f,targerFilePath,targetFileName+i+i);
            }           
            i++;
        }
        ff.stop();
    }

    /*
     * 旋转角度的
     */
    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName) {

        if (null ==f ||null ==f.image) {
            return;
        }
        Java2DFrameConverter converter =new Java2DFrameConverter();
        String imageMat ="jpg";
        String FileName =targerFilePath + File.separator +targetFileName +"." +imageMat;
        BufferedImage bi =converter.getBufferedImage(f);
        System.out.println("width:" + bi.getWidth());
        System.out.println("height:" + bi.getHeight());
        File output =new File(FileName);
        try {
            ImageIO.write(bi,imageMat,output);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }   
   
}

如果不判断旋转,把手机视频放上去,截出来的是方向不对,如图左边是旋转过的,右边没有旋转的:

解决图片旋转问题参考:http://blog.csdn.net/z562743237/article/details/54667252,通过一段时间的搜索了解到,如果拍摄的视频中带有旋转(rotate)信息,那么截取出来的图片就会被旋转。通过查询API发现FFmpegFrameGrabber的getVideoMetadata("rotate")方法可以获取到视频的旋转信息。根据获取到的rotate信息对ff.grabImage()得到的Frame进行旋转,但是Frame并没有提供旋转接口。但IpImage对象提供了旋转方法 。

大多数人都是直接引入

javacv-platform
<dependency>
   <groupId>org.bytedeco</groupId>
   <artifactId>javacv-platform</artifactId>
   <version>1.3.1</version>
</dependency>

 

javacv-platform这种方式依赖的jar包300M,太大了,经过精简后pom文件如下:(在用,40兆左右)
    <properties>
        <javacpp.version>1.3</javacpp.version>
    </properties>  

    <dependencies>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>flycapture</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libdc1394</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libfreenect</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>libfreenect2</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>librealsense</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>videoinput</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>artoolkitplus</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>artoolkitplus</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco.javacpp-presets</groupId>
                    <artifactId>flandmark</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

      <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv</artifactId>
            <version>3.1.0-${javacpp.version}</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv</artifactId>
            <version>3.1.0-${javacpp.version}</version>
            <classifier>windows-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>3.2.1-${javacpp.version}</version>
            <classifier>windows-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>3.2.1-${javacpp.version}</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
   </dependencies>

共8个jar

 

 

转载于:https://www.cnblogs.com/zhaoyanhaoBlog/p/11465516.html

相关文章:

  • Android ANR log trace日志文件分析
  • ffmpeg开发文档
  • js 特殊字符替换成换行
  • xampp for mac配置局域网访问
  • Xray写POC插件
  • db timedb / ClickHouse
  • Redis 学习笔记(篇十):Sentinel
  • OS + Centos7.6 / Windows 10 shuangxitong
  • C#中字符串转换为计算公式
  • SSM框架-SpringMVC
  • SSM框架-mybatis
  • 微软3389远程漏洞CVE-2019-0708批量检测工具
  • 浅谈 赛马问题
  • JDK配置
  • 数据库模糊查询
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • $translatePartialLoader加载失败及解决方式
  • canvas 绘制双线技巧
  • CentOS 7 防火墙操作
  • eclipse(luna)创建web工程
  • Effective Java 笔记(一)
  • es的写入过程
  • HashMap ConcurrentHashMap
  • Java精华积累:初学者都应该搞懂的问题
  • Median of Two Sorted Arrays
  • node学习系列之简单文件上传
  • scala基础语法(二)
  • Vultr 教程目录
  • 从0到1:PostCSS 插件开发最佳实践
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 入门级的git使用指北
  • 思否第一天
  • 通过git安装npm私有模块
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 找一份好的前端工作,起点很重要
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​水经微图Web1.5.0版即将上线
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (全注解开发)学习Spring-MVC的第三天
  • (译)计算距离、方位和更多经纬度之间的点
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)nsfocus-绿盟科技笔试题目
  • (转)程序员技术练级攻略
  • (转)关于多人操作数据的处理策略
  • .NET Core中的去虚
  • .Net Remoting常用部署结构
  • .Net接口调试与案例
  • .NET设计模式(2):单件模式(Singleton Pattern)