只需45秒,Python给故宫画一组手绘图!

百家 作者:AI100 2019-02-18 06:59:59


作者?|?丁彦军

来源 |?恋习Python(ID:sldata2017

责编?|?swallow


13日早晨,当北京市民拉开窗帘时发现,窗外雪花纷纷扬扬在空中飘落,而且越下越大,树上、草地、屋顶、道路上,都落满雪花。京城银装素裹,这是今冬以来北京迎来的第二场降雪。

一下雪,北京就变成了北平,故宫就变成了紫禁城。八万张门票在雪花飘下来之前,便早已预订一空。

(图片来源:故宫官网?版权归故宫官网所有)


<iframe class="video_iframe" data-vidtype="1" data-cover="http%3A%2F%2Fshp.qpic.cn%2Fqqvideo_ori%2F0%2Fo0837086i8e_496_280%2F0" allowfullscreen="" frameborder="0" data-ratio="1.894736842105263" data-w="864" data-src="http://v.qq.com/iframe/player.html?vid=o0837086i8e&width=352&height=198&auto=0" width="352" height="198" data-vh="198" data-vw="352" style="display: none; width: 352px !important; height: 198px !important;"></iframe>


看着朋友圈、微博好友都在纷纷晒图,小编只能羡慕不已。


不过,突然想到,可以通过Python将故宫的建筑物图片,转化为手绘图(素描效果)。效果图如下:



一、概念与原理


我们都知道手绘图效果的特征主要有:


  • 黑白灰色;边界线条较重;相同或相近色彩趋于白色;略有光源效果


核心原理:利用像素之间的梯度值和虚拟深度值对图像进行重构,根据灰度变化来模拟人类视觉的模拟程度


把图像看成二维离散函数,灰度梯度其实就是这个二维离散函数的求导,用差分代替微分,求取图像的灰度梯度。常用的一些灰度梯度模板有:Roberts 梯度、Sobel 梯度、Prewitt 梯度、Laplacian 梯度。


以Sobel 梯度计算来解释:


首先计算出?,然后计算梯度角?梯度方向及图像灰度增大的方向,其中梯度方向的梯度夹角大于平坦区域的梯度夹角。如下图所示,灰度值增加的方向梯度夹角大,此时梯度夹角大的方向为梯度方向。对应在图像中寻找某一点的梯度方向即通过计算该点与其8邻域点的梯度角,梯度角最大即为梯度方向。



二、图像的数组形式与变换



其中,需要用到的方法:


  • Image.open( ):?打开图片

  • np.array( )?: 将图像转化为数组

  • convert("L"):?将图片转换成二维灰度图片

  • Image.fromarray( ):?将数组还原成图像uint8格式


代码如下:


from?PIL?import?Image
import?numpy?as?np

im?=?Image.open(r"C:UsersAdministratorDesktopgugong微信图片_20190216152248.jpg").convert('L')
a=np.asarray(im).astype('float')
print(a.shape,a.dtype)
(1080,?608)?float64
#(1080,?608)分别表示高度,宽度


三、图像的手绘效果处理


实现思路步骤:


1、梯度的重构


numpy的梯度函数的介绍


np.gradient(a) : 计算数组a中元素的梯度,f为多维时,返回每个维度的梯度?

离散梯度: xy坐标轴连续三个x轴坐标对应的y轴值:a, b, c 其中b的梯度是(c-a)/2?


而c的梯度是: (c-b)/1


当为二维数组时,np.gradient(a) 得出两个数组,第一个数组对应最外层维度的梯度,第二个数组对应第二层维度的梯度。?


代码如下:


grad=np.gradient(a)
grad_x,grad_y=grad
grad_x?=?grad_x?*?depth?/?100.#对grad_x值进行归一化
grad_y?=?grad_y?*?depth?/?100.#对grad_y值进行归一化


2、构造guan光源效果


设计一个位于图像斜上方的虚拟光源
光源相对于图像的视角为Elevation,方位角为Azimuth
建立光源对各点梯度值的影响函数
运算出各点的新像素值



其中:

np.cos(evc.el) :?单位光线在地平面上的投射长度

dx,dy,dz :光源对x,y,z三方向的影响程度


3、梯度归一化


  • 构造x和y轴梯度的三维归一化单位坐标系;

  • 梯度与光源相互作用,将梯度转化为灰度。


4、图像生成


具体详情代码如下:


from?PIL?import?Image
import?numpy?as?np
import?os
import?join
import?time

def?image(sta,end,depths=10):
????a?=?np.asarray(Image.open(sta).convert('L')).astype('float')
????depth?=?depths??#?深度的取值范围(0-100),标准取10
????grad?=?np.gradient(a)??#?取图像灰度的梯度值
????grad_x,?grad_y?=?grad??#?分别取横纵图像梯度值
????grad_x?=?grad_x?*?depth?/?100.#对grad_x值进行归一化
????grad_y?=?grad_y?*?depth?/?100.#对grad_y值进行归一化
????A?=?np.sqrt(grad_x?**?2?+?grad_y?**?2?+?1.)
????uni_x?=?grad_x?/?A
????uni_y?=?grad_y?/?A
????uni_z?=?1.?/?A
????vec_el?=?np.pi?/?2.2??#?光源的俯视角度,弧度值
????vec_az?=?np.pi?/?4.??#?光源的方位角度,弧度值
????dx?=?np.cos(vec_el)?*?np.cos(vec_az)??#?光源对x?轴的影响
????dy?=?np.cos(vec_el)?*?np.sin(vec_az)??#?光源对y?轴的影响
????dz?=?np.sin(vec_el)??#?光源对z?轴的影响
????b?=?255?*?(dx?*?uni_x?+?dy?*?uni_y?+?dz?*?uni_z)??#?光源归一化
????b?=?b.clip(0,?255)
????im?=?Image.fromarray(b.astype('uint8'))??#?重构图像
????im.save(end)

def?main():
????xs=10
????start_time?=?time.clock()
????startss?=?os.listdir(r"C:UsersAdministratorDesktopgugong")
????time.sleep(2)
????for?starts?in?startss:
????????start?=?''.join(starts)
????????sta?=?'C:/Users/Administrator/Desktop/gugong/'?+?start
????????end?=?'C:/Users/Administrator/Desktop/gugong/'?+?'HD_'?+?start
????????image(sta=sta,end=end,depths=xs)

????end_time?=?time.clock()
????print('程序运行了??----'?+?str(end_time?-?start_time)?+?'???秒')
????time.sleep(3)

main()
程序运行了??----43.01828205879955???秒??#一共35张图片


最终效果图对比:



最后,你自己动手试试吧?通过此代码为自己画一张手绘图,也可以为自己的家乡或母校画。


参考资料:

http://www.icourse163.org/learn/BIT-1001870002?tid=1001963001#/learn/announce

代码链接:

https://pan.baidu.com/s/1E_aZTRQWOzGV-2GV_iH43w

提取码:64z9

(本文为AI科技大本营转载文章,转载请联系原作者)

精彩推荐

推荐阅读:

? ? ? ? ? ? ? ? ? ? ? ? ?

点击“阅读原文”,打开CSDN?APP?阅读更贴心。

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接