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