一、圖片的邊界填充
在 OpenCV 中,cv2.copyMakeBorder()
是用于給圖像添加邊框(邊緣)的核心 API,其完整語法和參數說明如下:
函數完整定義
cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value=None)
參數詳細說明
src:
輸入圖像(numpy.ndarray
類型),可以是單通道(灰度圖)或多通道(如 RGB/BGR 彩色圖)。top:
整數,指定圖像頂部需要添加的邊框像素數量。bottom:
整數,指定圖像底部需要添加的邊框像素數量。left:
整數,指定圖像左側需要添加的邊框像素數量。right:
整數,指定圖像右側需要添加的邊框像素數量。borderType:
邊框填充方式的枚舉值,決定了邊框像素如何生成。OpenCV 支持以下類型:cv2.BORDER_WRAP
:外包裝填充
邊框像素從圖像的對側 “纏繞” 而來(類似平鋪效果)。
例:原圖邊緣為[1,2,3,4]
,右側邊框可能填充[1,2]
(復用左側內容)。cv2.BORDER_REFLECT_101
(或cv2.BORDER_DEFAULT
):對稱填充
與REFLECT
類似,但反射以邊緣像素為軸,包含邊緣像素。
例:原圖邊緣為[1,2,3,4]
,填充后可能為[2,1,1,2,3,4,4,3]
(OpenCV 推薦默認使用此類型)。cv2.BORDER_REFLECT
:反射填充
邊框像素是原圖邊緣的鏡像反射,不包含邊緣像素本身的重復。
例:原圖邊緣為[1,2,3,4]
,填充后可能為[3,2,1,2,3,4,3,2]
。cv2.BORDER_REPLICATE
:復制填充
邊框像素由原圖最邊緣的像素復制而來(如右側邊框復制原圖最右列像素,頂部邊框復制原圖最上行像素)。cv2.BORDER_CONSTANT
:常數填充
邊框像素使用指定的單一顏色填充,需配合value
參數設置顏色(BGR 格式,如(255,0,0)
表示藍色)。
value:
可選參數,僅當borderType=cv2.BORDER_CONSTANT
時有效,指定邊框的顏色值:彩色圖:BGR 三通道值(如
(0,255,0)
表示綠色)。灰度圖:單值(如
128
表示灰色)。
返回值
添加邊框后的新圖像(
numpy.ndarray
類型),尺寸為:(src.shape[0] + top + bottom, src.shape[1] + left + right, src.shape[2])
(彩色圖)
或?(src.shape[0] + top + bottom, src.shape[1] + left + right)
(灰度圖)。
示例代碼:
可以自選隨便一張圖片
# 導入OpenCV庫
import cv2# 讀取圖像文件,返回BGR格式的numpy數組
# 注意:如果圖像路徑錯誤,會返回None但不報錯
ys = cv2.imread('mm.jpg')# 調整圖像尺寸:按比例縮小
# dsize=None表示不直接指定目標尺寸,而是通過fx和fy設置縮放比例
# fx=0.2表示寬度縮小為原來的20%,fy=0.2表示高度縮小為原來的20%
ys = cv2.resize(ys, dsize=None, fx=0.2, fy=0.2)# 下面是另一種尺寸調整方式(被注釋掉了)
# 直接指定目標尺寸為(640, 480),參數格式為(寬度, 高度)
# ys = cv2.resize(ys, (640, 480))# 定義邊界填充的尺寸:上下左右各填充50像素
# top: 頂部填充像素數,bottom: 底部填充像素數
# left: 左側填充像素數,right: 右側填充像素數
top, bottom, left, right = 50, 50, 50, 50# 1. 常量邊界填充(BORDER_CONSTANT)
# 使用指定的顏色填充邊界,這里填充為(229,25,80)對應的粉紅色
# 參數說明:原圖像、上下左右填充量、邊界類型、填充顏色
constant = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_CONSTANT, value=(229,25,80))# 2. 反射邊界填充(BORDER_REFLECT)
# 以圖像邊緣為軸,對稱反射填充像素(類似鏡像)
# 例如原圖像邊緣像素為a,b,c,則填充為c,b,a,b,c,b,a...
reflect = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT)# 3. 反射101邊界填充(BORDER_REFLECT101)
# 與REFLECT類似,但不重復邊緣像素
# 例如原圖像邊緣像素為a,b,c,則填充為b,a,b,c,b,a...
reflect101 = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT101)# 4. 復制邊界填充(BORDER_REPLICATE)
# 重復最邊緣的像素進行填充
# 例如原圖像邊緣像素為a,b,c,則填充為c,c,c,c,c...
replicate = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REPLICATE)# 5. 環繞邊界填充(BORDER_WRAP)
# 以圖像對側的內容填充邊界(類似平鋪效果)
# 例如右側邊界用左側內容填充,底部邊界用頂部內容填充
wrap = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_WRAP)# 顯示原始圖像,窗口名為"1.yuantu"
cv2.imshow('1.yuantu', ys)
# cv2.waitKey(0) # 注釋掉的等待按鍵,不啟用時所有窗口會同時顯示# 顯示常量填充效果
cv2.imshow('2.CONSTANT', constant)
# cv2.waitKey(0)# 顯示反射填充效果
cv2.imshow('3.REFLECT', reflect)
# cv2.waitKey(0)# 顯示反射101填充效果
cv2.imshow('4.REFLECT 101', reflect101)
# cv2.waitKey(0)# 顯示復制填充效果
cv2.imshow('5.REPLICATE', replicate)
# cv2.waitKey(0)# 顯示環繞填充效果
cv2.imshow('6.WRAP', wrap)# 等待用戶按鍵,0表示無限等待,按任意鍵后關閉所有窗口
cv2.waitKey(0)
二、圖像的運算
1. 像素值加法(numpy 運算)
c = a + 10 # 對圖像a的所有像素值加10
c = a[50:250, 50:200] + b[50:250, 50:200] # 對指定區域的像素相加
- 原理:基于 Numpy 數組的元素級運算,每個像素的 BGR 三個通道值分別參與運算
- 特點:屬于模運算(溢出時取模),例如像素值
250 + 10 = 260 → 260 % 256 = 4
- 限制:要求參與運算的圖像區域尺寸完全相同(如
a[50:250,50:200]
與b[50:250,50:200]
的寬高必須一致)
2. 圖像加法(OpenCV 函數)
c = cv2.add(a, b)
- 功能:與
a + b
類似,但屬于飽和運算(溢出時取最大值 255) - 區別:
a + b
:模運算(250 + 10 = 4)cv2.add(a, b)
:飽和運算(250 + 10 = 255)
- 優勢:更符合視覺預期,避免像素值溢出導致的異常顏色
3. 加權圖像融合:cv2.addWeighted()
c = cv2.addWeighted(a, 0.5, b, 0.5, 10)
- 功能:按權重融合兩張圖像,公式為:
result = α×img1 + β×img2 + γ
- 參數:
a
/b
:輸入圖像(需尺寸和通道數相同)0.5
/0.5
:權重α
和β
(總和可不為 1,控制兩張圖像的占比)10
:偏置項γ
(對結果整體加一個常量,調整亮度)
- 應用場景:實現圖像淡入淡出、疊加水印等效果
示例代碼:
# 導入OpenCV庫,cv2是OpenCV在Python中的別名
import cv2# 讀取圖像文件,返回的是numpy數組(ndarray),默認讀取為彩色圖像(BGR格式)
# 注意:如果文件路徑錯誤,會返回None但不報錯
a = cv2.imread('flower_dog.jpg') # 讀取第一張圖像
b = cv2.imread('img.png') # 讀取第二張圖像
# 像素值運算:對圖像a的所有像素點的每個通道值都加10
# 原理:numpy數組的元素級運算,屬于模運算(超過255會取模,如250+10=260→260%256=4)
c = a + 10
# 創建窗口顯示圖像,第一個參數是窗口名稱,第二個參數是要顯示的圖像
cv2.imshow('yuan', a) # 顯示原始圖像a,窗口名為"yuan"
cv2.imshow('a+10', c) # 顯示像素值加10后的圖像c,窗口名為"a+10"
# 等待鍵盤輸入,參數0表示無限等待,直到用戶按下任意鍵
# 必須配合imshow使用,否則窗口會一閃而逝
cv2.waitKey(0)
# 圖像區域像素相加:對a和b的指定區域進行像素加法
# [50:250,50:200]表示裁剪圖像的行范圍50-250,列范圍50-200(注意是高×寬)
# 要求兩個區域的尺寸完全相同,否則會報錯
c = a[50:250, 50:200] + b[50:250, 50:200]
cv2.imshow('a+b', c) # 顯示區域相加的結果# 重新讀取圖像(可能因為之前的操作修改了原圖像數據)
a = cv2.imread('flower_dog.jpg')
b = cv2.imread('img.png')
# 調整圖像尺寸:將a和b都調整為400×400像素
# 注意參數是(寬度, 高度),與圖像數組的(高度,寬度)維度順序相反
a = cv2.resize(a, (400, 400))
b = cv2.resize(b, (400, 400))
# OpenCV的圖像加法函數:與a+b的區別是采用飽和運算(超過255則取255)
# 例如250+10=255而不是4,更符合視覺預期
c = cv2.add(a, b)
cv2.imshow('a,add,b', c) # 顯示cv2.add的運算結果
cv2.waitKey(0) # 等待按鍵輸入
cv2.destroyAllWindows() # 關閉所有OpenCV創建的窗口# 再次讀取圖像,準備進行加權融合
a = cv2.imread('flower_dog.jpg')
b = cv2.imread('img.png')
# 統一圖像尺寸,確保可以進行融合運算
a = cv2.resize(a, (400, 400))
b = cv2.resize(b, (400, 400))
# 圖像加權融合:result = α*a + β*b + γ
# 參數說明:a和b是輸入圖像,0.5和0.5是權重,10是亮度調節值(偏置項)
# 公式:c = 0.5*a + 0.5*b + 10
c = cv2.addWeighted(a, 0.5, b, 0.5, 10)
cv2.imshow('addweighted', c) # 顯示加權融合結果
cv2.waitKey(0) # 等待按鍵輸入
cv2.destroyAllWindows() # 關閉所有窗口,釋放資源
三、圖像的閾值處理
1.?cv2.THRESH_BINARY
(二進制閾值)
核心邏輯:將圖像像素值與閾值比較,大于閾值的像素設為最大值(通常為 255,白色),小于等于閾值的設為 0(黑色)。
數學表達式:
dst(x,y) = maxval, if src(x,y) > thresh
dst(x,y) = 0, otherwise
直觀理解:非黑即白的二值化,直接將圖像分為兩個極端。
適用場景:
- 文檔掃描(將文字與背景分離)
- 目標檢測中提取輪廓(如二維碼識別)
- 去除灰度圖中灰度值較低的背景噪聲
2.?cv2.THRESH_BINARY_INV
(反二進制閾值)
核心邏輯:與THRESH_BINARY
完全相反,大于閾值的像素設為 0(黑色),小于等于閾值的設為最大值(255,白色)。
數學表達式:
dst(x,y) = 0, if src(x,y) > thresh
dst(x,y) = maxval, otherwise
直觀理解:黑白反轉的二值化,原來看起來亮的區域變暗,暗的區域變亮。
適用場景:
- 文字識別中需要 “黑底白字” 轉 “白底黑字”
- 提取圖像中較暗的目標(如夜景中的燈光)
- 修正光照不均導致的明暗顛倒問題
3.?cv2.THRESH_TRUNC
(截斷閾值)
核心邏輯:像素值大于閾值時,強制設為閾值本身;小于等于閾值時,保持原像素值不變。
數學表達式:
dst(x,y) = thresh, if src(x,y) > thresh
dst(x,y) = src(x,y), otherwise
直觀理解:“截斷” 過亮的像素,將超過閾值的亮度 “壓” 到閾值水平,保留暗部細節。
適用場景:
- 處理過曝圖像(如強光導致的白色區域過大)
- 抑制高光區域(如人像攝影中過亮的皮膚)
- 保留圖像暗部紋理,同時避免亮部過曝丟失信息
4.?cv2.THRESH_TOZERO
(歸零閾值)
核心邏輯:像素值大于閾值時,保持原像素值;小于等于閾值時,設為 0(黑色)。
數學表達式:
dst(x,y) = src(x,y), if src(x,y) > thresh
dst(x,y) = 0, otherwise
直觀理解:只保留亮度高于閾值的區域,低于閾值的區域直接 “歸零”(變黑)。
適用場景:
- 提取圖像中較亮的目標(如 X 光片中的高亮病變區域)
- 去除暗部噪聲(如低光照下的圖像噪點)
- 保留目標區域(通常較亮)并簡化背景(變為黑色)
5.?cv2.THRESH_TOZERO_INV
(反歸零閾值)
核心邏輯:與THRESH_TOZERO
相反,像素值大于閾值時,設為 0(黑色);小于等于閾值時,保持原像素值。
數學表達式:
dst(x,y) = 0, if src(x,y) > thresh
dst(x,y) = src(x,y), otherwise
直觀理解:只保留亮度低于閾值的區域,高于閾值的區域 “歸零”(變黑)。
適用場景:
- 提取圖像中較暗的目標(如夜景中的陰影區域)
- 去除高光干擾(如反光、光斑)
- 保留暗部細節,同時消除過亮區域的影響
總結:5 種閾值類型的核心差異
閾值類型 | 大于閾值的像素處理 | 小于等于閾值的像素處理 | 核心作用 |
---|---|---|---|
THRESH_BINARY | 設為 maxval(如 255) | 設為 0 | 亮區域保留,暗區域變黑 |
THRESH_BINARY_INV | 設為 0 | 設為 maxval(如 255) | 暗區域保留,亮區域變黑 |
THRESH_TRUNC | 設為閾值本身 | 保持原值 | 抑制過亮區域,保留暗部 |
THRESH_TOZERO | 保持原值 | 設為 0 | 保留亮區域,暗區域變黑 |
THRESH_TOZERO_INV | 設為 0 | 保持原值 | 保留暗區域,亮區域變黑 |
示例代碼:
# 導入OpenCV庫,OpenCV是一個用于計算機視覺的開源庫
import cv2# 讀取圖像文件,并轉換為灰度圖
# 參數說明:
# 'mm.jpg':圖像文件路徑(需與腳本同目錄或使用絕對路徑)
# 0:讀取模式,0表示以灰度圖模式讀取(單通道)
image = cv2.imread('mm.jpg', 0)# 調整圖像尺寸為400x400像素
# 注意:resize函數的參數是(width, height),與圖像通常的(height, width)格式相反
image = cv2.resize(image, (400, 400))# 1. 二進制閾值處理
# 參數說明:
# image:輸入的灰度圖像
# 130:設定的閾值
# 255:最大值(用于THRESH_BINARY和THRESH_BINARY_INV類型)
# cv2.THRESH_BINARY:閾值類型,大于閾值的像素設為255,否則設為0
# 返回值:ret為使用的閾值,binary為處理后的圖像
ret, binary = cv2.threshold(image, 130, 255, cv2.THRESH_BINARY)# 2. 反二進制閾值處理
# cv2.THRESH_BINARY_INV:與BINARY相反,大于閾值的像素設為0,否則設為255
ret1, binaryInv = cv2.threshold(image, 130, 255, cv2.THRESH_BINARY_INV)# 3. 截斷閾值處理
# cv2.THRESH_TRUNC:大于閾值的像素設為閾值(130),否則保持原像素值
ret2, trunc = cv2.threshold(image, 130, 255, cv2.THRESH_TRUNC)# 4. 歸零閾值處理
# cv2.THRESH_TOZERO:大于閾值的像素保持原值,否則設為0
ret3, tozero = cv2.threshold(image, 130, 255, cv2.THRESH_TOZERO)# 5. 反歸零閾值處理
# cv2.THRESH_TOZERO_INV:與TOZERO相反,大于閾值的像素設為0,否則保持原值
ret4, tozeroInv = cv2.threshold(image, 130, 255, cv2.THRESH_TOZERO_INV)# 顯示原始灰度圖像
# 參數:窗口名稱('gray')和要顯示的圖像
cv2.imshow('gray', image)# 顯示二進制閾值處理后的圖像
# 效果:像素值>130的區域變為白色(255),<=130的區域變為黑色(0)
cv2.imshow('binary', binary)# 顯示反二進制閾值處理后的圖像
# 效果:像素值>130的區域變為黑色(0),<=130的區域變為白色(255)
cv2.imshow('binaryInv', binaryInv)# 顯示截斷閾值處理后的圖像
# 效果:像素值>130的區域變為130(灰色),<=130的區域保持原圖亮度
cv2.imshow('trunc', trunc)# 顯示歸零閾值處理后的圖像
# 效果:像素值>130的區域保持原圖亮度,<=130的區域變為黑色(0)
cv2.imshow('tozero', tozero)# 顯示反歸零閾值處理后的圖像
# 效果:像素值>130的區域變為黑色(0),<=130的區域保持原圖亮度
cv2.imshow('tozeroInv', tozeroInv)# 等待用戶按鍵操作
# 參數0表示無限等待,直到用戶按下任意鍵
# 所有窗口會在用戶按鍵后關閉
cv2.waitKey(0)
四、圖像的平滑處理
圖像平滑(smoothing)也稱為“模糊處理”(bluring)
通過消除圖像中的噪聲或細節來使圖像看起來更為模糊,從而實現平滑效果
可以用來壓制、弱化或消除圖像中的細節、突變和噪聲。
下面是常用的一些濾波器
均值濾波(鄰域平均濾波)-> blur函數
方框濾波-> boxFilter函數
高斯濾波->GaussianBlur函數
中值濾波->medianBlur函數
dst=cv2.blur(src,ksize,anchor,borderType)
dst是返回值
src是需要處理的圖像
ksize是濾波核(卷積核)的大小
anchor是錨點,默認值是(-1,-1)一般無需更改
borderType是邊界樣式,一般無需更改
一般情況下,使用dst=cv2.blur(src,ksize)即可
準備代碼:
準備一個含有噪聲點的圖像來方便后面的演示
# 導入OpenCV庫,用于圖像處理
import cv2
# 導入numpy庫,用于數值計算和隨機數生成
import numpy as np# 定義添加椒鹽噪聲的函數
# 參數:
# image: 原始圖像
# n: 噪聲點的數量,默認值為10000
def add_peppersalt_noize(image, n=10000):# 復制原始圖像,避免直接修改原圖result = image.copy()# 獲取圖像的高度和寬度(shape[:2]取前兩個值,即高度和寬度)h, w = image.shape[:2]# 循環n次,生成n個噪聲點for i in range(n):# 隨機生成x坐標(行),范圍在1到h之間x = np.random.randint(1, h)# 隨機生成y坐標(列),范圍在1到w之間y = np.random.randint(1, w)# 隨機生成0或1,決定是添加椒噪聲(0)還是鹽噪聲(255)if np.random.randint(0, 2) == 0:# 添加椒噪聲(黑色點)result[x, y] = 0else:# 添加鹽噪聲(白色點)result[x, y] = 255# 返回添加噪聲后的圖像return result# 讀取圖像文件'mm.jpg',默認讀取為BGR格式
image = cv2.imread('mm.jpg')
# 調整圖像大小為400x400像素
image = cv2.resize(image, (400, 400))# 創建一個窗口顯示原始圖像,窗口名為'mm'
cv2.imshow('mm', image)# 調用函數為圖像添加椒鹽噪聲
noise = add_peppersalt_noize(image)# 創建一個窗口顯示帶噪聲的圖像,窗口名為'noise'
cv2.imshow('noise', noise)# 等待用戶按下任意鍵,參數0表示無限等待
cv2.waitKey(0)
# 關閉所有OpenCV創建的窗口(雖然代碼中沒寫,但通常建議加上)
# cv2.destroyAllWindows()
1、均值濾波
cv2.blur()
?是 OpenCV 中用于實現均值模糊(也稱為歸一化盒式濾波)的 API,其核心原理是用圖像中某一像素周圍鄰域內所有像素的平均值來替代該像素的值,從而達到平滑圖像、降低噪聲的效果。
語法格式:
dst = cv2.blur(src, ksize[, anchor[, borderType]])
參數說明:
src(必選):
輸入圖像(源圖像),可以是單通道灰度圖或多通道彩色圖(如 BGR 格式)。ksize(必選):
模糊核(卷積核)的大小,格式為?(width, height)
,例如?(3,3)
?表示使用 3×3 的正方形核。
核的尺寸越大,模糊效果越強,但圖像細節損失也越多。anchor(可選):
核的錨點(即計算均值時的參考點),默認值為?(-1,-1)
,表示錨點位于核的中心。borderType(可選):
邊界填充方式,用于處理圖像邊緣像素(因為邊緣像素沒有完整的鄰域)。
默認值為?cv2.BORDER_DEFAULT
,常用選項還包括?cv2.BORDER_CONSTANT
(常量填充)、cv2.BORDER_REPLICATE
(復制邊緣像素填充)等。
示例代碼(接上面的準備代碼):
blur_1 = cv2.blur(noise,(3,3))#卷積核為(3,3)
cv2.imshow('bler_1',blur_1)
blur_2 = cv2.blur(noise,(9,9))#卷積核為(3,3)
cv2.imshow('bler_2',blur_2)
blur_3 = cv2.blur(noise,(15,15))#卷積核為(3,3)
cv2.imshow('bler_3',blur_3)
blur_4 = cv2.blur(noise,(21,21))#卷積核為(3,3)
cv2.imshow('bler_4',blur_4)
cv2.waitKey(0)
2、方框濾波
cv2.boxFilter()
?是 OpenCV 中一個靈活的線性濾波函數,用于實現盒式濾波(Box Filter)。它可以看作是?cv2.blur()
?的通用版本,既可以實現均值模糊(歸一化盒式濾波),也可以實現非歸一化的盒式濾波(僅對鄰域像素求和)。
語法格式:
dst = cv2.boxFilter(src, ddepth, ksize[, anchor[, normalize[, borderType]]])
參數說明:
src(必選):
輸入圖像(源圖像),可以是單通道灰度圖或多通道彩色圖。ddepth(必選):
輸出圖像的深度(數據類型),常用值:cv2.CV_8U
:8 位無符號整數(0-255)cv2.CV_32F
:32 位浮點數-1
:表示輸出圖像深度與輸入圖像相同(推薦使用)
ksize(必選):
濾波核(卷積核)的大小,格式為?(width, height)
,例如?(3,3)
?表示 3×3 的核。anchor(可選):
核的錨點(計算濾波時的參考點),默認值?(-1,-1)
?表示錨點在核中心。normalize(可選):
布爾值,是否對濾波結果進行歸一化:True
(默認):歸一化盒式濾波,即鄰域像素求和后除以核的面積(等價于?cv2.blur()
)。False
:非歸一化盒式濾波,僅計算鄰域像素的總和(可能導致像素值溢出,需注意數據類型)。
borderType(可選):
邊界填充方式,用于處理圖像邊緣像素,默認值為?cv2.BORDER_DEFAULT
,其他常用選項同?cv2.blur()
。
功能說明:
當?
normalize=True
?時,cv2.boxFilter()
?與?cv2.blur()
?效果完全一致,都是計算鄰域像素的平均值:dst(x,y) = (sum of src(x',y') in ksize) / (width×height)
當?
normalize=False
?時,僅計算鄰域像素的總和:dst(x,y) = sum of src(x',y') in ksize
這種模式下,結果可能超過像素值范圍(如 0-255),因此通常需要配合?ddepth=cv2.CV_32F
?使用,避免溢出。
3、高斯濾波
cv2.GaussianBlur()
?是 OpenCV 中用于實現高斯模糊的 API,其核心原理是使用高斯核(符合高斯分布的卷積核)對圖像進行卷積操作,相比均值模糊能更好地保留圖像細節,同時有效去除高斯噪聲。
語法格式:
dst = cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, borderType]]])
參數說明:
src(必選):
輸入圖像(源圖像),可以是單通道灰度圖或多通道彩色圖(如 BGR 格式)。ksize(必選):
高斯核的大小,格式為?(width, height)
,需滿足:寬度和高度必須是正奇數(如?
(3,3)
、(5,5)
、(7,7)
?等)。- 若寬度≠高度,核可以是矩形(如?
(3,5)
),但通常使用正方形核。
核的尺寸越大,模糊效果越強。
sigmaX(可選):
高斯核在 X 方向(水平方向)的標準差,控制高斯分布的 "寬窄":sigmaX > 0
:使用指定值作為 X 方向標準差。sigmaX = 0
(默認):根據核尺寸自動計算(sigma = 0.3×((ksize-1)×0.5 - 1) + 0.8
)。sigmaX < 0
:不合法,會報錯。
sigmaY(可選):
高斯核在 Y 方向(垂直方向)的標準差:- 若未指定或為?
0
:默認與?sigmaX
?相等(各向同性高斯模糊)。 - 若?
sigmaY > 0
:可實現 X、Y 方向不同強度的模糊(各向異性)。
- 若未指定或為?
borderType(可選):
邊界填充方式,處理圖像邊緣像素,默認值為?cv2.BORDER_DEFAULT
,其他選項同?cv2.blur()
。
示例代碼(接上面的準備代碼):
GaussianB = cv2.GaussianBlur(noise, ksize=(3,3), sigmaX=1) # 標準正態分布、3、3、高斯濾波
cv2.imshow(winname='GaussianBlur', mat=GaussianB)
cv2.waitKey(0)
4、中值濾波
cv2.medianBlur()
?是 OpenCV 中用于實現中值濾波的 API,其核心原理是用圖像中某一像素周圍鄰域內所有像素的中值來替代該像素的值。這種濾波方式對椒鹽噪聲(圖像中隨機出現的黑白點)有非常好的去除效果,同時能較好地保留圖像邊緣細節。
語法格式:
dst = cv2.medianBlur(src, ksize[, dst])
參數說明:
src(必選):
輸入圖像(源圖像),可以是單通道灰度圖或多通道彩色圖(如 BGR 格式)。
注意:該函數僅支持 8 位單通道圖像、16 位單通道圖像(CV_16U
)或 32 位浮點單通道圖像(CV_32F
)。對于多通道圖像,會對每個通道分別進行中值濾波。ksize(必選):
濾波核的大小,必須是大于 1 的正奇數(如?3
、5
、7
?等),表示使用?ksize×ksize
?的正方形核。
核的尺寸越大,去噪效果越強,但圖像細節損失也可能越多。dst(可選):
輸出圖像,與輸入圖像具有相同的尺寸和類型,通常不需要手動指定,函數會自動創建并返回。
功能原理:
中值濾波的計算過程:
- 以目標像素為中心,取?
ksize×ksize
?大小的鄰域窗口; - 將窗口內所有像素值按大小排序;
- 取排序后的中間值作為目標像素的新值。
例如,使用 3×3 核時,會對 9 個像素值排序,取第 5 個值(中間值)作為結果。
示例代碼(接上面的準備代碼):
medianB = cv2.medianBlur(noise, ksize=3) # 4、中值濾波
cv2.imshow(winname='medianBlur', mat=medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
實戰項目:
現在有一個視頻,如上述的做法將其添加噪聲點并優化(視頻已經上傳)
示例代碼:
# 導入OpenCV庫,用于圖像處理和視頻操作
import cv2
# 導入NumPy庫,用于數值計算和隨機數生成
import numpy as np## 噪聲點選取:添加椒鹽噪聲
def add_peppersalt_noize(image, n=10000):"""為圖像添加椒鹽噪聲參數:image: 原始圖像n: 噪聲點數量,默認10000個返回:添加噪聲后的圖像"""# 復制原始圖像,避免直接修改原圖result = image.copy()# 獲取圖像的高度和寬度(忽略通道數)h, w = image.shape[:2]# 循環生成n個噪聲點for i in range(n):# 隨機生成一個高度方向的坐標(1到h之間)x = np.random.randint(1, h)# 隨機生成一個寬度方向的坐標(1到w之間)y = np.random.randint(1, w)# 50%概率生成胡椒噪聲(黑色點),50%概率生成鹽噪聲(白色點)if np.random.randint(0, 2) == 0:# 胡椒噪聲:將像素值設為0(黑色)result[x, y] = 0else:# 鹽噪聲:將像素值設為255(白色)result[x, y] = 255# 返回添加噪聲后的圖像return result## 視頻處理主程序# 創建VideoCapture對象,打開視頻文件'test.avi'
cap = cv2.VideoCapture('test.avi')
# 初始化幀計數器
frame_number = 0# 循環讀取視頻的每一幀
while cap.isOpened():# 讀取一幀圖像# ret: 布爾值,表示是否成功讀取幀# frame: 讀取到的當前幀圖像ret, frame = cap.read()# 如果沒有讀取到幀(視頻結束),退出循環if not ret:break# 調整幀的大小,縮小為原來的70%(fx和fy分別為x和y方向的縮放因子)# dsize=None表示根據縮放因子自動計算目標大小frame = cv2.resize(frame, dsize=None, fx=0.7, fy=0.7)# 為當前幀添加椒鹽噪聲noise = add_peppersalt_noize(frame)# 使用中值濾波去除噪聲,卷積核大小為3x3# 中值濾波對椒鹽噪聲有很好的去除效果medianB = cv2.medianBlur(noise, ksize=3)# 顯示原始圖像窗口,窗口名為'begin'cv2.imshow('begin', frame)# 顯示添加噪聲后的圖像窗口,窗口名為'noise'cv2.imshow('noise', noise)# 顯示中值濾波處理后的圖像窗口,窗口名為'mesianB'cv2.imshow('mesianB', medianB)# 等待25毫秒,接收鍵盤輸入# 25ms的延遲大約對應40fps的播放速度key = cv2.waitKey(25)# 如果按下ESC鍵(ASCII碼為27),退出循環if key == 27:print("用戶手動退出")break# 幀計數器加1frame_number += 1# 釋放視頻捕獲對象,關閉視頻文件
cap.release()
# 關閉所有OpenCV創建的窗口
cv2.destroyAllWindows()# 打印處理完成信息
print("視頻處理完成")