目錄
簡介
一、邊界填充
1.函數說明
2.案例分析
二、圖像運算
1.+號運算
2.cv2.add()函數
3.圖像加權運算
三、閾值處理
四、圖像平滑處理
1.椒鹽噪聲
2.均值濾波(Mean Filtering)
3.方框濾波
4. 高斯濾波(Gaussian Filtering)
5.中值濾波(Median Filtering)
總結:
簡介
繼上一篇博客:
計算機視覺第一課opencv(一)保姆級教
我們了解了關于opencv的一些基本用途,今天我們繼續來探究opencv的其他功能
一、邊界填充
1.函數說明
cv2.copyMakeBorder()是OpenCV庫中的一個函數,用于給圖像添加額外的邊界(padding)。
cv2.copyMakeBorder(src: UMat, top: int, bottom: int, left: int, right: int, borderType: int, dst: UMat | None = ..., value: cv2.typing.Scalar = ...)
它有以下幾個參數:
- # src: 要擴充邊界的原始圖像。
- # top, bottom, left, right: 相應方向上的邊框寬度。
- # borderType: 定義要添加邊框的類型,它可以是以下的一種:
- # cv2.BORDER_CONSTANT: 添加的邊框像素值為常數(需要額外再給定一個參數)。
- # cv2.BORDER_REFLECT: 添加的邊框像素將是邊界元素的鏡面反射,類似于 gfedcba|abcdefgh|hgfedcba。(交界處也復制了)
- # cv2.BORDER_REFLECT_101 或 cv2.BORDER_DEFAULT: 和上面類似,但是有一些細微的不同,類似于 gfedcb|abcdefgh|gfedcba。(交接處刪除了)
- # cv2.BORDER_REPLICATE: 使用最邊界的像素值代替,類似于 aaaaaa|abcdefgh|hhhhhhh
- # cv2.BORDER_WRAP: 上下左右邊界依次替換, cdefgh|abcdefgh|abcdefg
2.案例分析
導入庫
import cv2
讀取圖像
ys = cv2.imread('dama.jpg')
ys=cv2.resize(ys,dsize=None,fx=0.5,fy=0.5)
讀取名為dama.jpg
的圖像文件,注意圖像路徑需要正確。調整圖像大小
設置邊界參數
top, bottom, left, right = 50, 50, 50, 50
定義要在圖像的上、下、左、右四個方向各添加 50 像素的邊界。
五種邊界填充方式
# 顯示原始圖像,窗口名為'yuantu'
cv2.imshow(winname='yuantu', mat=ys)
cv2.waitKey(0) # 等待按鍵,按任意鍵繼續
# 常數填充,value指定填充顏色(BGR 格式,這里是(229,25,80) )
constant = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_CONSTANT, value=(229, 25, 80))
# 依次顯示不同填充方式處理后的圖像及對應窗口名
cv2.imshow(winname='CONSTANT', mat=constant)
cv2.waitKey(0)
# 鏡面反射填充(BORDER_REFLECT 模式)
reflect = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT)
cv2.imshow(winname='REFLECT', mat=reflect)
cv2.waitKey(0)
# 帶細微差別的鏡面反射填充(BORDER_REFLECT_101 模式,也可用 BORDER_DEFAULT )
reflect101 = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT101)
cv2.imshow(winname='REFLECT_101', mat=reflect101)
cv2.waitKey(0)
# 邊界像素復制填充(BORDER_REPLICATE 模式)
replicate = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REPLICATE)
cv2.imshow(winname='REPLICATE', mat=replicate)
cv2.waitKey(0)
這里使用白色背景沒啥明顯效果,可以換成其他圖片
# 邊界循環填充(BORDER_WRAP 模式)
wrap = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_WRAP)
cv2.imshow(winname='WRAP', mat=wrap)
cv2.waitKey(0)
二、圖像運算
1.+號運算
-
# 當某位置像素相加得到的數值小于255時,該位置數值為兩圖該位置像素相加之和 # 當某位置像素相加得到的數值大于255時,該位置數值將被截斷結果并將其減去 256 例如:相加后是260,實際是260 - 256 = 4
a = cv2.imread('ting98.jpg')
b = cv2.imread('zl.png')
c = a + 10 # 圖片
cv2.imshow('yuan', a)
cv2.imshow('a+10', c)
cv2.waitKey(0)c = a[50:450, 50:400] + b[50:450, 50:400]
cv2.imshow('a+b', c)
cv2.waitKey(0)
a[50:450, 50:400]
?表示截取圖像 a 中從 (50,50) 到 (450,400) 的區域(ROI,感興趣區域)- 要求 a 和 b 的截取區域尺寸完全相同,否則會報錯
2.cv2.add()
函數
-
# 當某位置像素相加得到的數值小于255時,該位置數值為兩圖該位置像素相加之和 # 當某位置像素相加得到的數值大于255時,該位置數值為255
a = cv2.imread('ting98.jpg')
b = cv2.imread('zl.png')
b = cv2.resize(b, dsize=(400, 400))
a = cv2.resize(a, dsize=(400, 400))
c = cv2.add(a, b) # 也可以使用使用
cv2.imshow('a add b', c)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 必須保證兩個圖像尺寸和通道數完全一致(這里通過
cv2.resize()
統一為 400x400) - 與
+
號操作的區別:超過 255 的像素會被截斷為 255(而非模 256),因此亮部更易呈現白色
3.圖像加權運算
-
# 就是在計算兩幅圖像的像素值之和時,將每幅圖像的權重考慮進來。可以用公式表示為dst = src1×α + src2×β + γ
α
:src1 的權重(0~1 之間)β
:src2 的權重(0~1 之間,通常 α+β=1)γ
:亮度調節常數(可正可負,用于整體提亮或變暗)
a = cv2.imread('ting98.jpg')
b = cv2.imread('zl.png')
b = cv2.resize(b, dsize=(400, 400))
a = cv2.resize(a, dsize=(400, 400))
#
c = cv2.addWeighted(a, 0.2, b, 0.8, 10) # 10:圖像的亮度值(常數),將添加到加權和上
cv2.imshow('addWeighted', c)
cv2.waitKey(0)
cv2.destroyAllWindows()
三、閾值處理
閾值處理是指刪除圖像內像素值高于一定值或低于一定值的像素點。使用的方法為:
retval, dst=cv2.threshold(src,thresh,maxval,type)
retval代表返回的閾值 # dst代表閾值分割結果圖像,與原始圖像具有相同的大小和類型 # src代表要進行閾值分割的圖像,可以是多通道的,8位或32位浮點型數值 # thresh代表要設定的閾值 # maxval代表type參數位THRESH_BINARY或者THRESH_BINARY_INV類型時,需要設定的最大值 # type代表閾值分割的類型,具體內容如下表所示:
選項 | 像素值 > thresh | 其他情況 |
---|---|---|
cv2.THRESH_BINARY | maxval | 0 |
cv2.THRESH_BINARY_INV | 0 | maxval |
cv2.THRESH_TRUNC | thresh | 當前灰度值 |
cv2.THRESH_TOZERO | 當前灰度值 | 0 |
cv2.THRESH_TOZERO_INV | 0 | 當前灰度值 |
import cv2image = cv2.imread('dama.jpg', 1) #為彩色圖像,0為灰度圖像
# 圖像縮放(寬高都縮放到原來的0.5倍)
image = cv2.resize(image, dsize=None, fy=0.5, fx=0.5)# 不同類型的閾值處理
ret, binary = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY)
ret1, binaryinv = cv2.threshold(image, 175, 255, cv2.THRESH_BINARY_INV)
ret2, trunc = cv2.threshold(image, 175, 255, cv2.THRESH_TRUNC)
ret3, tozero = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO)
ret4, tozeroinv = cv2.threshold(image, 175, 255, cv2.THRESH_TOZERO_INV)# 顯示原圖
cv2.imshow('gray', image)
cv2.waitKey(0)# 依次顯示各閾值處理結果
cv2.imshow('binary', binary)
cv2.waitKey(0)cv2.imshow('binaryinv', binaryinv)
cv2.waitKey(0)cv2.imshow('trunc', trunc)
cv2.waitKey(0)cv2.imshow('tozero', tozero)
cv2.waitKey(0)cv2.imshow('tozeroinv', tozeroinv)
cv2.waitKey(0)
代碼說明:
- 代碼使用
cv2.threshold()
函數實現了五種不同類型的閾值處理 - 所有處理使用的閾值 (thresh) 都是 175,最大值 (maxval) 都是 255
- 通過
cv2.imshow()
和cv2.waitKey(0)
實現了圖像的逐一顯示
四、圖像平滑處理
????????圖像平滑(smoothing)也稱為“模糊處理”(blurring)
????????圖像平滑處理是數字圖像處理中一種常用的技術,其核心目的是減少或消除圖像中的噪聲(如隨機干擾、斑點等),同時盡可能保留圖像的重要細節信息,使圖像變得更加平滑、清晰。在實際應用中,圖像采集、傳輸等過程可能會引入噪聲,平滑處理能有效改善圖像質量,為后續的圖像分析、識別等操作奠定基礎。
????????下面是常用的一些濾波器
????????? 均值濾波(鄰域平均濾波)-> blur函數
????????? 方框濾波-> boxFilter函數
????????? 高斯濾波->GaussianBlur函數
???????? 中值濾波->medianBlur函數
1.椒鹽噪聲
椒鹽噪聲是數字圖像中常見的一種噪聲類型,因其外觀類似圖像上隨機分布的黑白斑點(如同撒了鹽粒和胡椒粒)而得名。
特點
- 噪聲形態:表現為圖像中隨機出現的白色亮點(鹽噪聲,對應像素值為 255,即最大亮度)和黑色暗點(椒噪聲,對應像素值為 0,即最小亮度)。
- 產生原因:通常由圖像傳感器故障、傳輸信道干擾(如數據丟失)、模數轉換錯誤等導致,例如相機拍攝時的突發電子干擾、圖像壓縮或傳輸中的比特錯誤等。
- 分布特性:噪聲點在圖像中隨機分布,數量可多可少,且每個噪聲點通常只影響單個像素(少數情況下可能影響相鄰像素)。
對圖像的影響
椒鹽噪聲會破壞圖像的局部像素信息,導致圖像細節模糊或失真,尤其會干擾邊緣檢測、特征提取等后續圖像處理任務的準確性。例如,在文字識別中,椒鹽噪聲可能導致字符筆畫斷裂或出現偽影,影響識別率。
對一個圖片添加椒鹽噪聲
import cv2
import numpy as npdef add_peppersalt_noise(image, n=10000):result = image.copy() # 復制原圖,避免修改原圖h, w = image.shape[:2] # 獲取圖片的高和寬(忽略通道數)for i in range(n): # 生成n個椒鹽噪聲點# 隨機生成噪聲點的坐標x = np.random.randint(1, h) # 隨機行坐標(1到h-1之間)y = np.random.randint(1, w) # 隨機列坐標(1到w-1之間)# 50%概率生成鹽噪聲(白點),50%概率生成椒噪聲(黑點)if np.random.randint(0, 2) == 0:result[x, y] = 0 # 椒噪聲(黑色點,像素值0)else:result[x, y] = 255 # 鹽噪聲(白色點,像素值255)return result
# #
image = cv2.imread('dama.jpg')
image=cv2.resize(image,dsize=None,fx=0.5,fy=0.5)
cv2.imshow( 'yntu',image)
cv2.waitKey(0)
noise = add_peppersalt_noise(image)
cv2.imshow( 'noise',noise)
cv2.waitKey(0)
????????我們可以看見第二張圖片出現很多黑白色的點,這就是椒鹽噪聲。接下來我要介紹四種去除椒鹽噪聲的方法
2.均值濾波(Mean Filtering)
- 原理:用圖像中某個像素周圍(如 3×3、5×5 的鄰域)所有像素的平均值來替代該像素的值。
- 實現方式:通過一個固定大小的滑動窗口(卷積核)在圖像上移動,窗口內所有像素值的總和除以窗口像素數量,得到的結果作為窗口中心像素的新值。
- 特點:能有效抑制高斯噪聲等,但會使圖像邊緣變得模糊,窗口越大,平滑效果越明顯,但圖像細節丟失也越多。
紅色點計算公式:(1*12+1*45+128*1+100*1+66*1+212*1+88*1+15*1+215*1)/9
藍色點計算公式:對于藍色點我們只能讀取四個數據,一般我們會在外面一圈填充0或者1或者中心點的數值進行計算
dst=cv2.blur(src,ksize,anchor,borderType)
# dst是返回值 # src是需要處理的圖像 # kszje是濾波核(卷積核)的大小 # anchor是錨點,默認值是(-1,-1)一般無需更改 # borderType是邊界樣式,一般無需更改 # 一般情況下,使用dst=cv2.blur(src,ksize)即可
blur_1 = cv2.blur(noise, ksize=(3, 3)) # 卷積核為3,3 效果一般,清晰度一般
cv2.imshow('blur_1', blur_1)
cv2.waitKey(0)blur_2 = cv2.blur(noise, ksize=(63, 63))
cv2.imshow('blur_2', blur_2)
cv2.waitKey(0)
3.方框濾波
是指用當前像素點周圍nxn個像素值的和來代替當前像素值
dst=cv2.boxFilter (src, ddepth, ksize, anchor, normalize, borderType)
?● dst是返回值,表示進行方框濾波后得到的處理結果。
??? ● src 是需要處理的圖像,即原始圖像。
?? ● ddepth是處理結果圖像的圖像深度,一般使用-1表示與原始圖像使用相同的圖像深度。(可以理解為數據類型)
?? ● ksize 是濾波核的大小。濾波核大小是指在濾波處理過程中所選擇的鄰域圖像的高 度和寬度。
?? ● anchor 是錨點,(指對應哪個區域)
?? ● normalize 表示在濾波時是否進行歸一化。
?????? 1.當值為True時,歸一化,用鄰域像素值的和除以面積。 此時方框濾波與 均值濾波 效果相同。
?????? 2.當值為False時,不歸一化,直接使用鄰域像素值的和。和>255時使用255
boxFilter_1 = cv2.boxFilter(noise, -1, ksize=(3, 3), normalize=True) # 2、方框濾波
cv2.imshow('boxFilter_1', boxFilter_1)
cv2.waitKey(0)boxFilter_2 = cv2.boxFilter(noise, -1, ksize=(3, 3), normalize=False)
cv2.imshow('boxFilter_2', boxFilter_2)
cv2.waitKey(0)
4. 高斯濾波(Gaussian Filtering)
- 原理:基于高斯函數設計卷積核,對像素周圍鄰域進行加權平均,距離中心像素越近的像素權重越大,反之越小。
- 實現方式:卷積核的數值服從高斯分布,通過該核與圖像進行卷積運算,實現平滑處理。
- 特點:相比均值濾波,在平滑噪聲的同時能更好地保留圖像邊緣信息,對高斯噪聲的抑制效果較好。
cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, dst]]])
參數說明:src:輸入圖像,通常是一個NumPy數組。ksize:濾波器的大小,它是一個元組,表示在水平和垂直方向上的像素數量。例如,(5, 5)表示一個5x5的濾波器。 sigmaX和sigmaY:分別表示在X軸和Y軸方向上的標準差。這些值與濾波器大小相同。默認情況下,它們都等于0,這意味著沒有高斯模糊。dst:輸出圖像,通常是一個NumPy數組。如果為None,則會創建一個新的數組來存儲結果。
GaussianB = cv2.GaussianBlur(noise, ksize=(3,3), sigmaX=1) #標準差為1,標準正太分布。 3、高斯濾波
cv2.imshow('GaussianBlur', GaussianB)
cv2.waitKey(0)
5.中值濾波(Median Filtering)
- 原理:用像素鄰域內所有像素值的中值來替代該像素的值。
- 實現方式:滑動窗口遍歷圖像,將窗口內的像素值排序后,取中間值作為中心像素的新值。
- 特點:對椒鹽噪聲(圖像中出現的隨機黑白點)抑制效果顯著,且不易使圖像邊緣模糊,是處理椒鹽噪聲的首選方法。
這就很科學的把0和255給去掉了,也就是白色與黑色
cv2.medianBlur(src, ksize[, dst])
參數說明: src:輸入圖像。 ksize:濾波器的大小,它是一個整數,表示在水平和垂直方向上的像素數量。例如,5表示一個5x5的濾波器。 dst:輸出圖像,通常是一個NumPy數組。如果為None,則會創建一個新的數組來存儲結果。
medianB = cv2.medianBlur(noise, ksize=3) # 4、中值濾波
cv2.imshow('medianBlur', medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
總結:
????????不同的平滑處理方法各有側重,選擇時需根據圖像噪聲類型、對圖像細節保留的要求等因素綜合考慮。例如,處理椒鹽噪聲優先用中值濾波,需要保留邊緣時可選用雙邊濾波,而處理高斯噪聲時高斯濾波是較好的選擇。