1. 程式人生 > >關於高斯模糊的詳細介紹及python程式碼實現

關於高斯模糊的詳細介紹及python程式碼實現

講的是Gaussian Blur,講的很詳細,值得仔細閱讀!

python最常用的影象處理庫是PIL(PythonImaging Library),它內建了高斯模糊方法,簡單程式碼如下:

import Image 
import ImageFilter

im=Image.open('im.jpg')
im=im.filter(ImageFilter.GaussianBlur(radius=2))

im.show()

其中這個GaussianBlur()函式原始碼有錯誤:設定radius無效,也就是說radius不管設定成多大,都是按2來計算的。錯誤太明顯了!我們都知道radius越大影象越模糊。這個錯誤在PIL原始檔的ImageFilter.py中,第156行。擷取部分原始碼可知:

# Gaussian blur filter.

class GaussianBlur(Filter):
    name = "GaussianBlur"

    def __init__(self, radius=2):
        self.radius = 2#這個地方明顯不對
    def filter(self, image):
        return image.gaussian_blur(self.radius)
自己改正過來:
class MyGaussianBlur(ImageFilter.Filter):
    name="GaussianBlur"
    
    def __init__(self, radius=2):
        self.radius=radius
    def filter(self, image):
        return image.gaussian_blur(self.radius)

其實,上面的例子關於高斯模糊是不完整的。它沒有提供設定sigema值的方法,只提供了設定radius的方法。在pyOpenCV中應該有完整的高斯模糊函式,可以直接呼叫。我決定簡單地自己實現一下:

下面是具體程式碼,只用了PIL庫和numpy,PIL僅用於讀寫影象, numpy用於矩陣計算。全過程完全符合

# -*- coding: utf-8 -*-

import math
import numpy as np
import Image

class MyGaussianBlur():
    #初始化
    def __init__(self, radius=1, sigema=1.5):
        self.radius=radius
        self.sigema=sigema    
    #高斯的計算公式
    def calc(self,x,y):
        res1=1/(2*math.pi*self.sigema*self.sigema)
        res2=math.exp(-(x*x+y*y)/(2*self.sigema*self.sigema))
        return res1*res2
    #得到濾波模版
    def template(self):
        sideLength=self.radius*2+1
        result = np.zeros((sideLength, sideLength))
        for i in range(sideLength):
            for j in range(sideLength):
                result[i,j]=self.calc(i-self.radius, j-self.radius)
        all=result.sum()
        return result/all    
    #濾波函式
    def filter(self, image, template): 
        arr=np.array(image)
        height=arr.shape[0]
        width=arr.shape[1]
        newData=np.zeros((height, width))
        for i in range(self.radius, height-self.radius):
            for j in range(self.radius, width-self.radius):
                t=arr[i-self.radius:i+self.radius+1, j-self.radius:j+self.radius+1]
                a= np.multiply(t, template)
                newData[i, j] = a.sum()
        newImage = Image.fromarray(newData)          
        return newImage

r=1 #模版半徑,自己自由調整
s=2 #sigema數值,自己自由調整
GBlur=MyGaussianBlur(radius=r, sigema=s)#宣告高斯模糊類
temp=GBlur.template()#得到濾波模版
im=Image.open('lena1.bmp')#開啟圖片
image=GBlur.filter(im, temp)#高斯模糊濾波,得到新的圖片
image.show()#圖片顯示

原影象:


高斯模糊後的影象:


我這個例子同時提供了設定radius和sigema的方法。歡迎大家批評指正。

缺點:

運算時間太長了,跟要處理影象的大小成正比。為了測試能快一點,我只能把lena只取一張臉來測試了!另外,沒有考慮邊緣畫素!