[Java]代码实现图像转换成文本

版权声明:本文为博主原创文章,转载请申明出处,感谢。 https://blog.csdn.net/shichimiyasatone/article/details/86607425

一、前言

前天在B站看到一个将鬼畜视频转成文本的视频,觉得很有意思就去研究了下如何在JAVA中实现类型功能。主要使用了ffmpeg和JAVA API中的BufferedImage与ImageIO类,完整项目的压缩文件放在GitHub上。

二、图片转为文本

以一个彩色图片作为输入,通过处理,最后输出一串字符到文本中,要求文本中的字符能够尽量表示原图片中的内容。

首先我们需要将彩色图片处理正黑白图片,处理方式有两种:

  • 使用ColorSpace.CS_GRAY(灰色颜色空间)对原图片进行滤波,生成黑白图片
  • 使用自定义方式,将原图片中的每个彩色像素点映射成黑白像素

两种方法都已通过代码实现,主要讲第二种自定义方法。在JAVA中默认色域的图片,每个像素为一个int值。该值得高8位代表像素的透明度,低24位代表BGR三种颜色。我们只需要将图片读入内存,通过方法取出每个像素点的int值,再想办法把该值降低到[0,255]这个区间即可。

// 将文件(图片)读入内存
BufferedImage img = ImageIO.read(file);
// 通过对低24位开三次方,将值降低到[0, 255]
Math.floor(Math.cbrt(img.getRGB(c, r) & 0xFFFFFF));

你可以这么理解[0, 255]这个区间:

  • RGB中R代表该像素中红色的值,G代表绿色,B代表蓝色
  • 当RGB都为255时,此时为白色。高中也学过光的散射,当所有颜色的光聚集起来就是白色光。
  • 当RGB都为0时,此时为黑色。
  • 所以黑白图片中每个像素的颜色深度范围可以用[0, 255]表示

将彩色像素处理成代表黑白深度的像素后,通过对该值进行判断,判断使用哪种字符代表它即可。例如,你可以拿“R”来代表一个较深的颜色,以“.”代表一个较浅的颜色。每个人的视觉感官不同,可以使用自己满意的字符代替。

得到代表整个彩色图片的字符串后,将文本写入至txt文件中即可,查看时可使用notepade++,对字体进行缩放(Ctrl+鼠标滚轮)方便观察。

三、视频转成文本

基于上面的原理,我们只需要将视频转换成帧,再将代表每一帧的字符串写入文本显示即可。

通过使用FFmpeg工具,我们可以很方便地获得一个视频的帧,具体cmd命令:

// 获取输入视频的帧,每张图大小为600*500,以frame加4位整数命名
ffmpeg -i input.mp4 -s 600x500 frame%4d.jpg

在代码中使用Runtime类的exec()方法执行该命令时需要注意的是,即便已在系统环境变量中配置了ffmpeg.exe的位置,也需要通过全路径去访问,代码为:

// 获取当前Java应用程序关联的运行时对象
Runtime runtime = Runtime.getRuntime();
// 设置命令
String cmd = "D:\\FFmpeg\\bin\\ffmpeg.exe -i input.mp4 -s 600x500 frame%4d.jpg";
// 执行命令
runtime.exec(cmd);

// 也可以使用Process对象对返回结果进行判断
//Process proce = runtime.exec(cmd);

由于持续将每一帧的字符串写入txt文件,使用notepade++查看起来的效果差强人意。代码里直接使用swing里的JTextArea,效果要稍微好些。

JTextArea textArea = new JTextArea();
// 建议使用黑体,大小为3的字体,或者其它显示效果好的设置都可
textArea.setFont(new Font("黑体", Font.BOLD, 3));

四、输出结果

  • 图片转文本
彩色原图
输出文本
  •  视频转文本
文本截图

CSDN不让传超过5M的图片,动态文本的gif图也放GitHub上了,有兴趣的可以去查看

猜你喜欢

转载自blog.csdn.net/shichimiyasatone/article/details/86607425