javacv使用笔记

一.前言

最近在做一个视频审核的功能,但是运营觉得每个视频都要看一篇太浪费时间了,于是提出了这样一个需求,给每个视频随机截取5张图片展示出来,根据这5张图片决定是否需要继续观看视频内容,以提高审核效率。既然运营提出了这样的需求,就得尽力去完成。

二.准备

首先从感性的角度分析该需求肯定可以实现的,毕竟软件开发技术已经是相当成熟了。只是暂时不知道什么技术可以实现该功能。于是,只能向度娘去请教了。经过一个时间的搜索发现有个叫javacv的开源框架似乎可以满足我的需求,那么就要花更多的时间去学习并动手实践一下。

三.开始

1.首先创建一个maven工程,工程名随意

2. 引入javacv需求的jar包,在pom.xml文件中添加

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

这里使用的是最新版本1.3.1

3. 从百度上搜索到一段代码

package com.javacv.test;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.List;import javax.imageio.ImageIO;
import org.bytedeco.javacv.FFmpegFrameGrabber;import org.bytedeco.javacv.Frame;import org.bytedeco.javacv.FrameGrabber.Exception;import org.bytedeco.javacv.Java2DFrameConverter;public abstract class FrameGrabberKit {public static void main(String[] args) throws Exception {//        randomGrabberFFmpegImage("e:/ffmpeg/aa.mp4", "./target", "screenshot", 5);randomGrabberFFmpegImage("e:/ffmpeg/ffmpeg.mp4", "./target", "screenshot", 5);}public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName, int randomSize)throws Exception {FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);ff.start();int ffLength = ff.getLengthInFrames();List<Integer> randomGrab = random(ffLength, randomSize);int maxRandomGrab = randomGrab.get(randomGrab.size() - 1);Frame f;int i = 0;while (i < ffLength) {f = ff.grabImage();if (randomGrab.contains(i)) {doExecuteFrame(f, targerFilePath, targetFileName, i);}if (i >= maxRandomGrab) {break;}i++;}ff.stop();}public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName, int index) {if (null == f || null == f.image) {return;}Java2DFrameConverter converter = new Java2DFrameConverter();String imageMat = "png";String FileName = targerFilePath + File.separator + targetFileName + "_" + index + "." + imageMat;BufferedImage bi = converter.getBufferedImage(f);File output = new File(FileName);try {ImageIO.write(bi, imageMat, output);} catch (IOException e) {e.printStackTrace();}}public static List<Integer> random(int baseNum, int length) {List<Integer> list = new ArrayList<>(length);while (list.size() < length) {Integer next = (int) (Math.random() * baseNum);if (list.contains(next)) {continue;}list.add(next);}Collections.sort(list);return list;}
}

注:该段代码只需要将main方法中的视频源地址修改成自己的地址即可运行。

运气还不错,代码能成功运行且能成功截图。本以为到此可以告一段落了,但经过几次的测试发现一个问题,截取出来的图片被旋转了。这可不是我想要的结果啊,没办法,只能继续去请教度娘。

4. 解决图片旋转问题

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

public static IplImage rotate(IplImage src, int rotate) {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;
}

那么现在需要解决的就是把Frame转换成IpImage,旋转后在转回Frame。

再次查看API发现OpenCVFrameConverter.ToIplImage提供了相互转换的接口

OpenCVFrameConverter.ToIplImageconverter =new OpenCVFrameConverter.ToIplImage();

converter有两个重载的方法converter(IplImage img)和converter(Frame frame)可以实现IpImage和Frame的相互转换。

至此,基本满足了所有需求,最终代码如下:

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import javax.imageio.ImageIO;

import org.bytedeco.javacpp.opencv_core;

import org.bytedeco.javacpp.opencv_core.IplImage;

import org.bytedeco.javacv.FFmpegFrameGrabber;

import org.bytedeco.javacv.Frame;

import org.bytedeco.javacv.FrameGrabber.Exception;

import org.bytedeco.javacv.Java2DFrameConverter;

import org.bytedeco.javacv.OpenCVFrameConverter;

public abstract class FrameGrabberKit {

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

//        randomGrabberFFmpegImage("e:/ffmpeg/aa.mp4", "./target", "screenshot", 5);

randomGrabberFFmpegImage("e:/ffmpeg/ffmpeg.mp4","./target","screenshot", 5);

}

public static void randomGrabberFFmpegImage(StringfilePath, StringtargerFilePath, StringtargetFileName,int randomSize)

throws Exception {

FFmpegFrameGrabberff = FFmpegFrameGrabber.createDefault(filePath);

ff.start();

Stringrotate =ff.getVideoMetadata("rotate");

int ffLength =ff.getLengthInFrames();

List<Integer>randomGrab =random(ffLength,randomSize);

int maxRandomGrab =randomGrab.get(randomGrab.size() - 1);

Framef;

int i = 0;

while (i <ffLength) {

f =ff.grabImage();

if (randomGrab.contains(i)) {

if(null !=rotate &&rotate.length() > 1) {

OpenCVFrameConverter.ToIplImageconverter =new OpenCVFrameConverter.ToIplImage();

IplImagesrc =converter.convert(f);

f =converter.convert(rotate(src, Integer.valueOf(rotate)));

}

doExecuteFrame(f,targerFilePath,targetFileName,i);

}

if (i >=maxRandomGrab) {

break;

}

i++;

}

ff.stop();

}

public static IplImage rotate(IplImage src,int angle) {

IplImageimg = 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(Framef, StringtargerFilePath, StringtargetFileName,int index) {

if (null ==f ||null ==f.image) {

return;

}

Java2DFrameConverterconverter =new Java2DFrameConverter();

StringimageMat ="png";

StringFileName =targerFilePath + File.separator +targetFileName +"_" +index +"." +imageMat;

BufferedImagebi =converter.getBufferedImage(f);

Fileoutput =new File(FileName);

try {

ImageIO.write(bi,imageMat,output);

}catch (IOExceptione) {

e.printStackTrace();

}

}

public static List<Integer> random(int baseNum,int length) {

List<Integer>list =new ArrayList<>(length);

while (list.size() < length) {

Integernext = (int) (Math.random() *baseNum);

if (list.contains(next)) {

continue;

}

list.add(next);

}

Collections.sort(list);

return list;

}

}

javacv使用笔记相关推荐

  1. 文件笔记之javaCV 视频工具|获取视频时长|缩略图

    文件笔记之javaCV 视频工具|获取视频时长|缩略图) 目录 简介 依赖引入 实现 目录 简介 通过javaCV 视频工具-截取视频缩略图.获取视频属性 依赖引入 <!--javaCV 视频工 ...

  2. 【读书笔记】知易行难,多实践

    前言: 其实,我不喜欢看书,只是喜欢找答案,想通过专业的解答来解决我生活的困惑.所以,我听了很多书,也看了很多书,但看完书,没有很多的实践,导致我并不很深入在很多时候. 分享读书笔记: <高效1 ...

  3. 【运维学习笔记】生命不息,搞事开始。。。

    001生命不息,搞事不止!!! 这段时间和hexesdesu搞了很多事情! 之前是机械硬盘和固态硬盘的测速,我就在那默默的看着他一个硬盘一个机械测来测去. 坐在他后面,每天都能看到这位萌萌的小男孩,各 ...

  4. SSAN 关系抽取 论文笔记

    20210621 https://zhuanlan.zhihu.com/p/353183322 [KG笔记]八.文档级(Document Level)关系抽取任务 共指id嵌入一样 但是实体嵌入的时候 ...

  5. pandas以前笔记

    # -*- coding: utf-8 -*- """ Created on Sat Jul 21 20:06:20 2018@author: heimi "& ...

  6. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  7. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  8. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  9. 王道考研 计算机网络笔记 第六章:应用层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 第二章:王道考研 计算机网络笔记 第 ...

  10. 王道考研 计算机网络笔记 第五章:传输层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 第二章:王道考研 计算机网络笔记 第 ...

