JavaCV实现视频抽帧 JFrame字符动画

本文实现对视频进行抽帧,将视频图片转换成字符图片,在使用JFrame实现图片的连续播放。

javaCV实现对视频进行抽帧

		<!-- 首先引入javaCv的相关依赖 -->
		<dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.6</version>
        </dependency>
		// 进行视频的图片提取
		// 需要处理的视频位置
        String videoPath = "C:\\tmp\\videoDemo\\video\\1.mp4";
        // 存放图片的位置
        String imagePath = "C:\\tmp\\videoDemo\\image\\";
        // javaCv提供的视频处理
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath);
        ff.start();
        // 获取视频帧的长度
        int ffLength = ff.getLengthInFrames();
        System.out.println("ffLength = " + ffLength);
        // 提取视频中图片帧的间隔
        int interval = 1;
        for (int i = 0; i < ffLength; i++) {
            // 获取视频帧
            Frame frame = ff.grab();
            // 帧的类型
            EnumSet<Frame.Type> types = frame.getTypes();
            // VIDEO类型代表是图片,提取出来转换成图片
            if (types.contains(Frame.Type.VIDEO) && i % interval == 0) {
                if (frame.image == null) {
                    continue;
                }
                // 使用Java2DFrameConverter将帧转换成图片
                Java2DFrameConverter converter = new Java2DFrameConverter();
                String imgSuffix = "png";
                // 对应的目录写入图片
                String fileName = imagePath + File.separator + i + "." + imgSuffix;
                BufferedImage bufferedImage = converter.getBufferedImage(frame);
                ImageIO.write(bufferedImage, imgSuffix, new File(fileName));
                System.out.printf("执行:%d/%d%n", i, ffLength);
            }
        }
        ff.stop();
    }

以下是对视频进行提取后的图片:
在这里插入图片描述

图片转换

// 将提取出来的视频图片转换成字符图片
        String imageDir = "C:\\tmp\\videoDemo\\image";
        String targetDir = "C:\\tmp\\videoDemo\\charImage\\";
        File imageDirFile = new File(imageDir);
        File[] files = imageDirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            String absolutePath = file.getAbsolutePath();
            String fileName = file.getName();
            String targetFile = targetDir + fileName;
            // 转换成对应的视频图片,转换方法https://blog.csdn.net/weixin_45485300/article/details/121716788
            ImageOut.characterPainting("love", 0, absolutePath, targetFile, false);
            System.out.printf("%d/%d%n", i, files.length);
        }

转换后:
在这里插入图片描述

JFrame实现图片播放

public static void main(String[] args) {
        // 使用JFrame实现图片的播放
        ImageJPanel imageJPanel = new ImageJPanel();
        Thread thread = new Thread(imageJPanel);
        JFrame jFrame = new JFrame();
        // 添加图片
        jFrame.add(imageJPanel);
        // 设置尺寸,保持或图片大小一致即可
        jFrame.setSize(1920, 1080);
        // 设置可见
        jFrame.setVisible(true);
        // 窗口居中
        jFrame.setLocationRelativeTo(null);
        // 设置窗口关闭
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        thread.start();
    }

    static class ImageJPanel extends JPanel implements Runnable {

        // 进行渲染的图片
        private BufferedImage bufferedImage;

        // 图片地址
        private String path = "C:\\tmp\\videoDemo\\charImage";

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            if (bufferedImage != null) {
                // 绘制图片 参数是图片 x坐标 y坐标 图片渲染的一些回调通知,可以不用
                g.drawImage(bufferedImage, 0, 0, null);
            }
        }

        @Override
        public void run() {
            try {
                // 使用线程来加载的图片
                File file = new File(path);
                File[] files = file.listFiles();
                // 对图片进行一个排序,因为图片是按数字来命名的,读取的时候是按字典顺序来读取的,会出现114.png排在90.png的前面
                Arrays.sort(files, (f1, f2) -> {
                    String name = f1.getName();
                    String[] f1Index = name.split("\\.");
                    String f2Name = f2.getName();
                    String[] f2Index = f2Name.split("\\.");
                    return Integer.valueOf(f1Index[0]) - Integer.valueOf(f2Index[0]);
                });
                for (File imgFile : files) {
                    // 读取图片
                    bufferedImage = ImageIO.read(imgFile);
                    // 控制图片渲染的速度
                    Thread.sleep(50);
                    // 重新绘制
                    repaint();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

效果:
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dichotomy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值