opencv(6): 形态学操作(二值化、自适应阈值、开闭、对比度)

发布于:2025-02-26 ⋅ 阅读:(18) ⋅ 点赞:(0)

如何在图片中识别出一些物体的位置。具体是什么不是形态学的范畴。
处理方法基本是对二进制图像进行处理。
卷积核决定着图像处理后的效果。

图像二值化

将图像的每个像素变成两种值, 如 0, 255。

全局二值化:全局按照某个阈值二值化
局部二值化

threshold(img, thresh, maxVal,type)

import cv2

# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 进行简单阈值化
# 第一个参数是输入图像
# 第二个参数是用于分类像素值的阈值
# 第三个参数是当像素值高于阈值时要应用的新像素值
# 第四个参数是指定使用的阈值类型,如cv2.THRESH_BINARY、cv2.THRESH_BINARY_INV等
_, thresholded = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)

可以使用不同的阈值类型,根据应用的要求选择适当的类型。例如,cv2.THRESH_BINARY表示二进制阈值化,cv2.THRESH_BINARY_INV表示反二进制阈值化等。在这里插入图片描述
后面三种不是二值化。

ostu: 类间方差最大

自适应阈值

由于光照不均与以及阴影的存在,只有一个阈值会使得在阴影处的白色被二值化为黑色。
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])

  • src: 输入图像,应该是灰度图像。
  • maxValue: 分类像素值的最大值,通常为255。
  • adaptiveMethod: 指定阈值计算方法,可以是以下两者之一:
  • cv2.ADAPTIVE_THRESH_MEAN_C:使用邻域块的平均值作为阈值。
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:使用邻域块的加权平均值(高斯窗口)作为阈值。
  • thresholdType: 指定阈值类型,应该是以下两者之一:
    • cv2.THRESH_BINARY:二进制阈值。
    • cv2.THRESH_BINARY_INV:反二进制阈值。
  • blockSize: 用于计算阈值的邻域块大小,必须是奇数。
  • C: 从计算的平均值或加权平均值中减去的常数。
  • dst (可选): 输出图像,可以与输入图像相同。如果未提供,函数将创建一个新的图像。
# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 自适应阈值二值化
# 第一个参数是输入图像
# 第二个参数是用于分类像素值的最大值
# 第三个参数是指定使用的阈值类型,如cv2.ADAPTIVE_THRESH_MEAN_C或cv2.ADAPTIVE_THRESH_GAUSSIAN_C
# 第四个参数是指定阈值计算方法的区域大小,例如11表示计算每个像素周围的11x11区域
# 第五个参数是从计算的平均值或加权平均值中减去的常数
thresholded = cv2.adaptiveThreshold(
    image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2
)

cv2.adaptiveThreshold函数使用局部均值作为阈值计算方法,然后将每个像素的阈值与其周围11x11区域的均值进行比较。你还可以尝试使用cv2.ADAPTIVE_THRESH_GAUSSIAN_C作为阈值计算方法,它使用局部区域的加权平均值。

获取卷积核

cv2.getStructuringElement(shape, ksize[, anchor])
参数说明:

  • shape: 结构元素的形状,可以是 cv2.MORPH_RECT(矩形)、cv2.MORPH_ELLIPSE(椭圆)、cv2.MORPH_CROSS(十字形)等。
  • ksize: 结构元素的大小,通常是一个 (width, height) 的元组。
  • anchor(可选): 结构元素的锚点位置,默认为结构元素的中心。
import cv2
import numpy as np

# 创建一个 3x3 的矩形结构元素
kernel_rect = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
print("Rectangular Kernel:")
print(kernel_rect)

# 创建一个 3x3 的椭圆结构元素
kernel_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
print("\nElliptical Kernel:")
print(kernel_ellipse)

# 创建一个 3x3 的十字形结构元素
kernel_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
print("\nCross-shaped Kernel:")
print(kernel_cross)

腐蚀和膨胀

