• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 圖像處理之雙邊濾波效果(Bilateral Filtering for Gray and Color Image)

    圖像處理之雙邊濾波效果(Bilateral Filtering for Gray and Color Image)

    基本介紹:

    普通的時空域的低通濾波器,在像素空間完成濾波以后,導致圖像的邊緣部分也變得不那么明顯,

    整張圖像都變得同樣的模糊,圖像邊緣細節丟失。雙邊濾波器(ABilateral Filter)可以很好的保

    留邊緣的同時消除噪聲。雙邊濾波器能做到這些原因在于它不像普通的高斯/卷積低通濾波,只考

    慮了位置對中心像素的影響,它還考慮了卷積核中像素與中心像素之間相似程度的影響,根據位置

    影響與像素值之間的相似程度生成兩個不同的權重表(WeightTable),在計算中心像素的時候加以

    考慮這兩個權重,從而實現雙邊低通濾波。據說AdobePhotoshop的高斯磨皮功能就是應用了

    雙邊低通濾波算法實現。




    程序效果:


    看我們的美女lena應用雙邊濾鏡之后



    程序關鍵代碼解釋:

    建立距離高斯權重表(Weight Table)如下:

    private void buildDistanceWeightTable() {
    	int size = 2 * radius + 1;
    	cWeightTable = new double[size][size];
    	for(int semirow = -radius; semirow <= radius; semirow++) {
    		for(int semicol = - radius; semicol <= radius; semicol++) {
    			// calculate Euclidean distance between center point and close pixels
    			double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;
    			double deltaDelta = delta * delta;
    			cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);
    		}
    	}
    }
    建立RGB值像素度高斯權重代碼如下:

    private void buildSimilarityWeightTable() {
    	sWeightTable = new double[256]; // since the color scope is 0 ~ 255
    	for(int i=0; i<256; i++) {
    		double delta = Math.sqrt(i * i ) / rs;
    		double deltaDelta = delta * delta;
    		sWeightTable[i] = Math.exp(deltaDelta * factor);
    	}
    }
    完成權重和計算與像素×權重和計算代碼如下:

    for(int semirow = -radius; semirow <= radius; semirow++) {
    	for(int semicol = - radius; semicol <= radius; semicol++) {
    		if((row + semirow) >= 0 && (row + semirow) < height) {
    			rowOffset = row + semirow;
    		} else {
    			rowOffset = 0;
    		}
    		
    		if((semicol + col) >= 0 && (semicol + col) < width) {
    			colOffset = col + semicol;
    		} else {
    			colOffset = 0;
    		}
    		index2 = rowOffset * width + colOffset;
    		ta2 = (inPixels[index2] >> 24) & 0xff;
            tr2 = (inPixels[index2] >> 16) & 0xff;
            tg2 = (inPixels[index2] >> 8) & 0xff;
            tb2 = inPixels[index2] & 0xff;
            
            csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];
            csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];
            csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];
            
            csSumRedWeight += csRedWeight;
            csSumGreenWeight += csGreenWeight;
            csSumBlueWeight += csBlueWeight;
            redSum += (csRedWeight * (double)tr2);
            greenSum += (csGreenWeight * (double)tg2);
            blueSum += (csBlueWeight * (double)tb2);
    	}
    }
    完成歸一化,得到輸出像素點RGB值得代碼如下:

    tr = (int)Math.floor(redSum / csSumRedWeight);
    tg = (int)Math.floor(greenSum / csSumGreenWeight);
    tb = (int)Math.floor(blueSum / csSumBlueWeight);
    outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);
    關于什么卷積濾波,請參考:

    http://blog.csdn.net/jia20003/article/details/7038938

    關于高斯模糊算法,請參考:
    http://blog.csdn.net/jia20003/article/details/7234741
    最后想說,不給出源代碼的博文不是好博文,基于Java完成的雙邊濾波速度有點慢

    可以自己優化,雙邊濾鏡完全源代碼如下:

    package com.gloomyfish.blurring.study;
    /**
     *  A simple and important case of bilateral filtering is shift-invariant Gaussian filtering
     *  refer to - http://graphics.ucsd.edu/~iman/Denoising/
     *  refer to - http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
     *  thanks to cyber
     */
    import java.awt.image.BufferedImage;
    
    public class BilateralFilter extends AbstractBufferedImageOp {
    	private final static double factor = -0.5d;
    	private double ds; // distance sigma
    	private double rs; // range sigma
    	private int radius; // half length of Gaussian kernel Adobe Photoshop 
    	private double[][] cWeightTable;
    	private double[] sWeightTable;
    	private int width;
    	private int height;
    	
    	public BilateralFilter() {
    		this.ds = 1.0f;
    		this.rs = 1.0f;
    	}
    	
    	private void buildDistanceWeightTable() {
    		int size = 2 * radius + 1;
    		cWeightTable = new double[size][size];
    		for(int semirow = -radius; semirow <= radius; semirow++) {
    			for(int semicol = - radius; semicol <= radius; semicol++) {
    				// calculate Euclidean distance between center point and close pixels
    				double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;
    				double deltaDelta = delta * delta;
    				cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);
    			}
    		}
    	}
    	
    	/**
    	 * for gray image
    	 * @param row
    	 * @param col
    	 * @param inPixels
    	 */
    	private void buildSimilarityWeightTable() {
    		sWeightTable = new double[256]; // since the color scope is 0 ~ 255
    		for(int i=0; i<256; i++) {
    			double delta = Math.sqrt(i * i ) / rs;
    			double deltaDelta = delta * delta;
    			sWeightTable[i] = Math.exp(deltaDelta * factor);
    		}
    	}
    	
    	public void setDistanceSigma(double ds) {
    		this.ds = ds;
    	}
    	
    	public void setRangeSigma(double rs) {
    		this.rs = rs;
    	}
    
    	@Override
    	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    		width = src.getWidth();
            height = src.getHeight();
            //int sigmaMax = (int)Math.max(ds, rs);
            //radius = (int)Math.ceil(2 * sigmaMax);
            radius = (int)Math.max(ds, rs);
            buildDistanceWeightTable();
            buildSimilarityWeightTable();
            if ( dest == null )
            	dest = createCompatibleDestImage( src, null );
    
            int[] inPixels = new int[width*height];
            int[] outPixels = new int[width*height];
            getRGB( src, 0, 0, width, height, inPixels );
            int index = 0;
    		double redSum = 0, greenSum = 0, blueSum = 0;
    		double csRedWeight = 0, csGreenWeight = 0, csBlueWeight = 0;
    		double csSumRedWeight = 0, csSumGreenWeight = 0, csSumBlueWeight = 0;
            for(int row=0; row<height; row++) {
            	int ta = 0, tr = 0, tg = 0, tb = 0;
            	for(int col=0; col<width; col++) {
            		index = row * width + col;
            		ta = (inPixels[index] >> 24) & 0xff;
                    tr = (inPixels[index] >> 16) & 0xff;
                    tg = (inPixels[index] >> 8) & 0xff;
                    tb = inPixels[index] & 0xff;
                    int rowOffset = 0, colOffset = 0;
                    int index2 = 0;
                    int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;
            		for(int semirow = -radius; semirow <= radius; semirow++) {
            			for(int semicol = - radius; semicol <= radius; semicol++) {
            				if((row + semirow) >= 0 && (row + semirow) < height) {
            					rowOffset = row + semirow;
            				} else {
            					rowOffset = 0;
            				}
            				
            				if((semicol + col) >= 0 && (semicol + col) < width) {
            					colOffset = col + semicol;
            				} else {
            					colOffset = 0;
            				}
            				index2 = rowOffset * width + colOffset;
            				ta2 = (inPixels[index2] >> 24) & 0xff;
            		        tr2 = (inPixels[index2] >> 16) & 0xff;
            		        tg2 = (inPixels[index2] >> 8) & 0xff;
            		        tb2 = inPixels[index2] & 0xff;
            		        
            		        csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];
            		        csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];
            		        csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];
            		        
            		        csSumRedWeight += csRedWeight;
            		        csSumGreenWeight += csGreenWeight;
            		        csSumBlueWeight += csBlueWeight;
            		        redSum += (csRedWeight * (double)tr2);
            		        greenSum += (csGreenWeight * (double)tg2);
            		        blueSum += (csBlueWeight * (double)tb2);
            			}
            		}
            		
    				tr = (int)Math.floor(redSum / csSumRedWeight);
    				tg = (int)Math.floor(greenSum / csSumGreenWeight);
    				tb = (int)Math.floor(blueSum / csSumBlueWeight);
    				outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);
                    
                    // clean value for next time...
                    redSum = greenSum = blueSum = 0;
                    csRedWeight = csGreenWeight = csBlueWeight = 0;
                    csSumRedWeight = csSumGreenWeight = csSumBlueWeight = 0;
                    
            	}
            }
            setRGB( dest, 0, 0, width, height, outPixels );
            return dest;
    	}
    	
    	public static int clamp(int p) {
    		return p < 0 ? 0 : ((p > 255) ? 255 : p);
    	}
    
    	public static void main(String[] args) {
    		BilateralFilter bf = new BilateralFilter();
    		bf.buildSimilarityWeightTable();
    	}
    }
    

    感覺不錯,請頂一下!

    轉載文章請務必注明出自本博客




    版權聲明:本文為iteye_3606原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/iteye_3606/article/details/82369696

    智能推薦

    圖像質量評價論文閱讀之Deep Neural Networks for NR and FR Image Quality Assessment個人理解

        最近在看關于圖像質量評價的相關論文,理解不當之處還請包涵。廢話不多說直接上內容:     這篇文章使用深度學習的方法來實現全參考的圖像質量評價和無參考的圖像質量評價的方法,這里簡單說一下所謂全參考圖像質量評價是指,在度量圖像的質量過程中需要用到參考圖片和退化圖片進行比較的方法,而無參考的圖像質量評價是指找到退化圖像及其主觀分數之間...

    C++ opencv Image visual enhancement - false color(圖像視覺效果增強-偽彩色)

    今天,抽短暫時間實現了一個新的功能,那就是16位圖像的讀取以及偽彩色視覺效果增強。個人感覺各種語言還是C++好用,PY雖然很火,但是項目中執行效率是真的難受。 --->Today, a new feature has been briefly implemented, which is the ability to read 16-bit images and enhance false-c...

    數字圖像處理實驗(16):PROJECT 06-03,Color Image Enhancement by Histogram Processing ...

    實驗要求: Objective: To know how to implement image enhancement for color images by histogram processing. Note that the definition of histogram for color images differs from that of histogram for gray ima...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    猜你喜歡

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    精品国产乱码久久久久久蜜桃不卡