Low-Poly图像生成器

前些天在知乎上看到有一个《如何使用JavaScript生成lowpoly风格图像?》的帖子,觉得十分有趣。同时心里想,能不能使用Java来实现呢?要不试试吧!

于是,在摸索了几天之后,终于做出来了。我整理了下,发布到github上面,感兴趣的同学可以clone下来玩玩!喜欢的话star一下吧!

原始图:

source image

结果图:

result image

关于生成的过程算法,原作者羡辙已经在那个知乎帖子上回答的很详细了,这里稍微整理下。

首先,从最终结果看,其实就是将原图片切割成一个个小三角形,每个三角形使用颜色填充。

显然,我们需要在原图上面先挑选一些点作为三角形的顶点,然后生成一个个小三角形。对于挑选顶点的方法待会再说明,现在假设已经挑选出来一些顶点了,我们应该怎么三角化呢?

triangulation

你看,即便在顶点集相同的情况下,生成三角形的方式不止一种。经过对比,我们发现当三角形的每个角都基本相同的时候,这些三角形组成的图片最好看。对于上图来说,第一种三角化的结果最理想。

我们可以使用Delaunay算法来实现点集的三角化。感兴趣的同学可以深入研究下,这里不展开辣!值得一提的是,在摸索的过程中,我尝试了很多种开源的Delaunay Java实现,但是不知道哪里不对,都没有成功…于是在看了这个Javascript实现之后,觉得代码量很小,于是乎便参照它写了个Java实现

现在,三角化的问题我们解决了,那我们应该挑选哪些点作为顶点集呢?随机挑选点的做法会破换掉原图里面的边缘特性,所以应该挑选原图里面边缘上的点。但是如果仅仅挑选边缘点最终三角化后会有很多尖锐的三角形,因此除了挑选边缘上的点,我们还应该挑选一定量的非边缘点。

但怎么确定图片里面的边缘呢?这里我们可以使用Canny边缘检测算法,在实现上我使用了Tom Gibara的开源实现。大家如果想了解下这个算法,可以看下这篇文章

这样我们就基本完成low-poly的过程了,总结下就是:

  1. 使用Canny边缘检测算法检测图像边缘
  2. 挑选边缘点和一定量的非边缘点作为三角化的顶点集
  3. 使用Delaunay进行三角化
  4. 对三角形填充颜色

其中第四步中,三角形的颜色可以采用三角形重心的颜色来填充。

以上。

Written on June 2, 2016