(一)在pycharm軟件中,用python語言,opencv庫實現以下功能
(1.1)圖片的邊界填充
核心流程:
讀取原始圖像
使用?cv2.imread()
?加載名為?yueshan.png
?的圖像文件統一邊界參數
設定四周留白尺寸均為?50px
(上下左右各50像素)五種邊界填充模式實驗
對同一原始圖像執行以下操作,生成帶不同特性邊框的新圖像:- ?
BORDER_CONSTANT
: 用固定值?(22,25,8)
(藍綠色)填充邊界 - ?
BORDER_REFLECT
: 鏡像翻轉相鄰像素內容作為邊界 - ?
BORDER_REFLECT101
: 奇偶對稱的特殊鏡像模式 - ?
BORDER_REPLICATE
: 直接復制邊緣像素平鋪邊界 - ?
BORDER_WRAP
: 將圖像視為周期信號循環延伸
- ?
可視化對比
通過?cv2.imshow()
?分窗口顯示原始圖像及五種邊界處理結果,按任意鍵逐幅查看
示例代碼:
# cv2.copyMakeBorder()是opencV庫中的一個函數,用于給圖像添加額外的邊界(padding)
# copyMakeBorder(src: umat, top: int, bottom: int, left: int, right: int, borderType: int, dst: umat /None = ... valve: cv2.typing.scalar = ...)
# 它有以下幾個參數:
# src:要擴充邊界的原始圖像。
# top,bottom,left,right:相應方向上的邊寬度。
# borderType:定義要添加邊框的類型,它可以是以下的一種:
# CV2.BORDER_CONSTANT:添加的邊界框像素值為常數(需要額外再給定一個參數)。
# CV2.BORDER_REFLECT:添加的邊框像素將是邊界元素的鏡面反射,類似于gfedchalabcdefgh|hgfedcba。(交界處也復制了)
# CV2.BORDER_REFLECT_101 或 CV2.BORDER_DEFAULT;和上面類似,但是有一些細微的不同,類似于gfedcblabcdefghlgfedcba (交接處刪除了)
# CV2.BORDER_REPLICATE:使用最邊界的像素值代替,類似于aaaaaalabcdefghlhhhhhhh# CV2.BORDER_WRAP:上下左右邊依次替換,cdefghlabcdefghlabcdefgimport cv2ys = cv2.imread('yueshan.png')
# ys = cv2.resize(ys, dsize=None, fx=0.5, fy=0.5) # 圖片縮放
# ys = cv2.resize(ys, (640, 480))top, bottom, left, right = 50, 50, 50, 50constant = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_CONSTANT, value=(22, 25, 8))
reflect = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REFLECT101)
replicate = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_REPLICATE)
wrap = cv2.copyMakeBorder(ys, top, bottom, left, right, borderType=cv2.BORDER_WRAP)cv2.imshow('yuantu', ys)
cv2.waitKey(0)cv2.imshow('CONSTANT', constant)
cv2.waitKey(0)cv2.imshow('REFLECT', reflect)
cv2.waitKey(0)cv2.imshow('REFLECT_101', reflect101)
cv2.waitKey(0)cv2.imshow('REPLICATE', replicate)
cv2.waitKey(0)cv2.imshow('WRAP', wrap)
cv2.waitKey(0)
ys:
constant:
reflect:
reflect101:
replicate:
wrap:
(1.2)圖片的圖像運算
核心功能:
- ?基礎加減法:直接對像素值進行數學運算(如全局加10)
- ?區域疊加:通過切片操作實現特定區域的圖像相加
- ?安全加法:
cv2.add()
?自動處理像素溢出(超過255則置為255) - ?加權融合:
cv2.addWeighted()
?按比例混合兩張圖像并添加亮度偏移
示例代碼:
# 圖像加法運算
# 對于“+”號運算,當對圖像a、圖像b進行加法求和時,遵循以下規則:
# 當某位置像素相加得到的數值小于255時,該位置數值為兩圖像該位置像素相加之和;
# 當某位置像素相加得到的數值大于255時,該位置數值將截斷結果并將其減去256。
# 例如:相加后是260,實際是260-256=4
import cv2
a = cv2.imread('mimi.jpg')
b = cv2.imread('mimi1.jpg')
c = a + 10 # 圖像整體加10
cv2.imshow('yuantu', a)
cv2.imshow('a+10', c)
cv2.waitKey(0)# ROI 區域相加示例
c = a[50:450, 50:400] + b[50:450, 50:400]
cv2.imshow('a+b', c)
cv2.waitKey(0)# 對于 cv2.add 運算,當對圖像a、圖像b進行加法求和時,遵循以下規則:
# 當某位置像素相加得到的數值小于255時,該位置數值為兩圖像該位置像素相加之和;
# 當某位置像素相加得到的數值大于255時,該位置數值為255(飽和運算)。a = cv2.imread('mimi.jpg')
b = cv2.imread('mimi1.jpg')
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()# 圖像加權運算
# 在計算兩幅圖像的像素值之和時,將每幅圖像的權重考慮進來,公式為:
# dst = src1 × α + src2 × β + γa = cv2.imread('mimi.jpg')
b = cv2.imread('mimi1.jpg')
b = cv2.resize(b, dsize=(400, 400))
a = cv2.resize(a, dsize=(400, 400))c = cv2.addWeighted(a,0.5,b,0.5,10) # γ=10 為亮度偏移
cv2.imshow('addWeighted', c)
cv2.waitKey(0)
cv2.destroyAllWindows()
yuantu :
a+10:
a+b:
a add b:
addWeighted:
(1.3)圖片的閾值處理
核心功能:
1.讀入灰度圖
image = cv2.imread('mimi1.jpg', cv2.IMREAD_GRAYSCALE) # 讀入灰度圖
作用:加載一張只有亮度信息的灰度照片(像素值范圍0~255)
相當于:把彩色照片去掉顏色,只留下明暗層次
2.閾值處理類型對照表
所有方法共用同一組參數:threshold=175
,?maxval=255
(即:"以175為分界線,最高允許到255")
方法名稱 | 英文標識 | 行為規則 | 效果圖特征 |
---|---|---|---|
標準二值化 | cv2.THRESH_BINARY | ?≥175 → 純白(255) <175 → 純黑(0) | 黑白分明,像木刻版畫 |
反向二值化 | cv2.THRESH_BINARY_INV | ?≥175 → 純黑(0) <175 → 純白(255) | 陰陽顛倒,亮處變暗,暗處變亮 |
截斷處理 | cv2.THRESH_TRUNC | ?≥175 → 強制設為175 <175 → 保持原樣 | 過曝區域集體降亮度,畫面偏灰蒙蒙 |
低區歸零 | cv2.THRESH_TOZERO | ?≥175 → 保持原樣 <175 → 強制設為0(純黑) | 暗部全黑,亮部保留漸變 |
高區歸零 | cv2.THRESH_TOZERO_INV | ?<175 → 保持原樣 ≥175 → 強制設為0(純黑) | 亮部全黑,暗部保留漸變 |
示例代碼:
#閾值處理
import cv2# 讀取灰度圖
image = cv2.imread('mimi1.jpg', cv2.IMREAD_GRAYSCALE)# 閾值處理
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.destroyAllWindows()
gray:
binary:
binaryinv:
trunc:
tozero:
tozeroinv:
(1.4)圖片的圖像平滑處理
關鍵函數總結:
濾波方法 | 函數名 | 關鍵參數 | 特點 |
---|---|---|---|
均值濾波 | cv2.blur | (src, ksize) | 簡單平均,模糊均勻 |
方框濾波 | cv2.boxFilter | (src, ddepth, ksize, normalize) | 可控制是否歸一化 |
高斯濾波 | cv2.GaussianBlur | (src, ksize, sigmaX) | 保留邊緣,模糊更自然 |
中值濾波 | cv2.medianBlur | (src, ksize) | 去噪強,保留邊緣 |
示例代碼:
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):x = np.random.randint(1, h)y = np.random.randint(1, w)if np.random.randint(0, 2) == 0:result[x, y] = 0else:result[x, y] = 255return result# 讀取并顯示原圖
image = cv2.imread('zl.png')
cv2.imshow('yntu', image)
cv2.waitKey(0)# 添加噪聲并顯示
noise = add_peppersalt_noise(image)
cv2.imshow('noise', noise)
cv2.waitKey(0)
# 3x3核(輕度模糊)
blur_1 = cv2.blur(noise, (3, 3))
cv2.imshow('blur_1', blur_1)
cv2.waitKey(0)# 63x63核(重度模糊)
blur_2 = cv2.blur(noise, (63, 63))
cv2.imshow('blur_2', blur_2)
cv2.waitKey(0)# 歸一化(效果同均值濾波)
boxFilter_1 = cv2.boxFilter(noise, -1, (3, 3), normalize=True)
cv2.imshow('boxFilter_1', boxFilter_1)
cv2.waitKey(0)# 不歸一化(像素值可能溢出為255)
boxFilter_2 = cv2.boxFilter(noise, -1, (3, 3), normalize=False)
cv2.imshow('boxFilter_2', boxFilter_2)
cv2.waitKey(0)# 高斯濾波:3x3核,sigmaX=1
GaussianB = cv2.GaussianBlur(noise, (3, 3), sigmaX=1)
cv2.imshow('GaussianBlur', GaussianB)
cv2.waitKey(0)# 中值濾波:3x3核
medianB = cv2.medianBlur(noise, 3)
cv2.imshow('medianBlur', medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
yutu:
noise:
blur_1:
blur_2:
boxFilter_1:
boxFilter_2:
GaussianBlur:
medianBlur:
(二)實戰項目案例
項目內容:
核心步驟和功能:
1. 打開視頻流?
? ?cap = cv2.VideoCapture('test.avi')??
→ 把硬盤里的視頻文件變成一幀一幀的圖像流,供后續逐幀處理
2. 逐幀讀取??
?ret, frame = cap.read()??
→ 每次循環拿到一幀原始圖像(BGR 格式)
3. 加椒鹽噪聲??
?noisy = add_peppersalt_noise(frame, 10000)??
→ 在這幀上隨機撒 10000 個黑白點,模擬真實噪聲
4. 去噪處理
? ?denoised = cv2.medianBlur(noisy, 3)?
→ 用 3×3 中值濾波去掉椒鹽噪聲,同時盡量保留畫面細節
5.三窗口同步顯示?
?- cv2.imshow('Original Video', frame)?
- cv2.imshow('Noisy Video', noisy)??
- cv2.imshow('Denoised Video', denoised)??
→ 實時對比“原圖 / 有噪圖 / 去噪圖”
6. 按 q 退出?
? ?if cv2.waitKey(30) & 0xFF == ord('q'): break??
→ 用戶隨時按 q 鍵即可結束播放
7. 資源釋放?
? ?cap.release(); cv2.destroyAllWindows()
→ 關閉攝像頭或文件句柄,釋放內存,銷毀所有窗口
代碼實現和效果:
import cv2
import numpy as np# 1. 添加椒鹽噪聲函數(復用)
def add_peppersalt_noise(image, n=10000):result = image.copy()h, w = image.shape[:2]for i in range(n):x = np.random.randint(1, h)y = np.random.randint(1, w)if np.random.randint(0, 2) == 0:result[x, y] = 0else:result[x, y] = 255return result# 2. 打開視頻文件
cap = cv2.VideoCapture('test.avi')# 檢查視頻是否成功打開
if not cap.isOpened():print("無法打開視頻文件,請檢查路徑!")exit()# 3. 逐幀處理
while True:ret, frame = cap.read()if not ret:break# 添加噪聲noisy_frame = add_peppersalt_noise(frame, 10000)# 中值濾波去噪(保留邊緣,適合椒鹽噪聲)denoised_frame = cv2.medianBlur(noisy_frame, 3)# 顯示三個窗口cv2.imshow('Original Video', frame)cv2.imshow('Noisy Video', noisy_frame)cv2.imshow('Denoised Video', denoised_frame)# 按 'q' 鍵退出if cv2.waitKey(30) & 0xFF == ord('q'):break# 4. 釋放資源
cap.release()
cv2.destroyAllWindows()