传统CV算法——图像基本操作与形态学操作
环境配置地址
图像显示
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
img=cv2.imread('cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img_gray.shape
cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
转hsv图像
颜色表示为三个组成部分:色调(Hue)、饱和度(Saturation)和亮度(Value)。常用于图像处理中,因为它允许调整颜色的感知特性,如色彩和亮度,这些在RGB颜色模型中不那么直观。
HSV模型特别适用于任务如图像分割和对象追踪,因为它可以更好地处理光照变化的影响。
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.imshow("hsv", hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像阈值
ret, dst = cv2.threshold(src, thresh, maxval, type)
-
src: 输入图,只能输入单通道图像,通常来说为灰度图
-
dst: 输出图
-
thresh: 阈值
-
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
-
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
-
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
-
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
-
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
-
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
-
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
滤波操作
# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))
简单滤波
blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
局部平均滤波
cv2.boxFilter
用于对图像进行框滤波处理,也就是局部平均滤波。函数会计算图像中每个像素的邻域像素的平均值,并用这个平均值替换中心像素。这种滤波方法可以用于去噪和图像平滑处理。
这里是使用 cv2.boxFilter
的基本语法:
dst = cv2.boxFilter(src, ddepth, ksize, anchor=(-1, -1), normalize=True, borderType=cv2.BORDER_DEFAULT)
src
: 输入图像。ddepth
: 输出图像的所需深度(数据类型),如果为-1
,则输出和输入有相同的深度。ksize
: 核的大小,表示滤波器窗口的宽度和高度。anchor
: 核的锚点位置,默认值为核中心。normalize
: 如果设置为True
,则函数计算像素的平均值;如果为False
,则进行求和(可能会导致数值溢出)。borderType
: 边界像素的插值方式。
这种滤波器对于简单的图像平滑效果较好,但可能不适用于需要保留边缘信息的应用场景。
box = cv2.boxFilter(img,-1,(3,3), normalize=True)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 方框滤波
# 基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=False)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波
cv2.medianBlur
OpenCV 库中用于实现中值滤波的函数。中值滤波是一种非线性滤波技术,通常用于去除图像中的椒盐噪声(即随机出现的黑点和白点噪声),同时保持图像边缘的清晰度。
中值滤波的原理是用图像中每个像素点的邻域像素的中值来替换该像素点的值。这种方法特别有效于去除噪声点,因为噪声点通常会在其像素值上与周围像素差异很大。
下面是使用 cv2.medianBlur
的基本语法:
dst = cv2.medianBlur(src, ksize)
src
: 输入图像。ksize
: 滤波器的大小,它是一个大于 1 的奇数,表示滤波器窗口的宽度和高度。在这个例子中,ksize
是 5,所以滤波窗口为 5x5。
中值滤波特别适用于去除图像的椒盐噪声,而不会使图像边缘过分模糊,因此它在图像预处理中非常有用。
# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5) # 中值滤波
cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()
高斯滤波
cv2.GaussianBlur
是 OpenCV 库中用于实现高斯模糊的函数。高斯模糊是一种图像滤波技术,用于减少图像的细节和噪声,通过这种方式可以在图像处理中实现去噪和平滑效果。
高斯模糊的工作原理是每个像素点的值被替换为其周围像素的加权平均值,权重由高斯函数决定,高斯函数以当前像素为中心,且其形状由标准差σ控制。
以下是使用 cv2.GaussianBlur
函数的基本语法:
dst = cv2.GaussianBlur(src, ksize, sigmaX)
src
: 输入图像。ksize
: 滤波器的大小,必须是正数和奇数。在这个例子中,ksize
是 (5, 5),表示滤波器窗口的宽度为 5,高度也为 5。sigmaX
: 高斯核的标准差在 X 方向上。在此例中为 1。如果sigmaX
为 0,它将从ksize
计算得出。
高斯模糊被广泛用于图像处理中的边缘平滑和噪声减少,其效果较为自然。
# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)
cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
均值,中值,高斯滤波对比
# 展示所有的
res = np.hstack((blur,aussian,median))
#print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
形态学操作
原图
腐蚀操操作
cv2.erode
是 OpenCV 库中用于执行图像的腐蚀操作的函数。腐蚀是一种图像处理技术,通常用于减小图像中的前景对象。它主要用于去除小的白色噪点、分离两个连接在一起的对象等。
在腐蚀操作中,将一个结构元素(kernel)滑动过原始图像(src),只有当结构元素内的所有像素值都为 1 时,原始图像的中心像素才会被保留,否则该像素将被抹去(设为 0)。这样,只有当前景对象的区域足够大,才能在腐蚀操作后仍然存在。
cv2.erode
的基本语法如下:
dst = cv2.erode(src, kernel, iterations=1)
src
: 输入图像。kernel
: 用于腐蚀操作的结构元素。可以使用cv2.getStructuringElement
函数定义不同形状的结构元素。iterations
: 腐蚀操作的次数。在此例中,腐蚀操作执行一次。
此函数通常用于图像预处理,如去除细小噪声和分隔接触物体等,使图像的结构特征更加明显。
img = cv2.imread('images/dige.png')
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
不同腐蚀次数下情况对比
kernel = np.ones((30,30),np.uint8)
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
膨胀操作
cv2.dilate
是 OpenCV 库中用于执行图像的膨胀操作的函数。膨胀是一种图像处理技术,通常用于增加图像中前景对象的大小。它主要用于填补前景物体中的小洞、连接邻近的对象等。
在膨胀操作中,将一个结构元素(kernel)滑动过原始图像(src),只要结构元素与原始图像的任何一个像素值相交(即至少一个为 1),原始图像的中心像素就会被设为 1。这样,前景对象在膨胀后通常会变得更大。
cv2.dilate
的基本语法如下:
dst = cv2.dilate(src, kernel, iterations=1)
src
: 输入图像。kernel
: 用于膨胀操作的结构元素。可以使用cv2.getStructuringElement
函数定义不同形状的结构元素。iterations
: 膨胀操作的次数。在此例中,膨胀操作执行一次。
此函数通常与腐蚀操作结合使用,在去除噪声的同时保持物体的尺寸和形状,或用于填充物体内部的小孔和缝隙。
img = cv2.imread('images/dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8)
dige_erosion = cv2.erode(img,kernel,iterations = 1)
# 腐蚀结果
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 膨胀结果
kernel = np.ones((3,3),np.uint8)
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)
cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()
膨胀前
膨胀后
不同膨胀结果显示
pie = cv2.imread('images/pie.png')
kernel = np.ones((30,30),np.uint8)
dilate_1 = cv2.dilate(pie,kernel,iterations = 1)
dilate_2 = cv2.dilate(pie,kernel,iterations = 2)
dilate_3 = cv2.dilate(pie,kernel,iterations = 3)
res = np.hstack((dilate_1,dilate_2,dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
开运算
开运算(Opening)和闭运算(Closing)是图像处理中常用的形态学操作,用于去除小对象、平滑边界,同时保持图像的基本形状不变。这两种操作都使用 cv2.morphologyEx
函数实现,但具体的行为取决于所使用的特定操作类型。
开运算(Opening)
开运算首先进行腐蚀操作,然后进行膨胀操作。这个顺序很重要,因为首先通过腐蚀去掉小的噪声点,然后通过膨胀恢复腐蚀的对象的大小。它常用于去除小的白噪声(前景噪声)。
在 OpenCV 中,开运算可以通过下面的代码实现:
opened_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
img
: 原始图像。cv2.MORPH_OPEN
: 指定使用开运算。kernel
: 结构元素,定义了操作的性质。
闭运算(Closing)
闭运算先进行膨胀操作,后进行腐蚀操作。这种操作顺序用于填充前景物体内部的小洞,或小黑点,同时可以连接靠近的对象。闭运算常用于关闭前景物体中的小孔和缝隙。
在 OpenCV 中,闭运算可以通过下面的代码实现:
closed_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
img
: 原始图像。cv2.MORPH_CLOSE
: 指定使用闭运算。kernel
: 结构元素,定义了操作的性质。
这两种操作非常适用于图像预处理,如在进行目标检测和轮廓分析之前,用于改善图像的质量。
# 开:先腐蚀,再膨胀
img = cv2.imread('images/dige.png')
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
闭运算
梯度运算
cv2.morphologyEx
函数在OpenCV中用于执行形态学操作,其中cv2.MORPH_GRADIENT
是指定的操作类型之一,代表形态学梯度。
形态学梯度的原理基于图像膨胀和腐蚀的概念。简单来说:
- 膨胀操作会扩大图像中的亮区域,通过用结构元素探测并取代中心像素的最大值来实现。
- 腐蚀操作会缩小图像中的亮区域,通过用结构元素探测并取代中心像素的最小值来实现。
梯度操作则计算膨胀图像和腐蚀图像之间的差异。这种差异突出了图像中的高亮边缘,这是因为边缘附近的像素在膨胀时会增加其亮度,而在腐蚀时亮度会减少。因此,梯度操作能有效地捕捉到物体的边界和纹理变化,这对于图像分析和处理中的边缘检测等应用非常有用。
在代码中,kernel
参数是一个结构元素,定义了膨胀和腐蚀操作的形状和大小,影响最终梯度的计算结果。
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
礼帽操作
顶帽操作,也称为“白帽”操作,是一种形态学变换,主要用于突出比邻近区域亮的小对象或细节。它通过原始图像与开运算结果的差值来实现:
- 开运算:先执行腐蚀操作,然后进行膨胀。这个过程平滑了图像的外部边界,断开了狭窄的连接并消除了细小的突出部分。
- 顶帽操作:计算原始图像与开运算结果的差值。这个差值揭示了那些在开运算中被移除的亮部分,因此顶帽操作能够突出显示图像中比周围区域亮的小物体或细节。
cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
中的kernel
参数定义了进行腐蚀和膨胀时使用的结构元素的形状和大小,从而影响操作的具体效果。顶帽操作常用于增强图像中的亮区域或用于提取具有特定形状特征的物体。
#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
黑帽
黑帽操作,也称为“黑帽”操作,是一种形态学变换,主要用于突出比邻近区域暗的小对象或细节。它通过闭运算结果与原始图像的差值来实现:
- 闭运算:先进行膨胀操作,然后执行腐蚀。这个过程有助于填充前景物体中的小洞,连接邻近的对象,并保持前景物体的总体形状。
- 黑帽操作:计算闭运算的结果与原始图像的差值。这个差值揭示了那些在闭运算中新增的暗部分,因此黑帽操作能够突出显示图像中比周围区域暗的小物体或细节。
cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
中的kernel
参数定义了进行膨胀和腐蚀时使用的结构元素的形状和大小,从而影响操作的具体效果。黑帽操作常用于分析图像中的暗区域或检测亮背景中的暗物体。
#黑帽
img = cv2.imread('dige.png')
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()