从零开始学习:深度学习(基础入门版)(第2天)
(一)在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()