让代码跳绳 java 实现视频转字符画

java 实现视频转字符画

作为一个萌新,也想尝试写写教程。哈哈哈,高手误喷啊。不重复造轮子,很多代码参考其他大神

之前看到网上有很多字符画,感觉很炫,也想尝试完成下。csdn中只找到了python实现的。我们的大java怎么没有呢

话不多少先上效果

效果图

思路分析

  • 对视频进行抽帧得到图片
  • 对图片进行处理得到字符画
  • 按照一定顺序和一定时间在终端打印字符画实现动画效果代码实现

代码实现

为了快速实现功能和方便同学们,这里使用了maven

<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.0</version>
        </dependency>

对视频进行抽帧得到图片 

public class VideoToImage {

    /**
     * 视频抽帧
     * @param filePath 批量处理,视频所在文件夹
     * @param targetPath 输出图片文件夹
     * @throws Exception
     */
    public static void videoToImage(String filePath,String targetPath ) throws Exception {
        File file = new File(filePath);
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (int i=0; i<files.length; i++) {
                String fpath = files[i].getParent()+"\\"+files[i].getName();
                //System.out.println(fpath);
                String fileName = files[i].getName();
                randomGrabberFFmpegImage(fpath, targetPath, fileName.substring(0, fileName.length()-4));
            }
        }
    }

    public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName)
            throws Exception {
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        int ffLength = ff.getLengthInFrames();
        System.out.println(ffLength);
        System.out.println("帧率: " + ff.getFrameRate());
        System.out.println("视频长度: " + ff.getLengthInTime());
        Frame f;
        int t = 3;		//抽帧间隔,可以自行调节
        for (int k=0; k<ffLength; k++){
            String format = String.format("%05d", k);
            f = ff.grabImage();
            if (k%t==0){
                doExecuteFrame(f, targerFilePath, targetFileName, format);
            }
        }
        ff.stop();
    }

    public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName, String index) {
        if (null == f || null == f.image) {
            return;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        String imageMat = "jpg";
        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 class ImageToStr {
    /**
     * 图片转字符
     * @param filePath
     * @param targetPath
     */
    public static void createAsciiPic(String filePath,String targetPath) {
        //final String base = "@#&$%*o!;.";// 字符串由复杂到简单
        final String base = "KSPksp;,";
        try {	//输出图片文件夹
            File file = new File(filePath);
            FileWriter fileWriter = null;
            fileWriter = new FileWriter(targetPath);//创建文本文件
            BufferedWriter bw = new BufferedWriter(fileWriter);
            if (file.isDirectory()){
                File[] files = file.listFiles();
                System.out.println(files.length);
                for (int i=0; i<files.length; i++) {
                    //System.out.println(files[i].getName());
                    BufferedImage image = ImageIO.read(files[i]);
                    for (int y = 0; y < image.getHeight(); y += 4) {
                        StringBuilder sss=new StringBuilder ( "" );
                        for (int x = 0; x < image.getWidth(); x+=2) {
                            final int pixel = image.getRGB(x, y);
                            final int r = (pixel & 0xff0000) >> 16, g = (pixel & 0xff00) >> 8, b = pixel & 0xff;
                            final float gray = 0.299f * r + 0.578f * g + 0.114f * b;
                            final int index = Math.round(gray * (base.length() + 1) / 255);
                            sss.append(index >= base.length() ? " " : String.valueOf(base.charAt(index)));
                        }
                        String s = sss.toString()+"\r\n";
                        bw.write(s);// 往已有的文件上添加字符串
                    }
                }
            }
            bw.close();
            fileWriter.close();
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }
}

按照一定顺序和一定时间在终端打印字符画实现动画效果代码实现 

public class TextMove {
    private static final int FRAME_WIDTH = 900;
    private static final int FRAME_HEIGHT = 900;
    /**
     * 字符动画
     * @param filePath
     * @throws IOException
     * @throws InterruptedException
     */
    public static void textMove(String filePath) throws IOException, InterruptedException {
        //JFrame的相关内容自行学习
        JFrame frame = new JFrame();
        frame.setTitle("字符动画");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(0,0,FRAME_WIDTH,FRAME_HEIGHT);
        frame.setResizable(false); //设置框架是否可由用户调整大小。
        frame.setUndecorated(false); //禁用或启用此框架的装饰
        JTextArea area = new JTextArea();
        area.setBackground(Color.white);
        area.setForeground(Color.BLACK);
        area.setBounds(0,0,FRAME_WIDTH,FRAME_HEIGHT);
        area.setFont(new Font("微软雅黑",Font.PLAIN,10));
        frame.add(area);
        frame.setVisible(true);
        File file =new File(filePath);
        show(area,file);
    }

    /**
     * 显示到窗口
     * @param area
     * @param file
     * @throws IOException
     * @throws InterruptedException
     */
    public static void show(JTextArea area, File file) throws IOException, InterruptedException {
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        StringBuffer sb = new StringBuffer();
        int line = 0;
        int page = 0;
        String[] pageStr=new String[41];
        while (line <= 4000 ) {  //总行数
            String str = br.readLine();
            sb.append(str+"\r\n");
            line++;
            if(line%100 == 0){  // 每帧的行数
                page++;
                //System.out.print(sb);
                pageStr[page] = sb.toString();
                sb = new StringBuffer();
                area.setText(pageStr[page]);
                Thread.sleep(25L); //视觉暂留
            }
        }
        for(int j=0;j<1000;j++){
            for(String sss : pageStr){
                area.setText(sss);
                Thread.sleep(25L);
            }
        }

    }
}

最后把这三个步骤串起来

    public static void main(String[] args) throws Exception {
        //对视频进行抽帧得到图片
        VideoToImage.videoToImage("E:\\testmp4","E:\\pic");
        //对图片进行处理得到字符画
        ImageToStr.createAsciiPic("E:\\pic","E:\\a.txt");
        //按照一定顺序和一定时间在终端打印字符画实现动画效果代码实现
        TextMove.textMove("E:\\a.txt");
    }

最后一步  “按照一定顺序和一定时间在终端打印字符画实现动画效果代码实现 ” 大家根据不同视频大小可以自行调整。也有很多其他实现的方式,希望大家提出更好的解决方案。

好了大功告成 。The Good Night!

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值