最新文章

  1. HTML基础部分(3)iframe,提交信息的一些知识
  2. STM32开发 -- 无线网络协议
  3. Ubuntu安装及配置OpenCV3.2.0
  4. LINUX服务器出网带宽 一直被占用原因查找
  5. 微信小程序利用缓存提高接口请求性能
  6. hive 窗口函数_Datatist科技专栏 | Hive排序窗口函数速学教程!
  7. 938. 二叉搜索树的范围和
  8. shell出错test_path: command not found
  9. JavaScript清空数组的三种方法
  10. Diy页面服务端渲染解决方案
  11. Chika and Friendly Pairs(莫队+树状数组+离散化+预处理上下界)
  12. C语言程序设计精要,C语言程序设计精要.doc
  13. java下载文件名乱码的解决方法
  14. springboot 多线程_从零开始到架构,800页Java+并发+容器+多线程+高并发+Spring+SpringBoot源码...
  15. 基于PHP的个人博客网站系统
  16. java商城系统设计-----积分商城系统
  17. DTI处理工具包PANDA小白记录
  18. PCIE:如何获取PCIE学习资料文档
  19. java阿姆斯特朗数,Java判断阿姆斯特朗数
  20. 关于日期格式的书写及对应含义(便于查找)

热门文章

  1. 科来过滤jd提示语法解析器错误的解决问题方法
  2. onpropertychange oninput兼容性
  3. 中标麒麟的下载和安装
  4. windows系统查看md5
  5. 码农小汪-synchronized
  6. 码农小汪之Alibaba-fastjson的基本使用
  7. linux下查询utp命令,Linux后台下载工具(器)transmission 使用详解
  8. ADAS工程师的成长之路——ACC法规(ISO 15622-2018 — Adaptive cruise control systems)
  9. java留言功能_java web实现简单留言板功能
  10. 今日头条导航栏动画选中+recyclerview