【计算机视觉】OpenCV 图像处理阈值处理 + 图像编辑 + 噪声滤波 + 图像运算
前言
在计算机视觉领域,OpenCV 是最经典、最常用的开源图像处理库,无论是基础的图像变换、噪声处理,还是进阶的目标检测、图像分割,都离不开 OpenCV 的核心操作。本次案例全覆盖图像阈值处理、图片打码 / 组合 / 缩放、椒盐噪声生成与平滑滤波、图像像素运算四大核心模块,搭配逐行代码解析 + 原理详解 + 效果说明,流程清晰、零基础可学,非常适合作为 OpenCV 图像处理的入门实战教程。
如果对计算机视觉有兴趣但是没有了解的读者,可以先观看博主的第一篇关于计算机视觉入门的文章。
【Python OpenCV 入门教程】图像读取、灰度转换、图片切分、视频逐帧处理
一、图像阈值处理
1.概念
图像阈值处理是图像分割的基础方法,核心逻辑为人为设定一个固定阈值,将图像中每个像素的灰度值与阈值对比,按照预设规则重新赋值,实现前景和背景的分离。
简单来说:把图像的像素分成两部分,要么是纯黑(0),要么是纯白(255),或保留部分像素,实现图像的简化、分割。
2.阈值处理类型
| 阈值类型常量 | 像素值 > 设定阈值 | 像素值 ≤ 设定阈值 |
|---|---|---|
| cv2.THRESH_BINARY | 赋值为 255(纯白) | 赋值为 0(纯黑) |
| cv2.THRESH_BINARY_INV | 赋值为 0(纯黑) | 赋值为 255(纯白) |
| cv2.THRESH_TRUNC | 赋值为设定阈值 | 保持原像素值 |
| cv2.THRESH_TOZERO | 保持原像素值 | 赋值为 0(纯黑) |
| cv2.THRESH_TOZERO_INV | 赋值为 0(纯黑) | 保持原像素值 |
"inv"代表对前一个处理类型的反转
3.完整代码
代码完整且可直接运行,有需要可自取
import cv2
image = cv2.imread(r'./carh5.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)
print(ret) #查看当前的阈值为多少
cv2.imshow('gray',image)
cv2.waitKey(0)
cv2.imshow('binary',binary)
cv2.waitKey(0)
cv2.imshow('binaryinv',binaryinv)
cv2.waitKey(0)
cv2.imshow('tozero',tozero)
cv2.waitKey(0)
cv2.imshow('tozeroinv',tozeroinv)
cv2.waitKey(0)
4.代码详解
在编写代码前,我们需要先安装两个核心工具包:
-
OpenCV-Python:OpenCV 的 Python 接口,用于实现所有图像处理操作;
-
NumPy:Python 科学计算库,用于生成随机数、处理图像像素数组(OpenCV 依赖 NumPy)。
pip install opencv-python numpy -i https://pypi.tuna.tsinghua.edu.cn/simple/
首先导入OpenCV库,然后读取本地图像:参数0表示以【灰度模式】读取图像(彩色图转灰度,阈值处理必须用灰度图)。
路径替换为你自己的图片路径,r表示原生字符串,避免路径转义报错。
如果不想使用相对路径,可将图片复制在py文件同一文件夹后,直接使用。
import cv2
image = cv2.imread(r'./carh5.png', 0)
调用cv2.threshold()执行5种阈值处理
函数参数:cv2.threshold(原图, 设定阈值, 最大值255, 阈值类型)
retval,dst=cv2.threshold(src, thresh,maxval,type)
-
src代表要进行阈值分割的图像,可以是多通道的,8位或32位浮点型数值
-
thresh代表要设定的阈值
-
maxval代表type参数位THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定的最大值
-
retval代表返回的阈值dst代表阈值分割结果图像,与原始图像具有相同的大小和类型type代表阈值分割的类型,
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)
打印返回的阈值(验证:ret的值就是我们手动设定的175)
print(ret) #查看当前的阈值为多少
显示图像:cv2.imshow(窗口名称, 图像变量)
窗口名称需要使用全英文,使用中文将显示乱码。
cv2.imshow('gray',image)
cv2.waitKey(0)
cv2.imshow('binary',binary)
cv2.waitKey(0)
cv2.imshow('binaryinv',binaryinv)
cv2.waitKey(0)
cv2.imshow('tozero',tozero)
cv2.waitKey(0)
cv2.imshow('tozeroinv',tozeroinv)
cv2.waitKey(0)
关闭所有OpenCV图像窗口
cv2.destroyAllWindows()
运行结果:
二、图像编辑操作(打码 + 组合 + 缩放)
1.概念
图片打码的原理为定位图像中需要打码的矩形区域,用随机生成的像素值替换原区域的所有像素,让区域内容无法识别,实现马赛克效果。
彩色图像是三维数组:(高度,宽度,3 通道);
用np.random.randint(0,256)生成 0-255 的随机数,替换指定区域像素。
2.完整代码
代码完整且可直接运行,有需要可自取
import cv2
import numpy as np
a = cv2.imread(r'./110614.png')
a[10:110, 200:300, :] = np.random.randint(0, 256, (100, 100, 3))
cv2.imshow('dama',a)
cv2.waitKey(0)
cv2.destroyAllWindows()
a = cv2.imread(r'./110614.png')
b = cv2.imread(r'./200257.png')
b[100:250,100:250] = a[50:200,100:250]#矩阵大小一致
cv2.imshow('b',b)
cv2.imshow('a',a)
cv2.waitKey(0)
cv2.destroyAllWindows()
a = cv2.imread(r'./110614.png')
a_new = cv2.resize(a,(600,200))
#a_new = cv2.resize(a,None,fx=1.5,fy=0.5)
cv2.imshow('a',a)
cv2.imshow('a_new',a_new)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.代码详解
1.图片打码
导入必备库,读取彩色图像
import cv2
import numpy as np
a = cv2.imread(r'./110614.png')
选择指定图片的指定区域,替换成随机生成的像素,
10:110 → 高度方向10到110像素,200:300 → 宽度方向200到300像素。
np.random.randint:生成和打码区域尺寸完全一致的随机数组,尺寸不匹配会报错。
a[10:110, 200:300, :] = np.random.randint(0, 256, (100, 100, 3))
显示图像,关闭所有OpenCV图像窗口。
cv2.imshow('dama',a)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:

