影象去霧之何凱明暗通道先驗去霧演算法原理及c++程式碼實現
http://blog.csdn.net/s12244315/article/details/50292049
何凱明博士,2007年清華大學畢業,2011年香港中文大學博士畢業,可謂是功力深厚,感嘆於國內一些所謂博士的水平,何這樣的博士才可以真正叫做
Doctor。
本文主要上是對《Single Image Haze Removal Using Dark Channel Prior》的翻譯、整理、及部分解釋、程式碼實現。如果您的英文水平好,建議看原
文可能來的更爽些。
一、論文思想的簡單描述
首先看看暗通道先驗是什麼:
在絕大多數非天空的區域性區域裡,某一些畫素總會有至少一個顏色通道具有很低的值。換言之,該區域光強度的最小值是個很小的數。
我們給暗通道一個數學定義,對於任意的輸入影象J,其暗通道可以用下式表達:
式中Jc表示彩色影象的每個通道 ,Ω(x)表示以畫素X為中心的一個視窗。
式(5)的意義用程式碼表達也很簡單,首先求出每個畫素RGB分量中的最小值,存入一副和原始影象大小相同的灰度圖中,然後再對這幅灰度圖進行最小值
濾波,濾波的半徑由視窗大小決定,一般有WindowSize = 2 * Radius + 1;
暗通道先驗的理論指出:
實際生活中造成暗原色中低通道值主要有三個因素:a)汽車、建築物和城市中玻璃窗戶的陰影,或者是樹葉、樹與岩石等自然景觀的投影;b)色彩鮮豔的物
體或表面,在RGB的三個通道中有些通道的值很低(比如綠色的草地/樹/植物,紅色或黃色的花朵/葉子,或者藍色的水面);c)顏色較暗的物體或者表面,
例如灰暗色的樹幹和石頭。總之,自然景物中到處都是陰影或者彩色,這些景物的影象的暗原色總是很灰暗的。
在作者的論文中,統計了5000多副影象的特徵,也都基本符合這個先驗,因此,我們可以認為其實一條定理。
有了這個先驗,接著就需要進行一些數學方面的推導來最終解決問題。
首先,在計算機視覺和計算機圖形中,下述方程所描述的霧圖形成模型被廣泛使用:
其中,I(X)就是我們現在已經有的影象(待去霧的影象),J(x)是我們要恢復的無霧的影象,A是全球大氣光成分, t(x)為透射率。現在的已知條件就是
I(X),要求目標值J(x),顯然,這是個有無數解的方程,因此,就需要一些先驗了。
將式(1)稍作處理,變形為下式:
如上所述,上標C表示R/G/B三個通道的意思。
首先假設在每一個視窗內透射率t(x)為常數,定義他為,並且A值已經給定,然後對式(7)兩邊求兩次最小值運算,得到下式:
上式中,J是待求的無霧的影象,根據前述的暗原色先驗理論有:
因此,可推匯出:
把式(10)帶入式(8)中,得到:
這就是透射率的預估值。
在現實生活中,即使是晴天白雲,空氣中也存在著一些顆粒,因此,看遠處的物體還是能感覺到霧的影響,另外,霧的存在讓人類感到景深的存在,因此,有
必要在去霧的時候保留一定程度的霧,這可以通過在式(11)中引入一個在[0,1] 之間的因子,則式(11)修正為:
本文中所有的測試結果依賴於: ω=0.95。
上述推論中都是假設全球達氣光A值時已知的,在實際中,我們可以藉助於暗通道圖來從有霧影象中獲取該值。具體步驟如下:
1) 從暗通道圖中按照亮度的大小取前0.1%的畫素。
2) 在這些位置中,在原始有霧影象I中尋找對應的具有最高亮度的點的值,作為A值。
到這一步,我們就可以進行無霧影象的恢復了。由式(1)可知: J = ( I - A)/t + A
現在I,A,t都已經求得了,因此,完全可以進行J的計算。
當投射圖t 的值很小時,會導致J的值偏大,從而使淂影象整體向白場過度,因此一般可設定一閾值T0,當t值小於T0時,令t=T0,本文中所有效果圖均以
T0=0.1為標準計算。
因此,最終的恢復公式如下:
當直接用上述理論進行恢復時,去霧的效果其實也是很明顯的,比如下面一些例子:
有霧圖 去霧圖
注意到第一幅圖的原圖兩個字的周圍明顯有一塊不協調的地方,而第二圖頂部水平方向似乎有一塊沒有進行去霧處理,這些都是由於我們的透射率圖過於粗
糙了。
要獲得更為精細的透射率圖,何博士在文章中提出了了soft matting方法,能得到非常細膩的結果。但是他的一個致命的弱點就是速度特慢,不使用於實際
使用。在2011年,何博士又除了一片論文,其中提到了導向濾波的方式來獲得較好的透射率圖。該方法的主要過程集中於簡單的方框模糊,而方框模糊有多重和
半徑無關的快速演算法。因此,演算法的實用性特強,關於這個導向濾波演算法大家在何博士的網站可以自己去研習下,除了在去霧方面外,還有著其他多方面的應
用,這部分本文不多述。
使用了導向濾波後的去霧效果:
二、各引數對去霧結果的影響
第一:視窗的大小。這個對結果來說是個關鍵的引數,視窗越大,其包含暗通道的概率越大,暗通道也就越黑。我們不去從理論角度分析,從實踐的效果來
看,似乎視窗越大,去霧的效果越不明顯,如下圖所示:
(a) 原始影象 (b) 視窗大小=11
(c) 視窗大小=21 (d) 視窗大小=101
我的建議是視窗大小在11-51之間,即半徑在5-25之間。
式(12)中的ω具有著明顯的意義,其值越小,去霧效果越不明顯,舉例如下:
(a) 原始影象 (b) ω=0.5
(c) ω=0.8 (d) ω=1
三:編碼的步驟
如果你仔細的分析了原文的細路,加上適當的參考,編碼其實並不是很困難。
1)根據原始影象求暗通道。。
2)按文中所描述的演算法自動獲得全球大氣光的值。
這裡說明一點,原始論文中的A最終是取原始畫素中的某一個點的畫素,我實際上是取的符合條件的所有點的平均值作為A的值,我這樣做是因為,如果是取
一個點,則各通道的A值很有可能全部很接近255,這樣的話會造成處理後的影象偏色和出現大量色斑。原文作者說這個演算法對天空部分不需特備處理,我實際發
現該演算法對有天空的影象的效果一般都不好。天空會出現明顯的過渡區域。作為解決方案,我增加了一個引數,最大全球大氣光值,當計算的值大於該值時,則
就取該值。
原圖 未對A值做限定 最大A值限定為220
3) 按式(12)計算預估的透射率圖。
在式(12)中,每個通道的資料都需要除以對應的A值,即歸一化,這樣做,還存在一個問題,由於A的選取過程,並不能保證每個畫素分量值除以A值後都
小於1,從而導致t的值可能小於0,而這是不容許的,原文作者並沒有交代這一點是如何處理的。我在實際的編碼中發現,如果真的這樣做了,其效果也並不是很
理想 ,因此,我最後的辦法是在式(12)中,不考慮A的計算。
4)計算導向濾波圖。
這裡可以直接用原始的影象做導向圖,當然也可以用其灰度圖,但是用RGB導向圖在下一步的計算中會佔用比較大的時間。
5)按照《Guided Image Filtering》論文中的公式(5)、(6)、(8)編碼計算獲得精細的透射率圖。c++程式碼見上一篇文章。
還有一點就是,上述計算需要在[0,1]範圍內進行,也就是說導向圖和預估的透射率圖都必須從[0,255]先對映到[0,1]在進行計算。
關於guidedfilter中的半徑r值,因為在前面進行最小值後暗通道的影象成一塊一塊的,為了使透射率圖更加精細,建議這個r的取值不小於進行最小值濾波的
半徑的4倍,如下圖所示:
(a) r=最小值濾波半徑的2倍 (b) r=最小值濾波半徑的8倍
可以看到,當r比較小的時候,在透射率圖中基本看不到什麼細節資訊,因此恢復處的影象邊緣處不明顯。
引數eps的取值也有所講究,他主要是為了防止計算中除以0的錯誤以及為了使得某些計算結果不至於過大,一般建議取值0.001或者更小。
如果使用的彩色RGB圖做導向圖,計算時間上會增加不少,所的到的透射率圖的邊緣會比灰度圖所處理的保留了更多的細節,效果上略微比灰度圖好。
以RGB圖為導向圖的計算中,涉及到3*3部分矩陣求逆的過程,如果用非matlab語言寫,可以先借助於matlab的符號計算功能,以及其中的符號計算命令
simple,把計算結果算出來,然後再再其他高階語言中實現。
(6) 按式(22)進行無霧影象的恢復。
mfc標頭檔案:
- #pragma once
- #include "afxwin.h"
- #include <cv.h>
- #include "cxcore.h"
- #include "math.h"
- #include <highgui.h>
- #include<vector>
- #include <iostream>
- #include "opencv2/core/core.hpp"
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- usingnamespace std;
- usingnamespace cv;
- class Ctry :
- public CCmdTarget
- {
- public:
- Ctry();
- virtual ~Ctry();
- DECLARE_MESSAGE_MAP()
- afx_msg void OnTryTyr1();
- afx_msg void OnTryPath();
- public:
- Mat getimage(Mat &a);
- Mat guidedFilter2(cv::Mat I, cv::Mat p, int r, double eps);
- IplImage* getDarkChannel(IplImage* &src);
- IplImage* getMinIcy(IplImage* dark,int w);
- double getA(IplImage* dark, IplImage*hazeImage);
-
IplImage* getTransmission(IplImage* Icy, double
相關推薦
影象去霧之何凱明暗通道先驗去霧演算法原理及c++程式碼實現
http://blog.csdn.net/s12244315/article/details/50292049 何凱明博士,2007年清華大學畢業,2011年香港中文大學博士畢業,可謂是功力深厚,感嘆於國內一些所謂博士的水平,何這樣的博士才可以真正叫做
增強影象對比度演算法原理及matlab程式碼實現
clc; close all; clear all; % -------------Gamma Transformations----------------- %f = imread('Fig0316(4)(bottom_left).tif');
關於暗通道先驗去霧問題的小結
前段日子導師甩給我一篇何博士的論文,叫做《Single Image Haze Removal Using Dark Channel Prior》,利用統計得來的暗通道先驗實現對有霧影象的去霧問題,現大概說說對論文中的幾個點。 1.去霧問題的數學模型: 其中,I為haze image
資料結構圖文解析之:陣列、單鏈表、雙鏈表介紹及C++模板實現
0. 資料結構圖文解析系列 1. 線性表簡介 線性表是一種線性結構,它是由零個或多個數據元素構成的有限序列。線性表的特徵是在一個序列中,除了頭尾元素,每個元素都有且只有一個直接前驅,有且只有一個直接後繼,而序列頭元素沒有直接前驅,序列尾元素沒有直接後繼。 資料結構中常見的線性結構有陣列、單鏈表、雙鏈表、迴圈
資料探勘之clara演算法原理及例項(程式碼中有bug)
繼上兩篇文章介紹聚類中基於劃分思想的k-means演算法和k-mediod演算法 本文將繼續介紹另外一種基於劃分思想的k-mediod演算法-----clara演算法 clara演算法可以說是對k-mediod演算法的一種改進,就如同k-mediod演算法對 k-m
全面解讀Group Normbalization-(吳育昕-何凱明 重磅之作)
作者:劉威威 編輯:李雪冬 前 言Face bo
【何凱明】非區域性連線網路 Non-local Neural Network
《Non-local Neural Network》 一、 主要貢獻 1.提出了一種非區域性連線(Non-local operations)的計算塊 (building block),用於處理視訊和影象的長程依賴關係(long-range dependency); 2.在視訊資料集Kinetics
暗通道先驗+加權最小二乘 去霧 原理
本文主要講解,何愷明暗通道先驗去霧以及加權最小二乘演算法的原理部分,對應程式碼可在資源處下載。1暗通道先驗去霧模型 公式(1)是常用的霧靄形成模型: (1)其中,I(x)為實際拍攝到的有霧視訊幀,J(x)為去霧後的原視訊
c#程式碼實現排序演算法之歸併排序
歸併排序的平均時間複雜度為O(nlogn),最好時間複雜度為O(nlogn),最壞時間複雜度為O(nlogn),空間複雜度為O(n),是一種穩定的演算法。 1.將待排序序列r(1),r(2),…,r(n)劃分為兩個長度相等的子序列r(1),…r(n/2)和r(n/2+1),…,r
c#程式碼實現排序演算法之快速排序
快速排序的平均時間複雜度為O(nlog2n),最好時間複雜度為O(nlog2n),最壞時間複雜度為O(n²),空間複雜度為O(log2n),是一種不穩定的演算法。 1.劃分:選定一個記錄作為軸值,以軸值為基準將整個序列劃分為兩個子序列r(1)…r(i-1)和r(i+1)…r(n)
c#程式碼實現排序演算法之氣泡排序
氣泡排序的平均時間複雜度為O(n²),最好時間複雜度為O(n),最壞時間複雜度為O(n²),空間複雜度為O(1),是一種穩定的演算法。 1.將整個待排序的記錄序列劃分成有序區和無序區,初始時有序區為空,無序區包括所有待排序的記錄。 2.對無序區從前向後依次比較相鄰記錄,若反序則交
c#程式碼實現排序演算法之選擇排序
選擇排序的平均時間複雜度為O(n²),最好時間複雜度為O(n²),最壞時間複雜度為O(n²),空間複雜度為O(1),是一種不穩定的演算法。 1.將整個記錄序列劃分為有序區和無序區,初始時有序區為空,無序區含有待排序的所有記錄。 2.在無序區查詢值最小的記錄,將它與無序區的第一個記
c#程式碼實現排序演算法之插入排序
插入排序的平均時間複雜度為O(n²),最好時間複雜度為O(n),最壞時間複雜度為O(n²),空間複雜度為O(1),是一種穩定的演算法。 1.將整個待排序的記錄序列劃分成有序區和無序區,初始時有序區為待排序記錄序列的第一個記錄,無序區包括所有剩餘待排序的記錄。 2.將無序區的第一個
影象插值演算法的原理及C++實現
簡介: 在影象的處理過程中,經常需要對影象進行尺寸變換、旋轉或者扭曲等操作,在進行這些操作之後,原影象的尺寸往往就發生了改變,為了保持變換後的影象不失真,就需要對影象進行插值。 常見的插值方法有最近鄰插值和雙線性插值。 最近鄰插值: 最近鄰插值是最簡單的一種插值方式,
深度學習(七)U-Net原理以及keras程式碼實現醫學影象眼球血管分割
原文作者:aircraft 原文連結:https://www.cnblogs.com/DOMLX/p/9780786.html 全卷積神經網路 醫學影象分割框架 醫學影象分割主要有兩種框架,一個是基於CNN的,另一個就是基於FCN的。這裡都是通過網路來進行語義分割。 那麼什麼是語義分割?可
.NET Core實戰專案之CMS 第十二章 開發篇-Dapper封裝GURD及倉儲程式碼生成器實現
本篇我將帶著大家一起來對Dapper進行下封裝並實現基本的增刪改查、分頁操作的同步非同步方法的實現(已實現MSSQL,MySql,PgSQL)。同時我們再實現一下倉儲層的程式碼生成器,這樣的話,我們只需要結合業務來實現具體的業務部分的程式碼就可以了,可以大大減少我們重複而又繁瑣的增刪改查操作,多留點時間給生活
排序系列之(4)希爾排序及C語言實現
希爾排序(Shell Sort)也稱為遞減增量排序演算法,是插入排序的一種高速而安定的改良版。因希爾(Donald L. Shell)於1959年提出而得名。各種實現在如何進行遞減上有所不同。 希爾排序是基於插入排序的以下兩點性質而提出改進方法的: 插入排序在對幾乎已經排好序的資料操作時, 效率高, 即可以達
.NET Core實戰專案之CMS 第十二章 開發篇-Dapper封裝CURD及倉儲程式碼生成器實現
本篇我將帶著大家一起來對Dapper進行下封裝並實現基本的增刪改查、分頁操作的同步非同步方法的實現(已實現MSSQL,MySql,PgSQL)。同時我們再實現一下倉儲層的程式碼生成器,這樣的話,我們只需要結合業務來實現具體的業務部分的程式碼就可以了,可以大大減少我們重複而又繁瑣的增刪改查操作,多留點時間給生活
資料結構之:AVL樹詳解及C++模板實現
AVL樹簡介AVL樹的名字來源於它的發明作者G.M. Adelson-Velsky 和 E.M. Landis。AVL樹是最先發明的自平衡二叉查詢樹(Self-Balancing Binary Search Tree,簡稱平衡二叉樹)。一棵AVL樹有如下必要條件:條件一:它必
資料結構(C語言)讀書筆記6:棧的應用之括號匹配的C程式碼實現
括號匹配的演算法思想: 初始化一個空棧,掃描表示式,依次讀入字元,知道掃描完或者出現錯誤匹配。對於讀入的每個字元,分以下情況處理: (1)、如果是‘’(“”或“【”,將其壓入棧。 (2)、如果是“)”,則根據當前棧頂元素的值分情況考慮。若棧頂元素是“(”,則匹配成功,否則為