1. 程式人生 > >影象去模糊演算法 循序漸進 附完整程式碼

影象去模糊演算法 循序漸進 附完整程式碼

關於影象模糊演算法的實現,

我相信大多數學習影象演算法的朋友都很熟悉。

例如常見的毛玻璃效果,高斯模糊等等。

而影象模糊最簡單的實現就是 在一定區域 對畫素做平均值計算。

術語描述,卷積。

1.認識卷積

而平均值計算可以,是一種常見的卷積計算,卷積核權重都為1。

OpenCV中與之對應的演算法是BoxBlur。

影象方面深度學習中最重要的兩個層,一個池化層,一個卷積層,

其中池化層可以認為是一種特例的卷積層,與求平均值類似。

從網上找了一張卷積操作的示例圖片。

這樣看,雖然知道是在做一個點面計算的操作,但是要具體描述卷積的用途或者原理,是有點困難的。

在兩年前一次公司的內部技術分享會上,我是這麼定義卷積的。

卷積計算從形象上來描述,在影象領域,一般是2維,

所以可以這麼說 “計算兩個物體在n維空間的相似度(疊加度)的操作,就稱之為(n維)卷積。”

所以影象是計算兩個物體在2維空間的相似度(疊加度)的操作,就稱之為卷積。

如果兩個物體完全一致,卷積完全重合,重合度為1,這時可以認為它就是同一個物體。

以上描述的兩個物體,在演算法中一般 指的是 卷積核 和被卷積圖片,卷積結果就是其兩者的重合度。

看下深度學習中的池化層和均值層。

根據上面的描述,重新理解一下,這兩個層的作用。

這裡就不展開細講了,大概大家能理解一下卷積這個操作即可。

而一般情況下,卷積操作,是一種資訊外散或內聚的計算,

當然也有卷積,反捲積,轉置卷積的說法。

舉個例子,例如均值池化或者說均值卷積,均值模糊。

從計算來看,是取目標畫素臨近區域畫素的平均值,而所有臨近畫素的權重都為1.

最終目標畫素的值為n分之1. 

那麼這個計算就好像是把一個物品在2維空間直接攤平,還不能理解的再看下上面對卷積的描述。

就像你有9只螞蟻,你希望他們長得一樣大,你一巴掌下去,身體全部壓平。

而在影象領域,絕大多數的模糊,就是受到一個“物體”或者說“卷積核”的干擾,

致使採集到的資訊丟失,或者說不準確。

例如在按下快門的一瞬間,你手抖了,或者說失去焦點,

就會很容易造成呈像模糊。

2.影象修復

假設我們能找到導致成像模糊的原因,是不是就能實現修復模糊影象呢?

答案是肯定的。

不過取決於最終採集到的資訊的完整度。

如果最後成像一片漆黑,那這個時候是無能為力的。

因為已經沒有足夠的資訊了。

而一般影象是由色光三原色組成,紅綠藍。

理論上只要其中一種顏色資訊完整,就可以用於輔助修復其他色光。

只要能計算到當時的色光分佈情況即可實現。

這裡我們就需要稍微提及一下攝像領域3大演算法,自動白平衡,自動對焦,自動曝光。

簡單講下 這三個演算法的區別。

白平衡是為了解決色光分佈不均,資訊缺失或失真問題的。

自動對焦是為了成像清晰,人為干擾輔助最終成像。

自動曝光當然是為了解決採光問題,彌補感光元件的不足。

大概的先後順序,理論上應該是 對焦->曝光->白平衡

一般而言,從這邏輯來看,白平衡是最難解決的,因為它受到前面兩個因素的干擾。

但是實際上,白平衡和曝光目前都解決得很好。

HDR嚴格意義上來說,能兼顧白平衡和曝光。

但是對焦或者說失焦,抖動的問題,一直以來都是老大難。

原因也很簡單,導致成像模糊的因素有很多,通過什麼樣的方法來有效評估修復,就顯得比較困難。

 假設能知道計算到當時受到什麼“物體”的干擾,通過卷積的方式,移除這干擾,是不是就能修復模糊,恢復圖片呈像。

假設造成模糊的因素為:   清晰的圖片 + 干擾因素 = 最終成像

那麼反之恢復影象即為:   最終成像 - 干擾因素 = 清晰圖片

而這裡把干擾因素和清晰的圖片都認為是一種卷積“物體”。

3.去模糊

有了前面的基礎知識,我們可以做一個假設,進行驗證。

例如,我先對一張圖片做卷積操作,模擬模糊成像。

這個時候: 你同時有了  清晰的圖片 + 干擾因素 = 最終成像

