快速双边滤波在High-Dynamic Range(HDR)图像显示中的应用。
快速雙邊濾波在High-Dynamic Range(HDR)圖像顯示中的應用。
2014年10月21日?? 綜合?? 共 4617字 ? 字號?小?中?大???評論關閉 ? ? ?高動態范圍圖像(High-Dynamic Range,簡稱HDR),相比普通的圖像,可以提供更多的動態范圍和圖像細節,根據不同的曝光時間的LDR(Low-Dynamic
Range)圖像,利用每個曝光時間相對應最佳細節的LDR圖像來合成最終HDR圖像,能夠更好的反映人真實環境中的視覺效果。
現實真正存在的亮度差,即最亮的物體亮度,和最小的物體亮度之比為108,
而人類的眼睛所能看到的范圍是105左右,但是一般的顯示器,照相機能表示的只有256種不同的亮度,計算一般的顯示器,照相機能表示的只有256種不同的亮度機在表示圖象的時候是用8bit(256)級或16bit(65536)級來區分圖象的亮度的,但這區區幾百或幾萬無法再現真實自然的光照情況。HDR文件是一種特殊圖形文件格式,它的每一個像素除了普通的RGB信息,還有該點的實際亮度信息。普通的圖形文件每個象素只有0
-255的灰度范圍,這實際上是不夠的。想象一下太陽的發光強度和一個純黑的物體之間的灰度范圍或者說亮度范圍的差別,遠遠超過了256個級別。因此,一張普通的白天風景圖片,看上去白云和太陽可能都呈現是同樣的灰度/亮度,都是純白色,但實際上白云和太陽之間實際的亮度不可能一樣,他們之間的亮度差別是巨大的。因此,普通的圖形文件格式是很不精確的,遠遠沒有紀錄到現實世界的實際狀況。
以上均摘自百度相關網頁,放在這里只是做個簡單的介紹,我們實際關心的是如果已經有了原始的hdr數據,如何利用顯示器完美的把文件中包含的圖像信息表達出來。
簡單的說,就是現在有一堆離散的數據,數據的分布范圍可能很廣,如何把這些離散的數據隱射到0到255之間。
最簡單的當然是線性隱射,先算出離散數據的最大值和最小值,然后將數據線性的拉升至0到255之間,這種直接的操作往往無法得到滿意的效果,會導致大量細節丟失,表現在視覺上就是一大塊黑色或者一大塊白色的,如下圖所示:
???
???、
?????上面兩幅圖要么是暗部太暗,要么是亮部太亮,整體對比度太強,導致細節信息大量丟失。
?????針對這一問題,很多人提出了不少相當不錯的解決方案,比如基于全局操作符的,其中本文作者實現其中的基于快速雙邊濾波技術的HDR顯示過程。
???? 本文對應的參考論文地址:?Fast Bilateral Filtering for the Display of High-Dynamic-Range Images
???? 論文的細路很簡單,首先他將原始的HDR數據分解成兩個層:base layer 和 detail layer,然后降低base layer的對比度,不改變detail layer的數據,在將這兩層合并。
???? 其中:base layer的數據用 HDR原始數據進行雙邊濾波獲取。
?????算法的簡單流程入下所示:
1、input intensity= 1/61*(R*20+G*40+B)
2、r=R/(input intensity), g=G/input intensity, B=B/input intensity
3、log(base)=Bilateral(log(input intensity))
4、log(detail)=log(input intensity)-log(base)
5、log (output intensity)=log(base)*compressionfactor+log(detail) - log_absolute_scale
6、R output = r*10^(log(output intensity)), etc.
???? 上述過程中的變量compressionfactor,log_absolute_scale原文作者的建議取值為:
?? compressionfactor = targetContrast/(max(log(base)) - min(log(base))) 對于很多圖像,targetContrast使用log(5)能獲得較為理想的值。
?? 而log_absolute_scale= max(log(base))*compressionfactor;
??? 在進行雙邊的時候,SigmaS一般取值為0.02*Max(Width,Height)比較合適,而SigmaR取值0.4較為理想。
所以都取優化的參數,則上述過程可以自動進行。
??? 作者提到上述log操作都是以10為底進行的,我覺得以e為底實際效果也沒啥區別的。
????按照這個思路編制程序后,確實能取得很不錯的效果,比如上述兩幅圖像,按照前面講的參數取值,解碼后得到的圖像如下:
?????
??? 可見,圖像的細節較為完美的體現出來了。
????當然,自動的參數不一定能調處最好的效果,比如還是這兩幅圖,手工選擇一些參數,可以調出如下效果:
?????
特別是第一幅圖,很有種蒙太奇的感覺。
??? 在看看幾張長出現在論文中的圖像的結果:
? ???
???????
? ???
????
? ??
??? 線性解碼圖 ??????????????? 雙邊濾波解碼圖
有些圖線性解碼啥都看不到,雙邊濾波解碼后細節表現的就很清晰了。
??? HDR格式的原始數據的解碼可以借助FreeImage來實現,一段簡單的實現代碼如下:
public Bitmap LoadHdrFormFreeImage(string FileName) {Bitmap Bmp = null;FREE_IMAGE_FORMAT fif = FREE_IMAGE_FORMAT.FIF_UNKNOWN; ;if (FreeImage.IsAvailable() == true){fif = FreeImage.GetFileType(FileName, 0);if (fif != FREE_IMAGE_FORMAT.FIF_HDR){MessageBox.Show("不是Hdr格式的圖像.");return null;}fif = FreeImage.GetFIFFromFilename(FileName);FIBITMAP Dib = FreeImage.Load(fif, FileName, FREE_IMAGE_LOAD_FLAGS.DEFAULT);uint Bpp = FreeImage.GetBPP(Dib);if (Bpp != 96){MessageBox.Show("無法支持的Hdr格式.");FreeImage.Unload(Dib);return null;}uint Width = FreeImage.GetWidth(Dib); // 圖像寬度uint Height = FreeImage.GetHeight(Dib); // 圖像高度uint Stride = FreeImage.GetPitch(Dib); // 圖像掃描行的大小,必然是4的整數倍IntPtr Bits = FreeImage.GetBits(Dib);float* Data = (float*)Bits;int Speed, Index;byte* Pixel;float Value;if (RawData != null) Marshal.FreeHGlobal((IntPtr)RawData);RawData = (float*)Marshal.AllocHGlobal((int)Width * (int)Height * 3 * sizeof(float));CopyMemory(RawData, Data, (int)Width * (int)Height * 3 * sizeof(float));Bmp = new Bitmap((int)Width, (int)Height, PixelFormat.Format24bppRgb);BitmapData BmpData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);Pixel = (byte*)BmpData.Scan0;for (int Y = 0; Y < Height; Y++){Speed = Y * BmpData.Stride;Index = Y * (int)Width * 3;for (int X = 0; X < Width; X++){Value = (Data[Index + 2] * 255);if (Value > 255)Value = 255;else if (Value < 0)Value = 0;Pixel[Speed] = (byte)Value;Value = (Data[Index + 1] * 255);if (Value > 255)Value = 255;else if (Value < 0)Value = 0;Pixel[Speed + 1] = (byte)Value;Value = (Data[Index + 0] * 255);if (Value > 255)Value = 255;else if (Value < 0)Value = 0;Pixel[Speed + 2] = (byte)Value;Index += 3;Speed += 3;}}FreeImage.Unload(Dib);Bmp.UnlockBits(BmpData);Bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);return Bmp;}elsereturn null; }以上采用的是線性解碼。
附一個解碼的調用程序:http://files.cnblogs.com/Imageshop/ReadHdrTest.rar?
?????更多的源碼可參考:http://people.csail.mit.edu/sparis/code/src/tone_mapping
????????????????????????????http://people.csail.mit.edu/fredo/PUBLI/Siggraph2002/
???? 一些常見的用于測試的HDR圖像可以從這里下載:http://www.pauldebevec.com/Research/HDR/
???? 同樣,這種 tone mapping算法也可以用在普通的RGB圖像上,效果如下所示:
? ???
原圖 增加base layer的對比度
????
? 原圖 降低base layer的對比度
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的快速双边滤波在High-Dynamic Range(HDR)图像显示中的应用。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV2:图像滤波基础
- 下一篇: 基于deep learning的快速图像