在上一篇博客里我用Java创建了一个简单的Ascii 字符画生成器(可以从 GitHub 上获取), 文章发布之后我收到了很多反馈。所以今天我打算继续在这个项目上添加一些新特性,期待能受到更多欢迎。我重新设计了核心部分,目的是增加扩展性以便测试不同的算法以及产生多样化的结果。 在本文中,我会展示本项目的全新架构,方便您整合进自己的项目中以及根据需要进行扩展。
在任何ascii字符渲染发生前,我们需要创建一个此类的实例。 它需要一个字体和字符列表作为参数,然后它将为每个字符生成一个图片的Map。如果你嫌麻烦,也有默认的字符列表提你选择。
提供给对此感兴趣的读者:
private static final char[] defaultCharacters = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft///|()1{}[]?-_+~<>i!lI;:,/"^`'. "
示例
// use only '/' '/' and ' ' AsciiImgCache mediumBlackAndWhiteCache = AsciiImgCache. create(new Font("Courier", Font.BOLD, 10), new char[] {'//', ' ', '/'}); // use default list AsciiImgCache largeFontCache = AsciiImgCache. create(new Font("Courier",Font.PLAIN, 16));
这是一个算法的抽象,用来判断源图像与每个字符的相似度。该抽象只有一个方法:
float calculateError(final GrayscaleMatrix character, final GrayscaleMatrix tile);
对于具体的实现来说,它应该比较两个图片并返回浮点格式的偏差值。每个字符都会被用来进行比较,最终采用返回最小偏差值的字符。目前有两种实现:
这个实现非常容易理解。 它比较每个像素然后计算 灰度差异的均方误差 (Mean squared error)。
数学表达式如下:
其中n代表像素的数量, C和T分别代表字符和tile图像的像素。
结构相似性(SSIM)索引算法声称能还原人类视角,其目标是提升传统的诸如MSE的算法。此处我不打算详细解释其原理,如果你感兴趣可以在 Wikipedia 上阅读相关资料。我自己也进行了一些尝试并实现了一个版本,似乎能在我们的用例中获得不错的结果。
这是整个流程的核心,它包含源图像取样(tiling)的逻辑,调用具体实现计算出最匹配的字符。然而,它并不知道如何创建ascii 字符 – 这需要子类来实现。 目前有两个实现:AsciiToImageConverter and AsciiToStringConverter – 顾名思义,它们分别输出图像和字符串。
正所谓埋头苦干胜于纸上谈兵,下面就整合各个部分,给大家展示整个流程:
// initialize cache AsciiImgCache cache = AsciiImgCache.create(new Font("Courier",Font.BOLD, 6)); // load image BufferedImage portraitImage = ImageIO.read(new File("image.png")); // initialize converters AsciiToImageConverter imageConverter = new AsciiToImageConverter(cache, new ColorSquareErrorFitStrategy()); AsciiToStringConverter stringConverter = new AsciiToStringConverter(cache, new StructuralSimilarityFitStrategy()); // image output ImageIO.write(imageConverter.convertImage(portraitImage), "png", new File("ascii_art.png")); // string converter, output to console System.out.println(stringConverter.convertImage(portraitImage));
下面还有一些通过设置不同参数产生的图片:
原始图片
16 pts字体,MSE
16 pts 字体, SSIM
10 pts 字体3字符 ,MSE
10 pts字体3字符,SSIM
6 pts字体,MSE
6 pts字体,SSIM下面是对未来工作的一些想法:
对代码有建议或者发现任何问题,欢迎通过 GitHub 评论和提交!
原文链接: korhner 翻译:ImportNew.com -jakiewoo
译文链接:[]