驗證一下:  最終成像 - 干擾因素 = 清晰圖片

這裡不展開演算法實現,

但是結果我可以告訴大家,這思路沒錯,但是有一個干擾因素錯了。

它就是卷積核的大小。

卷積核大小直接決定它的作用範圍。

而我們第一步拿到的 清晰的圖片 + 干擾因素 = 最終成像

這裡 最終成像-干擾因素 卻絕對不等於清晰的圖片。

因為 這裡的干擾因素和最終成像 兩者之間並不是簡單的線性關係,相加或者相減,

他們的關係是卷積關係,也就是說他們都受到卷積核的影響。

如果想要達到 最終成像 - 干擾因素 = 清晰圖片

必須 在最終成像的時候用類似卷積的方式,消除卷積核的內容以及範圍的影響。

換句話說,這個操作必須控制好變數。

這個問題說真的,我思考了很久很久。

最後終於知道問題在哪裡,就是影象的明度,也就是最終成像。

也就是最終成像中是含有卷積核權重資訊的,如果要消除這個資訊,

必須將成像也作為權重參與計算。

 也就是說,造成模糊的情況應該是:

    if( sqrt(nx-x) + sqrt(ny-y) <  sqrt(radius) )
    {
        w = luminance(rgb)
        sum += w*s;
        wsum += w;
    }
     sum /= wsum; 

 虛擬碼,簡潔形象地表達這個現象。

知道這個前因後果,現在恢復模糊,該如何計算。

這個留個作業給大家。

上面虛擬碼我稱之為  散焦 演算法,反之為 聚焦 也就是去模糊 。

聚焦演算法最終可以實現耗時模糊半徑無關,它是去模糊的一種特例。

目前,此演算法暫無開源計劃。

好幾年前就有去模糊的商業軟體,當然早期版本作者也開源了。

但是這個專案並沒有很好準確計算到去模糊卷積核。

前幾天ipol.im公佈了一個比較優秀的評估去模糊卷積核的演算法。

從官網demo演示來看,效果特別不錯。

但是,它和SmartDeblur 都有著一樣的問題,就是用到傅立葉變換去做卷積操作,

十分耗時。

都採用了fftw,計算量還是居高不下。

我對它提供的程式碼,做了一些簡單的裁剪,cmake編譯通過,僅依賴fftw。

而程式碼的演算法調優等等,還沒做,演算法優化空間比較大,最近精力有限,

在音訊演算法上花的時間比較多,影象暫時沒有精力做起來。

感興趣的朋友,可以移步專案:

而近些年,深度學習大興,各種各樣的模型以及訓練集,五花八門。

當然也有去模糊的實現。

效果非常驚豔!

網路結構如下:

對於採用深度學習的方法進行去模糊實現,可以參閱文章:

專案地址:

相關論文:

DeblurGAN: Blind Motion Deblurring Using Conditional Adversarial Networks

最後做一個簡單的總結,在影象領域,使用卷積就能非常好解決 影象的空間問題,

而深度學習訓練得到的權重,可以簡單的類比上面提到的干擾因素。

通過大量的資料,訓練提取 可能性的干擾因素(物體),若是當前影象也有符合這個特徵的因素(物體),

則進行相應的操作計算。

定位特徵,確認特徵,發現並處理特徵。

分別 對應物體檢測,物體識別,風格化或其他增強修復處理。

採用深度學習最大的好處就是能預先訓練得到已知的資訊,然後進行對應的處理。

而傳統演算法,則需要採用先驗條件,

然後在一張圖片中去發現可能性因素,由於引數較少,魯棒性一般不佳。

相比而言,傳統演算法困難重重,因為你要通過科學方式找到一種適配資料自然規律的先驗,真的太不容易。

而深度學習是另一個問題,資料依賴,資料干擾,資料處理,這些預處理也著實夠人頭大的了,

然後還要設計一個比較有效且優良的神經網路。

就目前來看,經典傳統演算法穩定性比較高,但是泛化能力一般較差。

深度學習目前還需要不少傳統演算法配合進行訓練處理,以求達到更好的效果。

就目前來看,工業化落地也有不少問題,不過相信很快就能做得很好了。

因為有大公司和大量資金資本的助推,應該不是難事。

國慶前辭去了工作,現裸辭回廣東,下一站工作方向暫未知,

不過可以肯定的是,紮在演算法裡醉生夢死,

當然也希望能結交演算法方面的有志之士,一起愉快地玩耍。

若有其他相關問題或者需求也可以郵件聯絡俺探討。

郵箱地址是: [email protected]