高斯濾波和雙向濾波的區別與聯系

1. 簡介

????????? 圖像平滑是一個重要的操作,而且有多種成熟的算法。這里主要簡單介紹一下Bilateral方法(雙邊濾波),這主要是由于前段時間做了SSAO,需要用bilateral blur 算法進行降噪。Bilateral blur相對于傳統的高斯blur來說很重要的一個特性即可可以保持邊緣(Edge Perseving),這個特點對于一些圖像模糊來說很有用。一般的高斯模糊在進行采樣時主要考慮了像素間的空間距離關系,但是卻并沒有考慮像素值之間的相似程度,因此這樣我們得到的模糊結果通常是整張圖片一團模糊。Bilateral blur的改進就在于在采樣時不僅考慮像素在空間距離上的關系,同時加入了像素間的相似程度考慮,因而可以保持原始圖像的大體分塊進而保持邊緣。在于游戲引擎的post blur算法中,bilateral blur常常被用到,比如對SSAO的降噪。

2. 原理

????????? 濾波算法中,目標點上的像素值通常是由其所在位置上的周圍的一個小局部鄰居像素的值所決定。在2D高斯濾波中的具體實現就是對周圍的一定范圍內的像素值分別賦以不同的高斯權重值,并在加權平均后得到當前點的最終結果。而這里的高斯權重因子是利用兩個像素之間的空間距離(在圖像中為2D)關系來生成。通過高斯分布的曲線可以發現,離目標像素越近的點對最終結果的貢獻越大,反之則越小。其公式化的描述一般如下所述:

其中的c即為基于空間距離的高斯權重,而用來對結果進行單位化。

???????? 高斯濾波在低通濾波算法中有不錯的表現,但是其卻有另外一個問題,那就是只考慮了像素間的空間位置上的關系,因此濾波的結果會丟失邊緣的信息。這里的邊緣主要是指圖像中主要的不同顏色區域(比如藍色的天空,黑色的頭發等),而Bilateral就是在Gaussian blur中加入了另外的一個權重分部來解決這一問題。Bilateral濾波中對于邊緣的保持通過下述表達式來實現:

??????? 其中的s為基于像素間相似程度的高斯權重,同樣用來對結果進行單位化。對兩者進行結合即可以得到基于空間距離、相似程度綜合考量的Bilateral濾波:

??????? 上式中的單位化分部綜合了兩種高斯權重于一起而得到,其中的cs計算可以詳細描述如下:

且有

且有

??????? 上述給出的表達式均是在空間上的無限積分,而在像素化的圖像中當然無法這么做,而且也沒必要如此做,因而在使用前需要對其進行離散化。而且也不需要對于每個局部像素從整張圖像上進行加權操作,距離超過一定程度的像素實際上對當前的目標像素影響很小,可以忽略的。限定局部子區域后的離散化公就可以簡化為如下形式:

??????? 上述理論公式就構成了Bilateral濾波實現的基礎。為了直觀地了解高斯濾波與雙邊濾波的區別,我們可以從下列圖示中看出依據。假設目標源圖像為下述左右區域分明的帶有噪聲的圖像(由程序自動生成),藍色框的中心即為目標像素所在的位置,那么當前像素處所對應的高斯權重與雙邊權重因子3D可視化后的形狀如后邊兩圖所示:????????????

左圖為原始的噪聲圖像;中間為高斯采樣的權重;右圖為Bilateral采樣的權重。從圖中可以看出Bilateral加入了相似程度分部以后可以將源圖像左側那些跟當前像素差值過大的點給濾去,這樣就很好地保持了邊緣。為了更加形象地觀察兩者間的區別,使用Matlab將該圖在兩種不同方式下的高度圖3D繪制出來,如下:

??

上述三圖從左到右依次為:雙邊濾波,原始圖像,高斯濾波。從高度圖中可以明顯看出Bilateral和Gaussian兩種方法的區別,前者較好地保持了邊緣處的梯度,而在高斯濾波中,由于其在邊緣處的變化是線性的,因而就使用連累的梯度呈現出漸變的狀態,而這表現在圖像中的話就是邊界的丟失(圖像的示例可見于后述)。??????????????????????????????????????????????

3. 代碼實現

有了上述理論以后實現Bilateral Filter就比較簡單了,其實它也與普通的Gaussian Blur沒有太大的區別。這里主要包括3部分的操作: 基于空間距離的權重因子生成;基于相似度的權重因子的生成;最終filter顏色的計算。

