原理
原理很简单。一张图片的色彩,基本上由红绿蓝三基色构成。然后我们把对应颜色的像素用ascii字符来替代,这样就可以得到一张ascii字符画了,如果是视频,我们可以将视频读取到缓冲池,然后对视频的每一帧进行如上处理,最后将得到的ascii字符画合成,就得到了ascii动画。
步骤
第一步:我们先将图像转换为灰度图(使用黑色调表示物体,即用黑色为基准色,不同的饱和度的黑色来显示图像),然后让其通过一个阈值滤波器,此时就得到了一个黑白对比图。
第二步:我们可以将其与每个字符对比并计算差值。
第三步:接着,对每个图片块选取最相似的字符,一直进行下去,直到整个图像都转换完成。
第四步:根据需要调整阈值大小来影响对比度,并增强最终的结果。
为了实现这一点,一个非常简单的方法是将红、绿、蓝的值都设置成三种颜色的平均值:红=绿=蓝 =(红+绿+蓝)/ 3
代码实现
public Output convertImage(final BufferedImage source) { // 每个图块的尺寸 Dimension tileSize = this.characterCache.getCharacterImageSize(); // 四舍五入宽度和高度,所以我们避免部分字符 int outputImageWidth = (source.getWidth() / tileSize.width) * tileSize.width; int outputImageHeight = (source.getHeight() / tileSize.height) * tileSize.height; //从源图像中提取像素 int[] imagePixels = source.getRGB(0, 0, outputImageWidth, outputImageHeight, null, 0, outputImageWidth); // 将像素处理为灰度矩阵 GrayscaleMatrix sourceMatrix = new GrayscaleMatrix(imagePixels, outputImageWidth, outputImageHeight); //将矩阵分成小块以便于处理 TiledGrayscaleMatrix tiledMatrix = new TiledGrayscaleMatrix( sourceMatrix, tileSize.width, tileSize.height); this.output = initializeOutput(outputImageWidth, outputImageHeight); //比较每个图块与每个角色,以确定最合适的位置 for (int i = 0; i < tiledMatrix.getTileCount(); i++) { GrayscaleMatrix tile = tiledMatrix.getTile(i); float minError = Float.MAX_VALUE; Entry bestFit = null; for (Entry charImage : characterCache) { GrayscaleMatrix charPixels = charImage.getValue(); float error = this.characterFitStrategy.calculateError( charPixels, tile); if (error < minError) { minError = error; bestFit = charImage; } } int tileX = ArrayUtils.convert1DtoX(i, tiledMatrix.getTilesX()); int tileY = ArrayUtils.convert1DtoY(i, tiledMatrix.getTilesX()); // 复制字符到输出 addCharacterToOutput(bestFit, imagePixels, tileX, tileY, outputImageWidth); } finalizeOutput(imagePixels, outputImageWidth, outputImageHeight); return this.output;}
最终效果
![95ff1c0b332b3dcc2060b5cc1003831e.gif](https://i-blog.csdnimg.cn/blog_migrate/27517ac45da06e649ba3526d8c78a87a.gif)
原图
![7dbe9e67fba601cf3fe47518d9aff018.gif](https://i-blog.csdnimg.cn/blog_migrate/251a8929cd825e717cbc9a465aa1305b.gif)
ascii动图
评论或者私信获取源码。