2.图片区域组合(像素替换拼接)
首先读取两张彩色图片
a = cv2.imread(r'./110614.png')
b = cv2.imread(r'./200257.png')
将a图像的区域,替换到b图像的对应位置
规则:左边区域尺寸 = 右边区域尺寸
矩阵的大小要一致
b[100:250, 100:250] = a[50:200, 100:250]
显示两张图像对比效果
cv2.imshow('b',b)
cv2.imshow('a',a)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:

3.图片尺寸缩放(自由调整大小)
首先读取一张彩色图片
a = cv2.imread(r'./110614.png')
参数可随意更改,查看效果
两种方法:
- 固定尺寸缩放: 参数:(宽度, 高度)
- 比例缩放: None=不指定尺寸,fx=宽倍数,fy=高倍数
推荐比例缩放,不会让图片变形
a_new = cv2.resize(a,(600,200))
#a_new = cv2.resize(a,None,fx=1.5,fy=0.5)
显示两张图像对比效果
cv2.imshow('a',a)
cv2.imshow('a_new',a_new)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:
三、椒盐噪声生成 + 4 种图像平滑滤波
1.概念
椒盐噪声是图像中最常见的噪声类型,表现为随机分布的纯黑像素(胡椒噪声)和纯白像素(盐噪声),看起来像撒了盐和胡椒,因此得名。
生成原理为随机选择图像中的像素点,赋值为 0(黑)或 255(白)。
图像滤波的作用是去除图像噪声,同时保留图像细节。
2.图像平滑滤波(降噪)类型
- 均值滤波:计算区域内像素平均值,简单但会模糊图像;
- 方框滤波:均值滤波的变体,可选择是否归一化;
- 高斯滤波:按高斯权重计算,平滑效果自然,抑制高斯噪声;
- 中值滤波:取区域像素中位数,对椒盐噪声降噪效果最好。
3.完整代码
代码完整且可直接运行,有需要可自取
import cv2
import numpy as np
# 产生噪点图
image = cv2.imread(r'./carh5.png')
def add_peppersalt_noise(image,n = 10000):
result = image.copy()
h,w = image.shape[:2]
for i in range(n):
x = np.random.randint(0,h)
y = np.random.randint(0,w)
if np.random.randint(0,2 ) == 0:
result [x,y] = 0
else:
result[x,y] = 255
return result
cv2.imshow('yntu',image)
cv2.waitKey(0)
noise = add_peppersalt_noise(image)
cv2.imshow('noise',noise)
cv2.waitKey(0)
# 均值滤波
blur_1 = cv2.blur(noise,(3,3))
cv2.imshow('blur_1',blur_1)
cv2.waitKey(0)
blur_2 = cv2.blur(noise,(20,20))
cv2.imshow('blur_2',blur_2)
cv2.waitKey(0)
# 方框滤波
boxFilter_1 = cv2.boxFilter(noise,-1,(3,3),normalize=True)
cv2.imshow('box_filtwer_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)
# 高斯滤波
Gaussian = cv2.GaussianBlur(noise,(3,3),1)
cv2.imshow('gauss',Gaussian)
cv2.waitKey(0)
# 中值滤波
median = cv2.medianBlur(noise,3)
cv2.imshow('median',median)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.代码详解
1.生成椒盐噪声图像
导入必备库,读取灰度图像
import cv2
import numpy as np
image = cv2.imread(r'./carh5.png', 0)
定义函数:添加椒盐噪声
image=原图,n=噪声点数量(默认10000个),同时复制原图,不修改原图像,获取图像高度h、宽度w
def add_peppersalt_noise(image,n = 10000):
result = image.copy()
h,w = image.shape[:2]
循环生成n个噪声点,(x,y)为随机生成噪声的坐标。
if判断语句的含义是50%概率生成黑噪声,50%概率生成白噪声
for i in range(n):
x = np.random.randint(0,h)
y = np.random.randint(0,w)
if np.random.randint(0,2 ) == 0:
result [x,y] = 0
else:
result[x,y] = 255
return result
显示两张图像对比效果
cv2.imshow('yntu',image)
cv2.waitKey(0)
noise = add_peppersalt_noise(image)
cv2.imshow('noise',noise)
cv2.waitKey(0)
运行结果:

2.4 种滤波降噪代码
1.均值滤波
cv2.blur:核越大,模糊越严重
计算区域内像素平均值,简单但会模糊图像;
blur_1就是在3x3的区域内进行轻度滤波
blur_2就是在20x20的区域内进行重度滤波
# 均值滤波
blur_1 = cv2.blur(noise,(3,3))
cv2.imshow('blur_1',blur_1)
cv2.waitKey(0)
blur_2 = cv2.blur(noise,(20,20))
cv2.imshow('blur_2',blur_2)
cv2.waitKey(0)
运行结果:

2.方框滤波
方框滤波:均值滤波的变体,可选择是否归一化;
cv2.boxFilter(图, 深度:-1, 核大小, normalize=True/False)
normalize=True=归一化(效果同均值滤波),False=不归一化(像素溢出,变亮)
# 方框滤波
boxFilter_1 = cv2.boxFilter(noise,-1,(3,3),normalize=True)
cv2.imshow('box_filtwer_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.高斯滤波
高斯滤波:cv2.GaussianBlur(图, 核大小, 标准差)
核大小不变的情况下,效果和均值滤波差距不大
# 高斯滤波
Gaussian = cv2.GaussianBlur(noise,(3,3),1)
cv2.imshow('gauss',Gaussian)
cv2.waitKey(0)
运行结果:

4.均值滤波
中值滤波:取区域像素中位数,对椒盐噪声降噪效果最好。
中值滤波:cv2.medianBlur(图, 核大小)
核的大小决定取中值的范围
# 中值滤波
median = cv2.medianBlur(noise,3)
cv2.imshow('median',median)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:

四、图像像素运算(加法 / 加权融合)
1.概念
在图像中需要运算的矩形区域,用另外一张鱼片的像素值替换原区域的所有像素,让区域内容透明融合,比如水印、叠加效果。
对于+号运算,当对图像a,图像b进行加法求和时,遵循以下规则:
- 当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和
- 当某位置像素相加得到的数值大于255时,该位置数值将截断结果并将其减去 256 例如:相加后是260,实际是260-256=4
2.完整代码
代码完整且可直接运行,有需要可自取
import cv2
import numpy as np
a = cv2.imread(r'./110614.png')
b = cv2.imread(r'./200257.png')
c = b+100
cv2.imshow('yuan',b)
cv2.imshow('b+10',c)
cv2.waitKey(0)
c = a[50:250,50:400]+b[50:250,50:400]
cv2.imshow('a+b',c)
cv2.imshow('a',a)
cv2.waitKey(0)
# cv2.destroyAllWindows()
a = cv2.resize(a,[400,400])
b = cv2.resize(b,[400,400])
c = cv2.add(a,b)
cv2.imshow('a add b',c)
cv2.waitKey(0)
cv2.destroyAllWindows()
c = cv2.addWeighted(a,0.2,b,0.8,10)
cv2.imshow('weight',c)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.代码详解
1.加法运算
导入必备库,读取彩色图像
import cv2
import numpy as np
a = cv2.imread(r'./110614.png')
b = cv2.imread(r'./200257.png')
图像整体加100,超过255会变色
a = cv2.imread(r'./110614.png')
b = cv2.imread(r'./200257.png')
c = b+100
cv2.imshow('yuan',b)
cv2.imshow('b+10',c)
cv2.waitKey(0)
运行结果:

2.OpenCV加法(饱和处理,正常)
先缩放为相同尺寸(必须一致才能相加)
c = a[50:250,50:400]+b[50:250,50:400]
cv2.imshow('a+b',c)
cv2.imshow('a',a)
cv2.waitKey(0)
运行结果:

3.图像融合
对于cv2.add()运算,当对图像a,图像b进行加法求和时,遵循以下规则:
- 当某位置像素相加得到的数值小于255时,该位置数值为两图像该位置像素相加之和
- 当某位置像素相加得到的数值大于255时,该位置数值为255
a = cv2.resize(a,[400,400])
b = cv2.resize(b,[400,400])
c = cv2.add(a,b)
cv2.imshow('a add b',c)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:
4.图像加权运算
就是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来
c = cv2.addWeighted(a,0.2,b,0.8,10)
cv2.imshow('weight',c)
cv2.waitKey(0)
cv2.destroyAllWindows()
将a图的权重设置为0.2,图b的权重值设置为0.8.
运行结果:
总结
本篇文章覆盖了 OpenCV最核心、最基础的 4 大模块,所有代码都经过实测,零基础也能轻松运行。这些操作是学习计算机视觉的基石,熟练掌握后,才能进一步学习边缘检测、特征提取、目标检测等进阶内容。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)