[Toy]自動生成Low Poly風格圖像 —— 基於Edge Drawing和Delaunay

 

大概是暑假期間,和學弟討論了一下這個問題,當時只草草分析了一下問題的解決思路,但是自己一直沒有功夫動手實現。剛好國慶期間浪完返校,就想寫個程序收收心。於是就把這個Low Poly做了一下。

還是慣例先貼一下實現結果:

一、本文提供的資源

程序的百度網盤鏈接:https://pan.baidu.com/s/1YlTIMPv4VjxOtUmkdRiF5w 密碼:ufwu

bilibili程序演示視頻:https://www.bilibili.com/video/av33758221

二、程序信息

編程語言:C++(Qt)。程序除了自動生成Low Poly圖像外,還允許用戶使用鼠標對Polygon進行編輯調整。具體使用操作見我錄製的的Bilibili視頻

程序的界面如下:

程序界面
圖像的編輯模式

三、參考文獻:
[1] Meng Gai, Guoping Wang. Artistic Low Poly Rendering for Images.

[2] Cihan Topal, Cuneyt Akinlar. Edge Drawing:A Combined Real-time Edge and Segment Detector.

四、程序的算法流程

這裏簡單的介紹了本程序所採用的算法思路,重點說明了採用文獻[2]的Edge Drawing方法的單像素邊緣提取方法。

1. 高斯模糊

     同傳統的圖像處理程序一樣,我們首先對原始圖像進行高斯模糊(Gaussian Blur),以減弱圖像噪聲並平滑圖像。關於這一步的處理,可以參考我的另一篇博客

2. Edge Drawing - 單像素寬度的邊緣檢測

     Edge Drawing是Topal等[2]提出的一種有效的邊緣檢測算法。同Canny、Sobel等傳統邊緣提取算法相比,Edge Drawing的一個優勢是:能夠提出到乾淨的單像素寬的邊緣線條,並且在算法中能夠準確的獲取到這些數據結構。

      圖1是兩種算法的對比圖,能夠發現Edge Drawing算法能夠更加有效的獲取邊緣信息。

圖1   Sobel算法(左)和EdgeDrawing算法(右)的對比

    Edge Drawing算法的詳細流程如下:

   (1)計算Gradient map(map G)。map G用來反映圖像亮度梯度的變化。這裏可以採用任意梯度計算的算子進行計算,如Sobel、Prewitt等。map G中的每個像素的梯度變化可由公式G= \sqrt{Gx^{2}+Gy^{2}}計算得到。

   (2)計算Direction map(map D)。mapD可與Gradient map同時計算得到。如果|Gx|\geqslant |Gy|,則一條豎直方向的邊通過該像素;如果|Gx|< |Gy|,則一條水平方向的邊經過該像素。

   (3)錨點提取(Extraction of Archors)。這裏archors中的頂點,被用於作爲圖像邊緣edges的起始分析點。我們對原始圖像進行二次求導,即對Gradient map進行一次求導。此時計算結果反映的是亮度梯度的變化率。我們採用亮度梯度變化率較大的點作爲圖像的archor點。其算法流程如圖2所示:

圖2 對像素(x,y)判斷是否爲錨點archor

  (4)邊緣路徑追蹤。這裏我們對每個錨點進行邊緣路徑追蹤,以生成圖像的edges。首先Direction map反映了通過某點的edge方向,因此對於水平、豎直兩方向的點有如下幾個探測方向,如圖3所示:

圖3 水平方向的探測方向和豎直方向的探測方向

          之後,我們對每個archor進行相反方向的路徑追蹤,這可以是一個遞歸算法。圖4反映了向左追蹤的算法流程,其餘幾個方向與之類似。圖5反映了以點(4,8)爲起點的路徑追蹤結果。

圖4  向左追蹤的處理
圖5 以點(4,8)爲起點的路徑追蹤結果

3. 三角形頂點提取

    此處的頂點提取,我們採取一種簡單的策略。即在Edge Drawing中獲取到的各個邊緣,限制每條Edge在經過minLen個像素寬度時變發生斷裂(例如minLen = 5),這時所有Edge在斷裂後餘下的點就是我們Delaunay三角剖分的輸入。

4. Delaunay三角剖分

   Delaunay三角剖分是一種很常見的將離散點轉變成三角網格的處理算法,其實現也較爲簡單。不過需要提的一點是,建議參考維基中提及的flipped優化方法來實現,該策略能夠將算法耗時顯著降低。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章