转载

用Java生成字符画(2)

在上一篇博客里我用Java创建了一个简单的Ascii 字符画生成器(可以从 GitHub 上获取), 文章发布之后我收到了很多反馈。所以今天我打算继续在这个项目上添加一些新特性,期待能受到更多欢迎。我重新设计了核心部分,目的是增加扩展性以便测试不同的算法以及产生多样化的结果。 在本文中,我会展示本项目的全新架构,方便您整合进自己的项目中以及根据需要进行扩展。

架构

用Java生成字符画(2)

AsciiImgCache

在任何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));

BestCharacterFitStrategy

这是一个算法的抽象,用来判断源图像与每个字符的相似度。该抽象只有一个方法:

float calculateError(final GrayscaleMatrix character, final GrayscaleMatrix tile);

对于具体的实现来说,它应该比较两个图片并返回浮点格式的偏差值。每个字符都会被用来进行比较,最终采用返回最小偏差值的字符。目前有两种实现:

ColorSquareErrorFitStrategy

这个实现非常容易理解。 它比较每个像素然后计算 灰度差异的均方误差 (Mean squared error)。

数学表达式如下:

用Java生成字符画(2)

其中n代表像素的数量, C和T分别代表字符和tile图像的像素。

StructuralSimilarityFitStrategy

结构相似性(SSIM)索引算法声称能还原人类视角,其目标是提升传统的诸如MSE的算法。此处我不打算详细解释其原理,如果你感兴趣可以在 Wikipedia 上阅读相关资料。我自己也进行了一些尝试并实现了一个版本,似乎能在我们的用例中获得不错的结果。

AsciiConverter

这是整个流程的核心,它包含源图像取样(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

下一步工作

下面是对未来工作的一些想法:

  • 研究并实现更多的图像比较算法。
  • 对图片重新处理达到更佳效果(改进对比度,使用边缘监测等)。
  • 通过并行处理改进图像处理效果,根据结果评估是否值得改进。
  • 增加一些转换格式(比如html输出)。
  • 支持输出带颜色的字符。
  • 为项目添加测试。

对代码有建议或者发现任何问题,欢迎通过 GitHub 评论和提交!

原文链接: korhner 翻译:ImportNew.com -jakiewoo

译文链接:[]
正文到此结束
Loading...