李振海的gravatar头像
李振海 2018-01-01 21:02:04
javacv获取视频第一帧

公司网站需要上传视频,上传视频后在电脑浏览器上可以显示视频的封面,但是在手机微信浏览器上看不到封面,

在网上找了半天,说的最多的就俩中方法,这方面资源也挺少的,第一种是用ffmpeg工具,不过还得安装客户端软件,于是放弃了,还有一种是javacv开源工具,

今天讲的是第二种,javacv,

 <dependency>
        <groupId>org.bytedeco</groupId>
        <artifactId>javacv</artifactId>
        <version>0.8</version>
    </dependency>
/**
 * 获取指定视频的帧并保存为图片至指定目录
 * @param videofile  源视频文件路径
 * @param framefile  截取帧的图片存放路径
 * @throws Exception
 */
public static void fetchFrame(String videofile, String framefile)
        throws Exception {
    long start = System.currentTimeMillis();
    File targetFile = new File(framefile);
    FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); 
    ff.start();
    int lenght = ff.getLengthInFrames();
    int i = 0;
    Frame f = null;
    while (i < lenght) {
        // 过滤前5帧,避免出现全黑的图片,依自己情况而定
        f = ff.grabFrame();
        if ((i > 5) && (f.image != null)) {
            break;
        }
        i++;
    }
    IplImage img = f.image;
    int owidth = img.width();
    int oheight = img.height();
    // 对截取的帧进行等比例缩放
    int width = 800;
    int height = (int) (((double) width / owidth) * oheight);
    BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
            0, 0, null);
    ImageIO.write(bi, "jpg", targetFile);
    //ff.flush();
    ff.stop();
    System.out.println(System.currentTimeMillis() - start);
}

public static void main(String[] args) {
    try {
        Test.fetchFrame("http://wemewtest.oss-cn-qingdao.aliyuncs.com/2017-06-08-14/wKPPSfepDZ.mp4", "D:/new/test4.jpg");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

这是从

http://blog.csdn.net/syz_mumu/article/details/77203247

csdn博客上弄过来的,刚开始运行的时候没问题,可以正常截取,后来把手机视频放上去,截出来的是方向不对

javacv获取视频第一帧

左边是需要的,右边是通过上边工具截出来的,

最后又找了相关资料终于在

http://blog.csdn.net/z562743237/article/details/54667252

这篇博客的启发下,把方向调整过来了,

 解决图片旋转问题

通过一段时间的搜索了解到,如果拍摄的视频中带有旋转(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;  
}  

如果需要随机获取视频中的截图,那就去上边那个csdn博客里,我改了他的方法,获取的是视频的第一帧


import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
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("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();
        String rotate =ff.getVideoMetadata("rotate");
        Frame f;
        int i = 0;
        while (i <1) {
            f =ff.grabImage();
            IplImage src = null;
            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++;
        }

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

这个是


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

大家看清楚 jar包的版本,,javacv0.8和java1.3 的 f.image 不一样,大家自己改改,我喜欢用新版本,哈哈,觉得有用的话给点个赞,纯手写的


打赏

已有1人打赏

最代码官方的gravatar头像
最近浏览
ericfunny  LV9 2023年7月12日
cocon2  LV10 2021年11月8日
月之氏族  LV23 2021年6月22日
liaopf 2021年3月25日
暂无贡献等级
qwe3020618  LV1 2021年2月24日
ztztndnb 2021年1月8日
暂无贡献等级
小夏夏 2020年10月16日
暂无贡献等级
yy回忆天空  LV6 2020年8月12日
zzq229 2020年6月17日
暂无贡献等级
chaoqun 2020年5月19日
暂无贡献等级
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友