计算机视觉第一课opencv(二)保姆级教
目录
简介
一、边界填充
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()
总结:
不同的平滑处理方法各有侧重,选择时需根据图像噪声类型、对图像细节保留的要求等因素综合考虑。例如,处理椒盐噪声优先用中值滤波,需要保留边缘时可选用双边滤波,而处理高斯噪声时高斯滤波是较好的选择。