一,边界填充
cv2.copyMakeBorder()是OpenCV库中的一个函数,用于给图像添加额外的边界(padding)。
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: 使用最边界的像素值代替,类似于aaaaaaa|abcdefgh|hhhhhhh
cv2.BORDER_WRAP: 上下左右边依次替换,cdefgh|abcdefgh|abcdefg
import cv2
ys = cv2.imread('aigc.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,50
constant = cv2.copyMakeBorder(ys,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT,value=(229,25,80))
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)
可以观察到图像边缘变化
二,图像的加法运算
1. +号运算
对图像a、图像b进行加法求和时,遵循以下规则:
---当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和
---当某位置像素相加得到的数值大于255时,该位置数值将截断结果并将其减去 256 例如:相加后是260,实际是260-256= 4
# a = cv2.imread('aigc.png')
# b = cv2.imread('aigc1.jpg')
# c = a + 10 # 图片...
# cv2.imshow('yuan', a)
# cv2.imshow('a+10', c)
# cv2.waitKey(0)
# c=a+b
# cv2.imshow('a+b', c)
# cv2.waitKey(0)
可以观察图像变化
2.cv2.add()运算
当对图像a、图像b进行加法求和时,遵循以下规则:
--当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和
--当某位置像素相加得到的数值大于255时,该位置数值为255
a = cv2.imread('aigc.png')
b = cv2.imread('aigc1.jpg')
b = cv2.resize(b, (400, 400))
a = cv2.resize(a, (400, 400))
c = cv2.add(a, b) # 也可以使用使用
cv2.imshow('a add b', c)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以观察图像变化,大部分区域是白色
3.图像加权运算
是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来,可以用公式表示为dst=src1×α+src2×β+γ
# a = cv2.imread('aigc.png')
# b = cv2.imread('aigc1.jpg')
# b = cv2.resize(b, (400, 400))
# a = cv2.resize(a, (400, 400))
# #
# c = cv2.addWeighted(a, alpha=0.2, beta=0.8, gamma=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 cv2
image = cv2.imread('longpic.png',0) # 灰度图
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)
可以从左到右依次观察到图像的变化
四,图像平滑处理
图像平滑(smoothing)也称为“模糊处理”(bluring)
通过消除图像中的噪声或细节来使图像看起来更为模糊,从而实现平滑效果
可以用来压制、弱化或消除图像中的细节、突变和噪声。
下面是常用的一些滤波器
均值滤波(邻域平均滤波)-> blur函数
方框滤波-> boxFilter函数
高斯滤波->GaussianBlur函数
中值滤波->medianBlur函数
dst=cv2.blur(src,ksize,anchor,borderType)
dst是返回值
src是需要处理的图像
kszie是滤波核(卷积核)的大小
anchor是锚点,默认值是(-1,-1)一般无需更改
borderType是边界样式,一般无需更改
一般情况下,使用dst=cv2.blur(src,ksize)即可
先为图像添加噪声
import cv2
import numpy as np
def add_peppersalt_noise(image, n=5000):
result = image.copy()
h, w = image.shape[:2] # 获取图片的高和宽
for i in range(n): # 生成n个椒盐噪声
x = np.random.randint(1, h)
y = np.random.randint(1, w)
if np.random.randint(0, 2) == 0:
result[x, y] = 0
else:
result[x, y] = 255
return result
image = cv2.imread('longpic.png')
noise = add_peppersalt_noise(image)
cv2.imshow('yantu', image)
cv2.imshow('noise', noise)
cv2.waitKey(0)
可以观察到原图与添加过噪声的图的变化
1,均值滤波
均值滤波是取像素邻域(如 \(3\times3\) 窗口)内所有像素值的平均值,替换中心像素值,以此平滑图像、削弱噪声,但会让图像变模糊。 用数值示例(\(3\times3\) 邻域)更直观: 原始邻域像素值: | 10 | 20 | 15 | | 10 | 20 | 15 |
| 25 | 30 | 22 | ---> | 25 | 20 | 22 |
| 12 | 18 | 25 | | 12 | 18 | 25 |
均值滤波后中心像素值:(10 + 20 + 15 + 25 + 30 + 22 + 12 + 18 + 25)=20,邻域整体数值更平均,噪声被削弱,同时图像细节也变模糊。
blur_1 = cv2.blur(noise, (3, 3)) # 卷积核为3,3 效果一般,清晰度一般
cv2.imshow('blur_1', blur_1)
cv2.waitKey(0)
blur_2 = cv2.blur(noise, (63, 63))
cv2.imshow('blur_2', blur_2)
cv2.waitKey(0)
从右到左可以观察到图像的变化
2,方框滤波
用一个固定大小的 “方框”(如 3x3、5x5)在图像上滑动,方框内所有像素的平均值(或总和)作为中心像素的新值。
- 若 “归一化”(默认):新值 = 方框内像素总和 / 方框像素数量(即均值滤波);
- 若 “不归一化”:新值 = 方框内像素总和(可能导致像素值溢出,需谨慎使用)。
图像示例:
假设 3x3 方框覆盖的像素值如下(中心像素为 5):
1 2 3
4 5 6
7 8 9
归一化方框滤波后,中心像素新值 =(1+2+3+4+5+6+7+8+9)/9 = 5。
直观效果:方框内像素 “平均化”,模糊效果均匀,但可能模糊边缘细节。
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, (3, 3), normalize=True) # 2、方框滤波
cv2.imshow('boxFilter_1', boxFilter_1)
cv2.waitKey(0)
boxFilter_2 = cv2.boxFilter(noise, -1, (3, 3), normalize=False)
cv2.imshow('boxFilter_2', boxFilter_2)
cv2.waitKey(0)
3,高斯滤波
原理:
用 “高斯核”(权重符合高斯分布的方框)滑动,方框内像素的加权平均值作为中心像素的新值。
- 高斯核的权重特点:中心像素权重最大,向四周(距离中心越远)权重逐渐减小(符合 “近大远小” 的高斯分布);
- 本质是 “加权平均”,比方框滤波更注重保留中心附近的像素信息。
图像示例:
以简化的 3x3 高斯核(权重总和为 16)为例,权重分布如下:
1 2 1
2 4 2
1 2 1
覆盖的像素值仍为:
1 2 3
4 5 6
7 8 9
中心像素新值 =(1×1 + 2×2 + 3×1 + 4×2 + 5×4 + 6×2 + 7×1 + 8×2 + 9×1)/16 = 5。
直观效果:平滑噪声的同时,比方框滤波更能保留图像边缘(因中心权重高),是最常用的平滑方法之一。
cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, dst]]])高斯滤波
参数说明:
src:输入图像,通常是一个NumPy数组。
ksize:滤波器的大小,它是一个元组,表示在水平和垂直方向上的像素数量。例如,(5, 5)表示一个5x5的滤波器。
sigmaX和sigmaY:分别表示在X轴和Y轴方向上的标准差。这些值与滤波器大小相同。默认情况下,它们都等于0,这意味着没有高斯模糊。
dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果。
4.中值滤波
原理:
用固定大小的方框滑动,方框内所有像素值排序后,取 “中值” 作为中心像素的新值(而非平均值)。
- 核心:对极端值(如椒盐噪声中的亮 / 暗点)不敏感,适合去除脉冲噪声。
图像示例:
3x3 方框内的像素值(含椒盐噪声,255 为亮点,0 为暗点):
1 3 255
7 5 11
0 15 17
排序后:[0, 1, 3, 7, 5, 11, 15, 17, 255] → 中值为 5。
中心像素新值 = 5(极端值 255 和 0 被过滤)。
直观效果:能有效去除椒盐噪声,同时比前两种滤波更能保留边缘的锐利度。
# cv2.medianBlur(src, ksize[, dst])
参数说明:
src:输入图像。
ksize:滤波器的大小,它是一个整数,表示在水平和垂直方向上的像素数量。例如,5表示一个5x5的滤波器。
dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果。
medianB = cv2.medianBlur(noise, 3) # 4、中值滤波
cv2.imshow('medianBlur', medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们观察到,中值滤波的效果最好,因为我们的噪声点不是为1就是为255,在排序过程中很容易把0或255排到两边,过滤掉。