3.1 Spatial Weight

這就是通常的Gaussian Blur中使用的計算高斯權重的方法,其主要通過兩個pixel之間的距離并使用如下公式計算而來:

其中的就表示兩個像素間的距離,比如當前像素與其右邊緊鄰的一個像素之間的距離我們就可以用來計算,也即兩個二維向量{0 , 0}以及{0 , 1}之間的歐氏距離。直接計算一個區域上的高斯權重并單位化后就可以進行高斯模糊了。

3.2 Similarity Weight

與基于距離的高斯權重計算類似,只不過此處不再根據兩個pixel之間的空間距離,而是根據其相似程度(或者兩個pixel的值之間的距離)。

其中的表示兩個像素值之間的距離,可以直接使用其灰度值之間的差值或者RGB向量之間的歐氏距離。

3.3 Color Filtering

有了上述兩部分所必需的權重因子之后,那么具體的雙邊濾波的實現即與普通的高斯濾波無異。主要部分代碼如下述:

[cpp]?view plaincopy
  1. UCHAR3?BBColor(int?posX?,?int?posY)??
  2. {??
  3. ????int?centerItemIndex?=?posY?*?picWidth4?+?posX?*?3?,?neighbourItemIndex;??
  4. ????int?weightIndex;??
  5. ????double?gsAccumWeight?=?0;??
  6. ????double?accumColor?=?0;??
  7. ??
  8. ????//?計算各個采樣點處的Gaussian權重,包括closeness,similarity??
  9. ????for(int?i?=?-number?;?i?<=?number?;?++i)??
  10. ????{??
  11. ????????for(int?j?=?-number?;?j?<=?number?;?++j)??
  12. ????????{??
  13. ????????????weightIndex?=?(i?+?number)?*?(number?*?2?+?1)?+?(j?+?number);??
  14. ????????????neighbourItemIndex?=?min(noiseImageHeight?-?1?,?max(0?,?posY?+?j?*?radius))?*?picWidth4?+??
  15. ?????????????????????????????min(noiseImageWidth?-?1??,?max(0?,?posX?+?i?*?radius))?*?3;??
  16. ??????????????
  17. ????????????pCSWeight[weightIndex]?=?LookupGSWeightTable(pSrcDataBuffer[neighbourItemIndex]?,?pSrcDataBuffer[centerItemIndex]);??
  18. ????????????pCSWeight[weightIndex]?=?pGSWeight[weightIndex]?*?pGCWeight[weightIndex];??
  19. ????????????gsAccumWeight?+=?pCSWeight[weightIndex];??
  20. ????????}??
  21. ????}??
  22. ??????
  23. ????//?單位化權重因子??
  24. ????gsAccumWeight?=?1?/?gsAccumWeight;??
  25. ????for(int?i?=?-number?;?i?<=?number?;?++i)??
  26. ????{??
  27. ????????for(int?j?=?-number?;?j?<=?number?;?++j)??
  28. ????????{??
  29. ????????????weightIndex?=?(i?+?number)?*?(number?*?2?+?1)?+?(j?+?number);??
  30. ????????????pCSWeight[weightIndex]?*=?gsAccumWeight;??
  31. ????????}??
  32. ????}??
  33. ??????
  34. ????//?計算最終的顏色并返回??
  35. ????for(int?i?=?-number?;?i?<=?number?;?++i)??
  36. ????{??
  37. ????????for(int?j?=?-number?;?j?<=?number?;?++j)??
  38. ????????{??
  39. ????????????weightIndex?=?(i?+?number)?*?(number?*?2?+?1)?+?(j?+?number);??
  40. ????????????neighbourItemIndex?=?min(noiseImageHeight?-?1?,?max(0?,?posY?+?j?*?radius))?*?picWidth4?+??
  41. ?????????????????????????????????min(noiseImageWidth?-?1??,?max(0?,?posX?+?i?*?radius))?*?3;??
  42. ????????????accumColor?+=?pSrcDataBuffer[neighbourItemIndex?+?0]?*?pCSWeight[weightIndex];??
  43. ????????}??
  44. ????}??
  45. ??
  46. ????return?UCHAR3(accumColor?,?accumColor?,?accumColor);??
  47. }??

