圖像濾波是一種十分常見的圖像處理手段。通常,你可以認(rèn)為相鄰位置像素是緊密聯(lián)系的,它們共同來顯示對某個物體,圖像濾波則通過運(yùn)算來排除圖像中和周圍相差大的像素。當(dāng)然,這并不是絕對的, 有時候你為了評估圖像的質(zhì)量,也會將這些“特立獨(dú)行”的像素作為選取的目標(biāo) 。無論你采用什么方法,記住你要的目標(biāo)就行,有時候你的目標(biāo)可能是別人的背景。
創(chuàng)新互聯(lián)建站專注于洛南企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。洛南網(wǎng)站建設(shè)公司,為洛南等地區(qū)提供建站服務(wù)。全流程按需開發(fā)網(wǎng)站,專業(yè)設(shè)計,全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務(wù)
濾波常常會使得圖像變得模糊(非絕對),那么,為什么你需要將一幅清晰的圖像變得模糊呢?下面的例子應(yīng)該可以解釋。
高斯濾波采用滿足正態(tài)分布的核模板,其參數(shù)的主要參數(shù)是標(biāo)準(zhǔn)差σ,代表核的離散程度,σ值越小,模板中心系數(shù)與邊緣系數(shù)差越大,平滑的程度越小。
高斯濾波對圖像采集過程中由于不良照明/高溫引起的傳感器噪聲信號有較好的效果,消除了圖像中的高頻信號。
由于得到的是一維的Gaussian Kernel,你可以采用下面的方式轉(zhuǎn)為二維的
為了便于直觀感受高斯濾波的效果,使用Canny算子來提取輪廓對比,你可以試試在特征提取前加高斯濾波對比。
補(bǔ)充說明:對于均值濾波,你也可以使用cv2.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]])來實(shí)現(xiàn),需要將normalize設(shè)置為True,當(dāng)設(shè)置normalize為False時,實(shí)現(xiàn)的是將kernel內(nèi)像素相加,官方文檔做出的描述為:
中值濾波對圖像中的脈沖型(椒鹽等)噪聲信號處理效果好,當(dāng) 你的應(yīng)用場景存在這種顆粒感的噪聲信號時,中值濾波會是一種很好的選擇 。它,選取kernel區(qū)域內(nèi)像素點(diǎn)集的中值最為錨點(diǎn)的像素值,對類似投票機(jī)制中的最高分(高灰階點(diǎn))和最低分(過低灰階點(diǎn))影響有很好的抑制作用。
如果你的應(yīng)用涉及到圖像美化,雙邊濾波可以初步達(dá)到你的期望,關(guān)于雙邊濾波,這里不做展開,由你來探索,其函數(shù)參數(shù)信息如下。
對于opencv-python的圖像濾波部分有問題歡迎留言, Have Fun With OpenCV-Python, 下期見。
Pillow是Python里的圖像處理庫(PIL:Python Image Library),提供了了廣泛的文件格式支持,強(qiáng)大的圖像處理能力,主要包括圖像儲存、圖像顯示、格式轉(zhuǎn)換以及基本的圖像處理操作等。
1)使用 Image 類
PIL最重要的類是 Image class, 你可以通過多種方法創(chuàng)建這個類的實(shí)例;你可以從文件加載圖像,或者處理其他圖像, 或者從 scratch 創(chuàng)建。
要從文件加載圖像,可以使用open( )函數(shù),在Image模塊中:
[python]?view plain?copy
from?PIL?import?Image
im?=?Image.open("E:/photoshop/1.jpg")
加載成功后,將返回一個Image對象,可以通過使用示例屬性查看文件內(nèi)容:
[python]?view plain?copy
print(im.format,?im.size,?im.mode)
('JPEG',?(600,?351),?'RGB')
format?這個屬性標(biāo)識了圖像來源。如果圖像不是從文件讀取它的值就是None。size屬性是一個二元tuple,包含width和height(寬度和高度,單位都是px)。?mode?屬性定義了圖像bands的數(shù)量和名稱,以及像素類型和深度。常見的modes 有 “L” (luminance) 表示灰度圖像, “RGB” 表示真彩色圖像, and “CMYK” 表示出版圖像。
如果文件打開錯誤,返回?IOError?錯誤。
只要你有了 Image 類的實(shí)例,你就可以通過類的方法處理圖像。比如,下列方法可以顯示圖像:
[python]?view plain?copy
im.show()
2)讀寫圖像
PIL 模塊支持大量圖片格式。使用在 Image 模塊的 open() 函數(shù)從磁盤讀取文件。你不需要知道文件格式就能打開它,這個庫能夠根據(jù)文件內(nèi)容自動確定文件格式。要保存文件,使用 Image 類的 save() 方法。保存文件的時候文件名變得重要了。除非你指定格式,否則這個庫將會以文件名的擴(kuò)展名作為格式保存。
加載文件,并轉(zhuǎn)化為png格式:
[python]?view plain?copy
"Python?Image?Library?Test"
from?PIL?import?Image
import?os
import?sys
for?infile?in?sys.argv[1:]:
f,e?=?os.path.splitext(infile)
outfile?=?f?+".png"
if?infile?!=?outfile:
try:
Image.open(infile).save(outfile)
except?IOError:
print("Cannot?convert",?infile)
save() 方法的第二個參數(shù)可以指定文件格式。
3)創(chuàng)建縮略圖
縮略圖是網(wǎng)絡(luò)開發(fā)或圖像軟件預(yù)覽常用的一種基本技術(shù),使用Python的Pillow圖像庫可以很方便的建立縮略圖,如下:
[python]?view plain?copy
#?create?thumbnail
size?=?(128,128)
for?infile?in?glob.glob("E:/photoshop/*.jpg"):
f,?ext?=?os.path.splitext(infile)
img?=?Image.open(infile)
img.thumbnail(size,Image.ANTIALIAS)
img.save(f+".thumbnail","JPEG")
上段代碼對photoshop下的jpg圖像文件全部創(chuàng)建縮略圖,并保存,glob模塊是一種智能化的文件名匹配技術(shù),在批圖像處理中經(jīng)常會用到。
注意:Pillow庫不會直接解碼或者加載圖像柵格數(shù)據(jù)。當(dāng)你打開一個文件,只會讀取文件頭信息用來確定格式,顏色模式,大小等等,文件的剩余部分不會主動處理。這意味著打開一個圖像文件的操作十分快速,跟圖片大小和壓縮方式無關(guān)。
4)圖像的剪切、粘貼與合并操作
Image 類包含的方法允許你操作圖像部分選區(qū),PIL.Image.Image.crop 方法獲取圖像的一個子矩形選區(qū),如:
[python]?view plain?copy
#?crop,?paste?and?merge
im?=?Image.open("E:/photoshop/lena.jpg")
box?=?(100,100,300,300)
region?=?im.crop(box)
矩形選區(qū)有一個4元元組定義,分別表示左、上、右、下的坐標(biāo)。這個庫以左上角為坐標(biāo)原點(diǎn),單位是px,所以上訴代碼復(fù)制了一個 200x200 pixels 的矩形選區(qū)。這個選區(qū)現(xiàn)在可以被處理并且粘貼到原圖。
[python]?view plain?copy
region?=?region.transpose(Image.ROTATE_180)
im.paste(region,?box)
當(dāng)你粘貼矩形選區(qū)的時候必須保證尺寸一致。此外,矩形選區(qū)不能在圖像外。然而你不必保證矩形選區(qū)和原圖的顏色模式一致,因?yàn)榫匦芜x區(qū)會被自動轉(zhuǎn)換顏色。
5)分離和合并顏色通道
對于多通道圖像,有時候在處理時希望能夠分別對每個通道處理,處理完成后重新合成多通道,在Pillow中,很簡單,如下:
[python]?view plain?copy
r,g,b?=?im.split()
im?=?Image.merge("RGB",?(r,g,b))
對于split( )函數(shù),如果是單通道的,則返回其本身,否則,返回各個通道。
6)幾何變換
對圖像進(jìn)行幾何變換是一種基本處理,在Pillow中包括resize( )和rotate( ),如用法如下:
[python]?view plain?copy
out?=?im.resize((128,128))
out?=?im.rotate(45)??#?degree?conter-clockwise
其中,resize( )函數(shù)的參數(shù)是一個新圖像大小的元祖,而rotate( )則需要輸入順時針的旋轉(zhuǎn)角度。在Pillow中,對于一些常見的旋轉(zhuǎn)作了專門的定義:
[python]?view plain?copy
out?=?im.transpose(Image.FLIP_LEFT_RIGHT)
out?=?im.transpose(Image.FLIP_TOP_BOTTOM)
out?=?im.transpose(Image.ROTATE_90)
out?=?im.transpose(Image.ROTATE_180)
out?=?im.transpose(Image.ROTATE_270)
7)顏色空間變換
在處理圖像時,根據(jù)需要進(jìn)行顏色空間的轉(zhuǎn)換,如將彩色轉(zhuǎn)換為灰度:
[python]?view plain?copy
cmyk?=?im.convert("CMYK")
gray?=?im.convert("L")
8)圖像濾波
圖像濾波在ImageFilter 模塊中,在該模塊中,預(yù)先定義了很多增強(qiáng)濾波器,可以通過filter( )函數(shù)使用,預(yù)定義濾波器包括:
BLUR、CONTOUR、DETAIL、EDGE_ENHANCE、EDGE_ENHANCE_MORE、EMBOSS、FIND_EDGES、SMOOTH、SMOOTH_MORE、SHARPEN。其中BLUR就是均值濾波,CONTOUR找輪廓,F(xiàn)IND_EDGES邊緣檢測,使用該模塊時,需先導(dǎo)入,使用方法如下:
[python]?view plain?copy
from?PIL?import?ImageFilter
imgF?=?Image.open("E:/photoshop/lena.jpg")
outF?=?imgF.filter(ImageFilter.DETAIL)
conF?=?imgF.filter(ImageFilter.CONTOUR)
edgeF?=?imgF.filter(ImageFilter.FIND_EDGES)
imgF.show()
outF.show()
conF.show()
edgeF.show()
除此以外,ImageFilter模塊還包括一些擴(kuò)展性強(qiáng)的濾波器:
class?PIL.ImageFilter.GaussianBlur(radius=2)
Gaussian blur filter.
參數(shù):
radius?– Blur radius. ? ?
class?PIL.ImageFilter.UnsharpMask(radius=2,?percent=150,?threshold=3)
Unsharp mask filter.
See Wikipedia’s entry on?digital unsharp masking?for an explanation of the parameters.
class?PIL.ImageFilter.Kernel(size,?kernel,?scale=None,?offset=0)
Create a convolution kernel. The current version only supports 3x3 and 5x5 integer and floating point kernels.
In the current version, kernels can only be applied to “L” and “RGB” images.
參數(shù):
size?– Kernel size, given as (width, height). In the current version, this must be (3,3) or (5,5).
kernel?– A sequence containing kernel weights.
scale?– Scale factor. If given, the result for each pixel is divided by this value. the default is the sum of the kernel weights.
offset?– Offset. If given, this value is added to the result, after it has been divided by the scale factor.
class?PIL.ImageFilter.RankFilter(size,?rank)
Create a rank filter. The rank filter sorts all pixels in a window of the given size, and returns therank‘th value.
參數(shù):
size?– The kernel size, in pixels.
rank?– What pixel value to pick. Use 0 for a min filter,?size?*?size?/?2?for a median filter,?size?*?size?-?1?for a max filter, etc.
class?PIL.ImageFilter.MedianFilter(size=3)
Create a median filter. Picks the median pixel value in a window with the given size.
參數(shù):
size?– The kernel size, in pixels. ? ?
class?PIL.ImageFilter.MinFilter(size=3)
Create a min filter. Picks the lowest pixel value in a window with the given size.
參數(shù):
size?– The kernel size, in pixels. ? ?
class?PIL.ImageFilter.MaxFilter(size=3)
Create a max filter. Picks the largest pixel value in a window with the given size.
參數(shù):
size?– The kernel size, in pixels. ? ?
class?PIL.ImageFilter.ModeFilter(size=3)
Create a mode filter. Picks the most frequent pixel value in a box with the given size. Pixel values that occur only once or twice are ignored; if no pixel value occurs more than twice, the original pixel value is preserved.
參數(shù):
size?– The kernel size, in pixels. ? ?
更多詳細(xì)內(nèi)容可以參考:PIL/ImageFilter
9)圖像增強(qiáng)
圖像增強(qiáng)也是圖像預(yù)處理中的一個基本技術(shù),Pillow中的圖像增強(qiáng)函數(shù)主要在ImageEnhance模塊下,通過該模塊可以調(diào)節(jié)圖像的顏色、對比度和飽和度和銳化等:
[python]?view plain?copy
from?PIL?import?ImageEnhance
imgE?=?Image.open("E:/photoshop/lena.jpg")
imgEH?=?ImageEnhance.Contrast(imgE)
imgEH.enhance(1.3).show("30%?more?contrast")
圖像增強(qiáng):
class?PIL.ImageEnhance.Color(image)
Adjust image color balance.
This class can be used to adjust the colour balance of an image, in a manner similar to the controls on a colour TV set. An enhancement factor of 0.0 gives a black and white image. A factor of 1.0 gives the original image.
class?PIL.ImageEnhance.Contrast(image)
Adjust image contrast.
This class can be used to control the contrast of an image, similar to the contrast control on a TV set. An enhancement factor of 0.0 gives a solid grey image. A factor of 1.0 gives the original image.
class?PIL.ImageEnhance.Brightness(image)
Adjust image brightness.
This class can be used to control the brighntess of an image. An enhancement factor of 0.0 gives a black image. A factor of 1.0 gives the original image.
class?PIL.ImageEnhance.Sharpness(image)
Adjust image sharpness.
This class can be used to adjust the sharpness of an image. An enhancement factor of 0.0 gives a blurred image, a factor of 1.0 gives the original image, and a factor of 2.0 gives a sharpened image.
圖像增強(qiáng)的詳細(xì)內(nèi)容可以參考:PIL/ImageEnhance
除了以上介紹的內(nèi)容外,Pillow還有很多強(qiáng)大的功能:
PIL.Image.alpha_composite(im1,?im2)
PIL.Image.blend(im1,?im2,?alpha)
PIL.Image.composite(image1,?image2,?mask)
PIL.Image.eval(image,?*args)
PIL.Image.fromarray(obj,?mode=None)
PIL.Image.frombuffer(mode,?size,?data,?decoder_name='raw',?*args)
import CV2
import copy
import numpy as np
import random
使用的是pycharm
因?yàn)樽罱戳恕躲y翼殺手2049》,里面Joi實(shí)在是太好看了所以原圖像就用Joi了
要求是灰度圖像,所以第一步先把圖像轉(zhuǎn)化成灰度圖像
# 讀入原始圖像
img = CV2.imread('joi.jpg')
# 灰度化處理
gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)
CV2.imwrite('img.png', gray)
第一個任務(wù)是利用分段函數(shù)增強(qiáng)灰度對比,我自己隨便寫了個函數(shù)大致是這樣的
def chng(a):
if a 255/3:
b = a/2
elif a 255/3*2:
b = (a-255/3)*2 + 255/6
else:
b = (a-255/3*2)/2 + 255/6 +255/3*2
return b
rows = img.shape[0]
cols = img.shape[1]
cover = copy.deepcopy(gray)
for i in range(rows):
for j in range(cols):
cover[i][j] = chng(cover[i][j])
CV2.imwrite('cover.png', cover)
下一步是直方圖均衡化
# histogram equalization
def hist_equal(img, z_max=255):
H, W = img.shape
# S is the total of pixels
S = H * W * 1.
out = img.copy()
sum_h = 0.
for i in range(1, 255):
ind = np.where(img == i)
sum_h += len(img[ind])
z_prime = z_max / S * sum_h
out[ind] = z_prime
out = out.astype(np.uint8)
return out
covereq = hist_equal(cover)
CV2.imwrite('covereq.png', covereq)
在實(shí)現(xiàn)濾波之前先添加高斯噪聲和椒鹽噪聲(代碼來源于網(wǎng)絡(luò))
不知道這個椒鹽噪聲的名字是誰起的感覺隔壁小孩都饞哭了
用到了random.gauss()
percentage是噪聲占比
def GaussianNoise(src,means,sigma,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum):
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
NoiseImg[randX, randY]=NoiseImg[randX,randY]+random.gauss(means,sigma)
if NoiseImg[randX, randY] 0:
NoiseImg[randX, randY]=0
elif NoiseImg[randX, randY]255:
NoiseImg[randX, randY]=255
return NoiseImg
def PepperandSalt(src,percetage):
NoiseImg=src
NoiseNum=int(percetage*src.shape[0]*src.shape[1])
for i in range(NoiseNum):
randX=random.randint(0,src.shape[0]-1)
randY=random.randint(0,src.shape[1]-1)
if random.randint(0,1)=0.5:
NoiseImg[randX,randY]=0
else:
NoiseImg[randX,randY]=255
return NoiseImg
covereqg = GaussianNoise(covereq, 2, 4, 0.8)
CV2.imwrite('covereqg.png', covereqg)
covereqps = PepperandSalt(covereq, 0.05)
CV2.imwrite('covereqps.png', covereqps)
下面開始均值濾波和中值濾波了
就以n x n為例,均值濾波就是用這n x n個像素點(diǎn)灰度值的平均值代替中心點(diǎn),而中值就是中位數(shù)代替中心點(diǎn),邊界點(diǎn)周圍補(bǔ)0;前兩個函數(shù)的作用是算出這個點(diǎn)的灰度值,后兩個是對整張圖片進(jìn)行
#均值濾波模板
def mean_filter(x, y, step, img):
sum_s = 0
for k in range(x-int(step/2), x+int(step/2)+1):
for m in range(y-int(step/2), y+int(step/2)+1):
if k-int(step/2) 0 or k+int(step/2)+1 img.shape[0]
or m-int(step/2) 0 or m+int(step/2)+1 img.shape[1]:
sum_s += 0
else:
sum_s += img[k][m] / (step*step)
return sum_s
#中值濾波模板
def median_filter(x, y, step, img):
sum_s=[]
for k in range(x-int(step/2), x+int(step/2)+1):
for m in range(y-int(step/2), y+int(step/2)+1):
if k-int(step/2) 0 or k+int(step/2)+1 img.shape[0]
or m-int(step/2) 0 or m+int(step/2)+1 img.shape[1]:
sum_s.append(0)
else:
sum_s.append(img[k][m])
sum_s.sort()
return sum_s[(int(step*step/2)+1)]
def median_filter_go(img, n):
img1 = copy.deepcopy(img)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img1[i][j] = median_filter(i, j, n, img)
return img1
def mean_filter_go(img, n):
img1 = copy.deepcopy(img)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img1[i][j] = mean_filter(i, j, n, img)
return img1
完整main代碼如下:
if __name__ == "__main__":
# 讀入原始圖像
img = CV2.imread('joi.jpg')
# 灰度化處理
gray = CV2.cvtColor(img, CV2.COLOR_BGR2GRAY)
CV2.imwrite('img.png', gray)
rows = img.shape[0]
cols = img.shape[1]
cover = copy.deepcopy(gray)
for i in range(rows):
for j in range(cols):
cover[i][j] = chng(cover[i][j])
CV2.imwrite('cover.png', cover)
covereq = hist_equal(cover)
CV2.imwrite('covereq.png', covereq)
covereqg = GaussianNoise(covereq, 2, 4, 0.8)
CV2.imwrite('covereqg.png', covereqg)
covereqps = PepperandSalt(covereq, 0.05)
CV2.imwrite('covereqps.png', covereqps)
meanimg3 = mean_filter_go(covereqps, 3)
CV2.imwrite('medimg3.png', meanimg3)
meanimg5 = mean_filter_go(covereqps, 5)
CV2.imwrite('meanimg5.png', meanimg5)
meanimg7 = mean_filter_go(covereqps, 7)
CV2.imwrite('meanimg7.png', meanimg7)
medimg3 = median_filter_go(covereqg, 3)
CV2.imwrite('medimg3.png', medimg3)
medimg5 = median_filter_go(covereqg, 5)
CV2.imwrite('medimg5.png', medimg5)
medimg7 = median_filter_go(covereqg, 7)
CV2.imwrite('medimg7.png', medimg7)
medimg4 = median_filter_go(covereqps, 7)
CV2.imwrite('medimg4.png', medimg4)