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();
}
}
}
即可获取第一帧图片
第二种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
javacv获取视频第一帧的更多相关文章
- Android -- 获取视频第一帧缩略图
干货 从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. public ...
- Android之使用MediaMetadataRetriever类获取视频第一帧
一.首先,来介绍一下MediaMetadataRetriever类,此类位于android.media包下,这里,先附上可查看此类的API地址:MediaMetadataRetriever类.大家能够 ...
- 关于video标签移动端开发遇到的问题,获取视频第一帧,全屏,自动播放,自适应等问题
最近一直在处理video标签在IOS和Android端的兼容问题,其中遇到不少坑,绝大多数问题已经解决,下面是处理问题经验的总结: 1.获取视频的第一帧作为背景图: 技术:canvas绘图 windo ...
- 通过 ffmpeg 获取视频第一帧(指定时间)图片
最近做一个上传教学视频的方法,上传视频的同时需要上传视频缩略图,为了避免用户上传的缩略图与视频内容不符,经理要求直接从上传的视频中截图视频的某一帧作为缩略图,并给我推荐了FFMPEG.FFMPEG 功 ...
- python cv2获取视频第一帧,并转码
安装Python库 sudo pip install opencv-python 或者sudo pip install opencv-python -i https://pypi.douban.com ...
- Android视频处理 --处理视频第一帧缩略图
从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. ? 1 publi ...
- 使用javacv 截取视频指定帧节
个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...
- vue 截取视频第一帧
最近自己写项目,在项目中涉及功能点又截取视频帧的点:需求澄清:移动端封面展示,平台上传图片(多张上传)取第一张上传图片为封面图:如上传视频则截取视频第一帧作为封面图: 实现思路:h5 video标签 ...
- php ffmpeg截取视频第一帧保存为图片的方法
php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...
随机推荐
- LIS(最长上升子序列)的 DP 与 (贪心+二分) 两种解法
正好训练赛来了一道最长递减序列问题,所以好好研究了一下最长递增序列问题. B - Testing the CATCHER Time Limit:1000MS Memory Limit:3000 ...
- qt 字符串 转换 hex
1. qt 中两个字符的字符串直接转换为 hex,类似于 "1A" 要转换成 16进制的 0x1A,使用 int QString::toInt(bool *ok, int base ...
- VSFTP 连接时425 Security: Bad IP connecting.报错-----解决方法
当登录FTP时候出现这个报错时.是因为PASV模式的安全检查是开启的(默认是开启的) ftp> ls227 Entering Passive Mode (172,16,101,33,35,58 ...
- 用matplotlib统计数据并画图
用jupyter来统计数据,画出柱状图 import numpy as np import pandas as pd import matplotlib.pyplot as plt import ma ...
- vue select框change事件
vue Select 中< :label-in-value="true" @on-change="satusSelect"> satusSelect ...
- SQL server 查询常用语句 2019.3.20
SQL查询语句 select ...列名 from 表名 投影查询 select sno num,2019-sage as birthday // 给列起别名 from student: 在每个学生姓 ...
- Object arrays cannot be loaded when allow_pickle=False
问题再现 代码是Deep Learning with Python中的: from keras.datasets import imdb (train_data, train_labels), (te ...
- Vue动画封装
<head> <meta charset="UTF-8"> <title>Title</title> <script src= ...
- IOS下的safari不支持localStorage?
同事在统计日志的时候,想用localStorag去记载一些什么,但是在各大浏览器都运行的良好的基础上,唯独IOS下的safari一直静静无声,没有任何反应.打印localStorage都是Object ...
- 使用py-faster-rcnn训练自己的数据集
https://www.jianshu.com/p/a672f702e596 本文记录了在ubuntu16.04下使用py-faster-rcnn来训练自己的数据集的大致过程. 在此之前,已经成功配置 ...