最近因为研一的课程、作业太多,平时很少有时间干自己的事情,也好久没有写新的文章。而且!!!最倒霉的是,我的算法课由于前两节没选课!导致不知道作业还有截止时间,oh,fuck!!少交了好几次哦我滴龟龟!!
嘛,吐槽完了,开始正题。前段时间基于C++做了一个Normal map的生成器。用处是把一副图像转换成Normal map,对于我们做Graphics的人来说,还是蛮有用的。
首先还是惯例贴一下实验结果:
一、Experimental Results
(1) Mapping on sphere with a stone picture.
(2) Mapping on plane with an anime picture.
(3) Mapping on a soldier model with a wall picture.
(4) A result set of my program.(Pair of original image and normal image)
二、我提供的一些资源:
1. 程序的下载链接:
2. 参考文献:
三、算法原理
下图是本文采用的Normal map generator的pipeline。使用该方法获得到的Normal map和常规方法的要平滑逼真的多。
1. 获取原始图像的grayscale image.
首先,加载一副彩色图像,并将其转换为灰度图像,即Grayscale Image。采用下式来将r,g,b值转换为灰度gray:
此时设点(i,k)处的灰度值记为G(i,k)。
2. 利用gradient来计算初步的Normal map 1
这里我们利用更高的grayscale image来获取一个初步的Normal Map。由于Normal是一个三维向量(x,y,z),所以我们利用如下方法来计算点(i,k)处的法向量:
利用Sobel算法来计算水平和数值方向的梯度,即:
此时,点(i,k)处的Normal值即:
其中,是一个修正量,默认可以是1.0。通过这一步获取到的图像可以就是初步的Normal map 1。
3. 对downscale后的image重新计算一个缩小的中间normal map 2
虽然通过上面的步骤就能够得到一个初步的Normal map 1,但是仅仅这样获取到的Normal map是不够光滑的。因此,我们这里采用一种PS中常用的手段来对修正法线。
我们对原始图像进行一个降采样,即缩小输入的Grayscale Image。例如,缩小至原来的50%。然后对这个缩小后的Grayscale Image进行第2步中的处理,求得一个缩小的Normal map2
4. 将两个Normal map合并得到最终的法线图
将缩小后的Normal map2放大回原来的大小,然后与Normal map1求一个平均,这样就得到了最终的Normal map。