?其中的相似度分部的權重s主要根據兩個Pixel之間的顏色差值計算面來。對于灰度圖而言,這個差值的范圍是可以預知的,即[-255, 255],因而為了提高計算的效率我們可以將該部分權重因子預計算生成并存表,在使用時快速查詢即可。使用上述實現的算法對幾張帶有噪聲的圖像進行濾波后的結果如下所示:

???

????

上圖從左到右分別為:雙邊濾波;原始圖像;高斯濾波。從圖片中可以較為明顯地看出兩種算法的區別,最直觀的感受差別就是使用高斯算法后整張圖片都是一團模糊的狀態;而雙邊濾波則可以較好地保持原始圖像中的區域信息,看起來仍然嘴是嘴、眼是眼(特別是在第一張美女圖像上的效果!看來PS是灰常重要啊~~^o^)。

4. 在SSAO中的使用

在上述實現中的邊緣判定函數主要是通過兩個像素值之間的差異來決定,這也是我們觀察普通圖片的一種普遍感知方式。當然,也可以根據使用的需求情況來使用其它的方式判斷其它定義下的邊緣,比如使用場景的depth或是normal。比如在對SSAO進行濾波時可以直接使用Depth值來行邊緣判斷。首先,設置一個深度的閾值,在作邊緣檢測時比較兩點間的depth差值,如果差值大于閾值,則認為其屬于不同的區域,則此處就應為邊界。使用此方法得到的效果可見于下圖所示:

高斯濾波

雙邊濾波

在得到濾波之后的SSAO圖像之后,與原始圖像進行直接的整合就可以得到最終的渲染效果,如下圖所示:

SSAO關閉

SSAO開啟

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/255537.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255537.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255537.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Eclipse變量名自動補全問題 自定義上屏按鍵為TAB

Eclipse空格等號等都可以上屏&#xff0c;這樣有時候輸入變量名再按空格就會自動補全&#xff0c;非常討厭。那么怎么辦呢&#xff1f; 1.首先你的Eclipse需要裝有 Eclipse plug-in development environment 和 Eclipse JDT Plug-in Developer Resources 或者直接去下載一個和…

Dreamweaver CS6 Mac破解版

介于之前小子分享的Mac版的Adobe的PS CS6和Illustrator CS6&#xff0c;有用戶要求小子分享下Dreamweaver&#xff0c;小子當然樂意效勞。 Dreamweaver CS6 是世界頂級軟件廠商Adobe推出的一套擁有可視化編輯界面&#xff0c;用于制作并編輯網站和移動應用程序的網頁設計軟件。…

【pyqt5學習】——graphicView顯示matplotlib圖像

目錄 一、導入模塊 二、自定義一個matplotlib窗口類Figure 三、利用QT_designer繪制窗口 四、寫邏輯代碼 五、結果展示 一、導入模塊 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplo…

happens-before規則

1&#xff09;程序順序規則&#xff1a;一個線程中的每個操作&#xff0c;happens-before于該線程中的任意后續操作。2&#xff09;監視器鎖規則&#xff1a;對一個鎖的解鎖&#xff0c;happens-before于隨后對這個鎖的加鎖。3&#xff09;volatile變量規則&#xff1a;對一個v…

what is ssao

說到ssao 就要從ao說起&#xff0c;ao&#xff0c;即間接環境光遮蔽技術。我們知道現實中的光線&#xff0c;除了來自太陽和電燈的直射光線以外&#xff0c;光線碰到物體以后&#xff0c;還會再次反射&#xff0c;折射&#xff0c;而再次反射折射的過程中&#xff0c;又會被其他…

【pyqt5學習】——groupBox顯示matplotlib圖像

目錄 一、導入模塊 二、創建matplotlib窗口類 三、qt_designer設計窗口 四、邏輯代碼 五、結果展示 一、導入模塊 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure impor…

[BZOJ3545][ONTAK2010]Peaks

[BZOJ3545][ONTAK2010]Peaks 試題描述 在Bytemountains有N座山峰&#xff0c;每座山峰有他的高度h_i。有些山峰之間有雙向道路相連&#xff0c;共M條路徑&#xff0c;每條路徑有一個困難值&#xff0c;這個值越大表示越難走&#xff0c;現在有Q組詢問&#xff0c;每組詢問詢問從…

杭電1027Ignatius and the Princess II模擬

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1027 題目&#xff1a; Problem DescriptionNow our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about to kill our pretty Princess. But now the BEelzebub has t…

angular 使用rxjs 監聽同級兄弟組件數據變化

