【Java SE】使用Javacv截取视频图片
【Java Web开发学习】使用Javacv截取视频图片
转载:https://www.cnblogs.com/yangchongxing/p/9482935.html
github地址:https://github.com/bytedeco/javacv
Java不擅长处理视频和图片。使用场景是上传上来的视屏需要一个封面,所以就用java实现了。
javacv文档很少,参考网上的代码稍作修改而成,仅供参考,有好的方式欢迎留言。
网上有好多没有解决截屏图片被旋转过的问题,使用String rotate = grabber.getVideoMetadata("rotate");获取视频有没有旋转,没有返回null,有返回度数,90,180,270等。把图片做对象旋转,图片就正了。
示例代码:select截取第20帧的图片
- public static void main(String[] args) throws IOException {
- // 截第20帧
- int select = 20;
- FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("E:/wx/下.mp4");
- grabber.start();
- int length = grabber.getLengthInFrames();
- int index = 1;
- Frame frame = null;
- while (index <= length) {
- frame = grabber.grab();
- if (index >= select) {
- break;
- }
- index++;
- }
- String rotate = grabber.getVideoMetadata("rotate");
- Java2DFrameConverter converter = new Java2DFrameConverter();
- BufferedImage bi = converter.getBufferedImage(frame);
- if (rotate != null) {
- //旋转图片
- bi = rotate(bi, Integer.parseInt(rotate));
- }
- ImageIO.write(bi, "jpg", new File("E:/wx/" + System.currentTimeMillis() + ".jpg"));
- grabber.stop();
- }
- public static BufferedImage rotate(BufferedImage src, int angel) {
- int src_width = src.getWidth(null);
- int src_height = src.getHeight(null);
- int type = src.getColorModel().getTransparency();
- Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
- BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
- Graphics2D g2 = bi.createGraphics();
- g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
- g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
- g2.drawImage(src, 0, 0, null);
- g2.dispose();
- return bi;
- }
- public static Rectangle calcRotatedSize(Rectangle src, int angel) {
- if (angel >= 90) {
- if(angel / 90 % 2 == 1) {
- int temp = src.height;
- src.height = src.width;
- src.width = temp;
- }
- angel = angel % 90;
- }
- double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
- double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
- double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
- double angel_dalta_width = Math.atan((double) src.height / src.width);
- double angel_dalta_height = Math.atan((double) src.width / src.height);
- int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
- int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
- int des_width = src.width + len_dalta_width * 2;
- int des_height = src.height + len_dalta_height * 2;
- return new java.awt.Rectangle(new Dimension(des_width, des_height));
- }
下面是一个上传截取第一帧做图片
- import java.awt.Dimension;
- import java.awt.Graphics2D;
- import java.awt.Rectangle;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import javax.imageio.ImageIO;
- import javax.servlet.http.HttpServletRequest;
- import org.bytedeco.javacv.FFmpegFrameGrabber;
- import org.bytedeco.javacv.Java2DFrameConverter;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.multipart.commons.CommonsMultipartFile;
- import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
- @RequestMapping("/upload")
- @Controller
- public class UploadController extends BaseController {
- // 图片上传
- @RequestMapping(value="/image", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
- @ResponseBody
- public String uploadImage(@RequestParam(value = "imageFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException {
- if (imageFile == null || imageFile.getSize() == 0) {
- DefaultMultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest)request;
- imageFile = (CommonsMultipartFile) multipartRequest.getFile("Filedata");
- if (imageFile == null || imageFile.getSize() == 0) {
- Result result = new Result();
- result.setStatus(Result.STATUS_FAILURE);
- result.setMessage(Result.STATUS_FAILURE);
- return result.toJson();
- }
- }
- //文件名
- String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename());
- //日期目录
- String path = "/uploads/images" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
- //服务器图片文件存放目录
- String serverPath = request.getServletContext().getRealPath(path);
- File serverPathFile = new File(serverPath);
- //目录不存在则创建
- if (!serverPathFile.exists()) {
- serverPathFile.mkdirs();
- }
- String imageUrl = path + fileName;
- String serverFilePath = serverPath + fileName;
- //移动文件
- imageFile.transferTo(new File(serverFilePath));return imageUrl;
- }
- // 视频上传
- @SuppressWarnings("resource")
- @RequestMapping(value="/video", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
- @ResponseBody
- public String uploadVideo(@RequestParam(value = "videoFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException {
- if (imageFile == null || imageFile.getSize() == 0) {
- Result result = new Result();
- result.setStatus(Result.STATUS_FAILURE);
- result.setMessage("文件不存在");
- return result.toJson();
- }
- //文件名
- String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename());
- //日期目录
- String path = "/uploads/videos" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
- //服务器图片文件存放目录
- String serverPath = request.getServletContext().getRealPath(path);
- File serverPathFile = new File(serverPath);
- //目录不存在则创建
- if (!serverPathFile.exists()) {
- serverPathFile.mkdirs();
- }
- String serverFilePath = serverPath + fileName;
- //移动文件
- imageFile.transferTo(new File(serverFilePath));
- //视频截屏
- FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(serverFilePath);
- grabber.start();
- Java2DFrameConverter converter = new Java2DFrameConverter();
- BufferedImage bi = converter.convert(grabber.grab());
- String rotate = grabber.getVideoMetadata("rotate");
- if (rotate != null) {
- bi = rotate(bi, Integer.parseInt(rotate));
- }
- fileName += ".v.jpg";
- serverFilePath = serverPath + fileName;
- String imageUrl = path + fileName;
- ImageIO.write(bi, "jpg", new File(serverFilePath));
- grabber.stop();
- // 返回截取封面
return imageUrl;- }
- public static BufferedImage rotate(BufferedImage src, int angel) {
- int src_width = src.getWidth(null);
- int src_height = src.getHeight(null);
- int type = src.getColorModel().getTransparency();
- Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
- BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
- Graphics2D g2 = bi.createGraphics();
- g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
- g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
- g2.drawImage(src, 0, 0, null);
- g2.dispose();
- return bi;
- }
- public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
- if (angel >= 90) {
- if(angel / 90 % 2 == 1) {
- int temp = src.height;
- src.height = src.width;
- src.width = temp;
- }
- angel = angel % 90;
- }
- double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
- double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
- double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
- double angel_dalta_width = Math.atan((double) src.height / src.width);
- double angel_dalta_height = Math.atan((double) src.width / src.height);
- int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
- int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
- int des_width = src.width + len_dalta_width * 2;
- int des_height = src.height + len_dalta_height * 2;
- return new java.awt.Rectangle(new Dimension(des_width, des_height));
- }
- }
【Java SE】使用Javacv截取视频图片的更多相关文章
- C#利用开源软件ffMpeg截取视频图片
#region 从视频画面中截取一帧画面为图片 /// <summary> /// 从视频画面中截取一帧画面为图片 /// </summary> /// <param n ...
- 使用javacv 截取视频指定帧节
个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...
- (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片
你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...
- iOS截取视频缩略图的两种方法
前言: 看完了使用MPMoviePlayerController播放在线视频,在实际应用中有时候须要获取视频的缩略图,我们来看看怎样截取指定时间内的视频缩略图. 一 使用MPMoviePlayerC ...
- FFmpeg-截取视频图片
FFmpeg-截取视频图片 标签(空格分隔): linux 安装FFmpeg 官网:http://www.ffmpeg.org/ 这里主要是linux环境下的安装 1. wget http://ffm ...
- javacv——读取摄像头的图像、截取视频的画面
javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能). 这些需要引入的包.音视频处理使用ff ...
- javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作
欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) javaCV图像处理系列: javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体.位置. ...
- Java截取视频文件缩略图
/** * 截取视频第0帧的图片 */public static void videoImage(String filePath, String fileName,int widthdist, int ...
- php ffmpeg截取视频第一帧保存为图片的方法
php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...
随机推荐
- C语言|博客作业06
这个作业属于哪个课程 C语言程序设计II 这个作业的要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-1/homework/9885 我在这个课程的 ...
- synchronized:内部锁
synchronized:内部锁 起源: 并行程序开发涉及多线程.多任务间的协作和数据共享 一).内部锁:synchronized 1).定义在方法上 public synchronized void ...
- vim用户手册笔记常用操作整理
"x"命令可以删除一个字符 "d"命令可以后跟任何一个位移命令,它将删除从当前光标起到位移的终点处的文本内容dw "c",改变命令例如cw ...
- node 后台使用增删改查(4)
无论node还是java增删改查都是一样的原理,变得是配合框架使用时候有简便方法而已. 这里我接着上一篇开始讲,使用同一个数据库(数据库创建)这里必须创建了数据库 优化:为了维护方便这里我们把sql语 ...
- [ch03-00] 损失函数
系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 第3章 损失函数 3.0 损失函数概论 3.0.1 概念 ...
- python3 之 内置函数enumerate
python3 内置函数enumerate一.简介: 该函数在字面上是枚举.列举的意思,用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列, 同时列出数据和数据下标,一般用在 for ...
- PHP开发各种规范,面试秘籍!
基本约定 源文件 代码使用<?php开头,忽略闭合标签?> 文件格式必须是无BOM UTF-8格式 一个文件只声明一种类型,如class和interface不能混写在一个源文件中 缩进 使 ...
- 【数据结构】之顺序表(C语言描述)
顺序表是线性表的一种,它将元素存储在一段连续的内存空间中,表中的任意元素都可以通过下标快速的获取到,因此,顺序表适合查询操作频繁的场景,而不适合增删操作频繁的场景. 下面是使用 C语言 编写的顺序表的 ...
- js贪吃蛇(构造函数)
给大家分享一下这几天我研究的一个贪吃蛇,挺简单的,但是实现起来其实有点绕的,我给大家附上完整代码,一起分析学习一下,主要用的是构造函数. 思想: .设计蛇:属性有宽.高.方向.状态(有多少节),方法: ...
- 爬取豆瓣top250音乐 时长 出版商 存入Mongo数据库
import requestsfrom lxml import etreeimport reimport pymongoimport time client = pymongo.MongoClient ...