原理
原理很简单。一张图片的色彩,基本上由红绿蓝三基色构成。然后我们把对应颜色的像素用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<Character, GrayscaleMatrix> bestFit = null;
for (Entry<Character, GrayscaleMatrix> 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;
}
最终效果
评论或者私信获取源码。