angular 的官網給出了父子組件之間數據交互的方法&#xff0c;如ViewChild、EventEmitter 但是如果要在同級組件之間進行數據同步&#xff0c;似乎并沒有給出太多的信息。 有時候我們想&#xff0c;在一個組件中修改數據之后&#xff0c;馬上反映到另外一個組件中&#xff0c; …

OpenCV里IplImage的widthStep參數 和width參數

一直以為IplImage結構體中的widthStep元素大小等于width*nChannels&#xff0c;大錯特錯&#xff01;&#xff08;為了快速訪問&#xff0c;要內存對齊啊&#xff09;查看OpenCV2.1的源碼&#xff0c;在src/cxcore/cxarray.cpp文件中&#xff0c;找到cvInitImageHeader函數&…

【數字信號處理】——Python頻譜繪制

# -*- coding: utf-8 -*- from matplotlib import pyplotpyplot.rcParams[font.sans-serif] [SimHei] pyplot.rcParams[axes.unicode_minus] Falseimport numpy as np import matplotlib.pyplot as pl import matplotlib import math import randomN 500 # 繪制點總數 fs 5…

Android開發:《Gradle Recipes for Android》閱讀筆記1.3

想命令行執行gradle的構建&#xff0c;可以通過提供的gradle wrapper或者安裝gradle。 構建android項目不需要安裝gradle&#xff0c;因為android studio已經包含gradle。"gradle wrapper"指的是根目錄下的gradlew和gradlew.bat腳本&#xff08;結尾的w是wrapper的意…

pic

轉載于:https://www.cnblogs.com/edisonxiang/p/5392651.html

leetcode 643 Maximum Average Subarray I

題目詳情 Given an array consisting of n integers, find the contiguous subarray of given length k that has the maximum average value. And you need to output the maximum average value. 輸入一個數組nums和一個整數k。要求找出輸入數組中長度為k的子數組&#xff0c…

OpenCV之cvSmooth函數平滑濾波

1、cvSmooth函數用法 定義原型 <span style"font-size:12px;"> void cvSmooth( const CvArr* src, CvArr* dst,int smoothtypeCV_GAUSSIAN,int param1, int param2, double param3, double param4 );</span>src:輸入圖像. dst:輸出圖像. smoot…

【python數字信號處理】——DFT、DTFT(頻譜圖、幅度圖、相位圖)

目錄 一、離散時間傅里葉變換DTFT 二、離散傅里葉變換DFT 三、DFT與DTFT的關系 ? 參考&#xff1a; 《數字信號處理》——&#xff08;一&#xff09;.DTFT、DFT(python實現)_遠行者223的博客-CSDN博客python繪制頻譜圖DTFT&#xff0c;DFTpython繪制頻譜圖&#xff1a;…

ERROR:Tried to register widget id ==basemapGalleryDiv but that id is already registered解決辦法

在ArcGIS Server開發中&#xff0c;遇到DIV已經被注冊的情況&#xff0c;不能對原DIV內容進行更新。這里需要調用Dojo的destroyRecursive&#xff08;&#xff09;方法&#xff0c;逐個銷毀該Widget下的子元素及其后代元素。然后就可以在原DIV上注冊新的小部件。 示例代碼&…

通過Spring Data Neo4J操作您的圖形數據庫

在前面的一篇文章《圖形數據庫Neo4J簡介》中&#xff0c;我們已經對其內部所使用的各種機制進行了簡單地介紹。而在我們嘗試對Neo4J進行大版本升級時&#xff0c;我發現網絡上并沒有任何成型的樣例代碼以及簡介&#xff0c;而其自身的文檔也對如何使用Spring Data Neo4J介紹得語…

圖像金字塔

圖像金字塔被廣泛用于各種視覺應用中。圖像金字塔是一個圖像集合&#xff0c;集合中所有的圖像都源于同一個原始圖像&#xff0c;而且是通過對原始圖像連續降采樣活得&#xff0c;直到達到某個中止條件才停止降采樣。&#xff08;當然&#xff0c;降為一個像素肯定是中止條件。…

python使用git進行版本控制-分支管理

1、遠程克隆 最好的方式是先創建遠程庫&#xff0c;然后&#xff0c;從遠程庫克隆&#xff1a; 首先在github上創建一個新的倉庫&#xff0c;名字叫gitskills 我們勾選Initialize this repository with a README&#xff0c;這樣GitHub會自動為我們創建一個README.md文件。 下一…