腐蚀
用结构元素扫描图像,当结构元素完全包含在目标区域内时,保留中心点。
效果:消除细小物体、分离粘连目标、收缩物体边界。

膨胀
用同一结构元素扫描腐蚀后的图像,当结构元素与目标区域有交集时,保留中心点。
效果:恢复被腐蚀物体的主要形状,但被完全消除的小物体无法恢复。

腐蚀 Erosion

将一个区域变小

卷积核都是全1 的,
在腐蚀操作中,结构元素(也称为内核)是一个小的图像,它定义了腐蚀的形状。在每一步腐蚀操作中,结构元素会在图像上滑动,并与图像的局部区域进行覆盖。在每个覆盖的位置,只有原图的像素全都包含在核中,该核中心点值才保留(个人理解?)。这个过程会导致图像中的边界逐渐变窄,因为图像中较亮的区域将被周围较暗的区域腐蚀。这会导致边界处的像素被腐蚀,对象会变小。

cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

  • src: 输入图像,通常是二进制图像。
  • kernel: 结构元素,用于定义腐蚀操作的形状。
  • dst (可选): 输出图像,可以与输入图像相同。如果未提供,函数将创建一个新的图像。
  • anchor (可选): 结构元素的锚点。默认值 (-1, -1) 表示锚点位于结构元素的中心。
  • iterations (可选): 腐蚀操作的迭代次数,默认为 1。
  • borderType (可选): 边界模式,表示当边界被腐蚀时如何处理。默认是 cv2.BORDER_CONSTANT。
  • borderValue (可选): 当 borderType 为 cv2.BORDER_CONSTANT 时的边界值,默认为 0。
# 读取图像
img = cv2.imread('input_image.png', cv2.IMREAD_GRAYSCALE)

# 创建结构元素,这里使用一个 3x3 的矩形结构元素
kernel = np.ones((3, 3), np.uint8)

# 进行腐蚀操作
result = cv2.erode(img, kernel, iterations=1)

膨胀

将一个区域变大

开闭运算

开运算和闭运算是形态学处理中的两个重要操作,通常用于图像处理中的去噪、分割等任务。

开运算是先腐蚀后膨胀的过程。腐蚀操作可以消除小的噪点或细小的结构,而膨胀则可以恢复保留下来物体的形状,但被腐蚀掉的区域不会恢复。因此,开运算适合去除图像中的小物体或者平滑物体的边界,同时保持主要结构不变。例如,如果有一张包含许多小点的图像,开运算可以有效去除这些小点,而较大的物体则不受影响。

开运算

先做腐蚀再做膨胀。
最后的动作是放大的,就是开运算。

闭运算

先做膨胀再做腐蚀。
最后的动作是缩小的,就是闭运算。
闭运算适合的场景:填充小孔、连接邻近物体、平滑边界、处理断裂区域。

dst = cv2.morphologyEx(
    src, 
    op, 
    kernel[, 
    dst[, 
    anchor[, 
    iterations[, 
    borderType[, 
    borderValue]]]]]
)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

操作流程:
膨胀:扩大亮区,填充孔洞
腐蚀:收缩回原始尺寸,保持主要形状

顶帽 & 黑帽

在这里插入图片描述

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 定义结构元素
kernel = np.ones((5, 5), np.uint8)

# 进行顶帽操作
tophat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, kernel)

# 进行黑帽操作
blackhat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, kernel)

# 显示原始图像、顶帽结果和黑帽结果
plt.figure(figsize=(15, 5))

plt.subplot(131)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')

plt.subplot(132)
plt.imshow(tophat, cmap='gray')
plt.title('Top Hat')
plt.axis('off')

plt.subplot(133)
plt.imshow(blackhat, cmap='gray')
plt.title('Black Hat')
plt.axis('off')

plt.show()

opencv 改变图片对比度

可以使用 cv2.convertScaleAbs 函数来改变图片的对比度。
可以按照一定的比例对图片的每个像素值进行缩放,同时还可以添加一个偏置,从而改变图片的对比度。