作者 | 丁彥軍
責編 | 屠敏
13日早晨,當北京市民拉開窗簾時發現,窗外雪花紛紛揚揚在空中飄落,而且越下越大,樹上、草地、屋頂、道路上,都落滿雪花。京城銀裝素裹,這是今冬以來北京迎來的第二場降雪。
一下雪,北京就變成了北平,故宮就變成了紫禁城。八萬張門票在雪花飄下來之前,便早已預訂一空。
看著朋友圈、微博好友都在紛紛曬圖,作為程式設計師的我只能坐在辦公室裡羨慕不已。
不過普通人得去故宮賞雪,程式設計師可以直接坐在家裡動動手指便可以欣賞到故宮的美麗雪景手繪圖了。如何操作呢?可通過Python將故宮的建築物圖片,轉化為手繪圖(素描效果)。效果圖如下:
概念與原理
我們都知道手繪圖效果的特徵主要有:
黑白灰色
邊界線條較重
相同或相近色彩趨於白色
略有光源效果
核心原理:利用像素之間的梯度值和虛擬深度值對圖像進行重構,根據灰度變化來模擬人類視覺的模擬程度。
把圖像看成二維離散函數,灰度梯度其實就是這個二維離散函數的求導,用差分代替微分,求取圖像的灰度梯度。常用的一些灰度梯度模板有:Roberts 梯度、Sobel 梯度、Prewitt 梯度、Laplacian 梯度。
以Sobel 梯度計算來解釋:
首先計算出、,然後計算梯度角
梯度方向及圖像灰度增大的方向,其中梯度方向的梯度夾角大於平坦區域的梯度夾角。如下圖所示,灰度值增加的方向梯度夾角大,此時梯度夾角大的方向為梯度方向。對應在圖像中尋找某一點的梯度方向即通過計算該點與其8鄰域點的梯度角,梯度角最大即為梯度方向。
圖像的數組形式與變換
其中,需要用到的方法:
Image.open( ): 打開圖片
np.array( ) : 將圖像轉化為數組
convert("L"): 將圖片轉換成二維灰度圖片
Image.fromarray( ): 將數組還原成圖像uint8格式
代碼如下:
圖像的手繪效果處理
實現思路步驟:
1、梯度的重構
numpy的梯度函數np.gradient(a) : 計算數組a中元素的梯度,f為多維時,返回每個維度的梯度。
離散梯度: xy坐標軸連續三個x軸坐標對應的y軸值:a, b, c 其中b的梯度是(c-a)/2
而c的梯度是: (c-b)/1。
當為二維數組時,np.gradient(a) 得出兩個數組,第一個數組對應最外層維度的梯度,第二個數組對應第二層維度的梯度。
代碼如下:
2、構造guan光源效果
設計一個位於圖像斜上方的虛擬光源,光源相對於圖像的視角為Elevation,方位角為Azimuth,建立光源對各點梯度值的影響函數,運算出各點的新像素值:
其中:
np.cos(evc.el) : 單位光線在地平面上的投射長度。
dx、dy、dz :光源對xyz三方向的影響程度。
3、梯度歸一化
構造x和y軸梯度的三維歸一化單位坐標系;
梯度與光源相互作用,將梯度轉化為灰度。
4、圖像生成
具體詳情代碼如下:
最終效果圖對比:
最後,你自己動手試試吧?通過此代碼為自己畫一張手繪圖,也可以為自己的家鄉或母校畫。
作者:丁彥軍,一名痴戀於Python的碼農
參考資料:
代碼連結:https://pan.baidu.com/s/1E_aZTRQWOzGV-2GV_iH43w
提取碼:64z9
聲明:本文為作者投稿,版權歸其個人所有。
熱 文推 薦