用Java写一个Photo Mosaic

早在两星期前也写了个“马赛克拼图”,不过只支持黑白色的图片,昨天试了下拼彩色图片,先来一张预览图,效果还是可以的

用Java写一个Photo Mosaic_第1张图片


实现思路

1、准备大量小张方形素材,为了方便表述,姑且称这些图片为“Tile”

2、对于每一个Tile,作如下处理:

  1. 统一压缩成同一大小,我压缩成了32x32
  2. 计算平均RGB值
  3. “简化”RGB值,我这么做是因为Tile素材量还不够大,我希望能将平均RGB值相近的Tile都归为一组,分组也方便后面对原图匹配步骤。我将每R,G,B都简化成三种值,0,127,254(0x00,0x7f,0xfe),那么简化后RGB可以组成27种不同的颜色,这样一来会有27个RGB颜色的分组,可以用文件夹将它们分组,如下图(我用的Tile素材大约有1000来张,但是颜色分布  不是很均匀,所以实际只分出了20组,有7组是没有图片分进去的,后来我是手动调整了一下,也可能是因为我的分组算法存在点缺陷,有空优化一下)

用Java写一个Photo Mosaic_第2张图片

3、上面都是Tile的准备,下面开始处理做拼接,先准备一张原图片,将它压小一点,建议高宽在60~100之间,太小效果不好,太大处理量会很大,至于怎么压缩有多种方法,可以直接用画图,也可以调用Java的API

4、读取压缩后的图片每一点的RGB值,将它“归类”到RGB最相近的Tile分组,例如某点rgb值是0x12f97e,最近的RGB值是0x00fe7f,然后从分组的多张图片里随机挑选一张Tile,在相应坐标上绘制这张Tile,这个坐标计算很容易,例如取(2,4)点的RGB值,Tile的大小是32x32,那么我应该把Tile摆在(64, 128)这点上,因为(2x32, 4x32)=(64, 128)

5、关于怎么让每次在同一分组上挑选的图片“随机”也是个重要的问题,因为对于原图片大片同色区域,都用同一张Tile效果 可反而不是很好。可以用简单的随机数生成,我的做法是将分组里的图片随机排列,按排列顺序依次取Tile,当取到最后一张Tile时,重新打乱这个排列,从开头开始取Tile。当然有效果更好的方法是每次取Tile都检测下周围是否已经用过这张Tile,当然这样开销会大一点,算法实现起来也复杂一点


实现代码

这里就不全部贴出来了,代码我放在github上

https://github.com/Kurozaki/color-graphic-mosaic


你可能感兴趣的:(算法,Java,图像)