opencv基础篇 ——(六)图像形态学

32 篇文章 1 订阅

概念


        图像形态学是一种数学理论和技术,用于分析和处理图像中的形状和结构。它主要基于数学形态学的概念,通过操作图像中的形状和结构元素(也称为内核或模板),来实现图像的分析、增强、去噪和特征提取等目的。图像形态学通常用于数字图像处理、计算机视觉和模式识别等领域。以下是图像形态学的一些关键概念和常见操作:

关键概念:

  • 结构元素(Structuring Element): 结构元素是一种小的图像模板,用于定义形态学操作的特征和行为。它通常是一个小的二值图像,用于描述待处理图像中的局部结构。常见的结构元素包括方形、圆形、十字形等。
  • 腐蚀(Erosion): 腐蚀是一种形态学操作,它通过结构元素对图像进行局部最小值滤波,使图像中边界部分逐渐缩小。腐蚀操作可以用于去除图像中的噪声、分割物体等。
  • 膨胀(Dilation): 膨胀是一种形态学操作,它通过结构元素对图像进行局部最大值滤波,使图像中的边界部分逐渐扩张。膨胀操作可以用于填充图像中的空洞、连接物体等。
  • 开运算(Opening): 开运算是先进行腐蚀操作,再进行膨胀操作的组合操作。它可以用于去除小的噪声,并保留图像中的主要结构。
  • 闭运算(Closing): 闭运算是先进行膨胀操作,再进行腐蚀操作的组合操作。它可以用于填充小的空洞,并连接图像中的断裂结构。
  • 形态学梯度(Morphological Gradient): 形态学梯度是膨胀和腐蚀之间的差异,它可以用于检测图像中的边缘和轮廓。

常见操作:

  • 形态学滤波: 使用腐蚀、膨胀、开运算、闭运算等形态学操作来进行图像滤波和去噪。
  • 图像分割: 使用腐蚀、膨胀等操作来分割图像中的对象。
  • 图像特征提取: 使用形态学操作来提取图像中的特征,如边缘、轮廓等。
  • 图像形态学在图像处理中有着广泛的应用,能够有效地处理不同形状、大小和复杂度的图像,并提取出有用的信息和特征。

图像腐蚀erode 

        cv::erode 是 OpenCV 库中用于执行图像腐蚀(erosion)这一形态学操作的函数。图像腐蚀是一种基本的图像处理技术,常用于消除噪声、细化边缘、分离紧密相连的物体等。

函数声明:

void cv::erode(
    InputArray src,
    OutputArray dst,
    InputArray kernel,
    Point anchor = Point(-1, -1),
    int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue());

参数说明:

  • InputArray src: 输入图像,需为单通道 8-bit、16-bit 或 32-bit 浮点型图像,或者是三通道 8-bit 图像。

  • OutputArray dst: 输出图像,与输入图像 src 具有相同的尺寸和类型。

  • InputArray kernel: 腐蚀所使用的结构元素(structuring element)。通常为方形、圆形或其他形状的二值矩阵,定义了腐蚀操作中影响像素邻域的形状。结构元素决定了哪些相邻像素将参与到腐蚀过程中,共同决定中心像素是否被保留。推荐使用 cv::getStructuringElement 函数来创建结构元素,它可以生成矩形(cv::MORPH_RECT)、椭圆(cv::MORPH_ELLIPSE)或十字形(cv::MORPH_CROSS)等常见形状。

  • Point anchor: 结构元素的锚点(anchor point),即结构元素相对于其作用像素的基准点。默认值为 Point(-1, -1),表示结构元素的中心作为锚点。根据需要,可以指定其他位置作为锚点。

  • int iterations: 腐蚀操作的迭代次数。默认值为 1,即执行一次腐蚀。若设置为大于 1 的整数,将连续多次应用腐蚀操作,每次迭代的结果作为下一次迭代的输入。

  • int borderType: 边界填充类型,定义了如何处理图像边缘以外的像素。可选值包括:

    • BORDER_CONSTANT: 使用指定的 borderValue 填充边缘。
    • BORDER_REPLICATE: 复制边缘像素值。
    • BORDER_REFLECT: 反射边缘像素。
    • BORDER_WRAP: 包裹边缘像素。
    • 其他边界模式,具体参见 OpenCV 文档。
  • const Scalar& borderValue: 当 borderType 为 BORDER_CONSTANT 时,用于填充图像边缘的值。默认情况下,使用 morphologyDefaultBorderValue() 提供的值,通常为黑色(对于 8-bit 图像,为 0)。

功能概述:

  • 消除噪声:在二值图像中,孤立的像素或小面积的像素团块往往被视为噪声。腐蚀操作可以有效地去除这些孤立像素,因为它们无法找到足够数量的相邻像素与其一起满足腐蚀条件,从而在腐蚀过程中被置为背景色。

  • 细化边缘:对于物体边缘的粗略轮廓,腐蚀操作能够使其变薄,减少边缘内部像素的数量。这有助于后续的边缘检测算法更准确地定位物体边缘。

  • 分离连接物体:当两个物体距离非常近以至于在原始图像中看似连在一起时,腐蚀可以减小物体的面积,使得原本重叠或接触的部分变得分离。这对于后续的物体分割或计数任务十分有用。

工作原理:

  1. 结构元素应用cv::erode 函数使用用户指定的结构元素(structuring element)对输入图像中的每个像素进行操作。结构元素通常是一个二值矩阵,代表了影响中心像素判断的邻域形状和大小。例如,一个 3x3 的矩形结构元素可以表示以当前像素为中心的 3x3 邻域。

  2. 条件判断:对于输入图像中的每个像素,将其邻域与结构元素进行比较。在二值图像中,判断条件通常是邻域内所有像素值是否均为 1(前景)。如果是彩色图像,通常先将其转化为灰度或二值图像再进行腐蚀。

  3. 像素值更新:如果邻域内所有像素都满足腐蚀条件,则保留中心像素的原始值;否则,将中心像素值设置为背景色(例如,在二值图像中,设为 0)。这意味着任何无法找到足够数量“支持”像素(即满足腐蚀条件的像素)的中心像素都将被“侵蚀”。

  4. 迭代处理:根据用户指定的迭代次数,重复执行上述过程。多次腐蚀可以进一步减小物体面积或消除边缘附近的噪声。

参数控制:

  • 结构元素:通过 cv::getStructuringElement 函数创建,可以是矩形、圆形、十字形或其他自定义形状,以适应不同的应用场景。

  • 锚点:指定结构元素相对于其作用像素的基准点。默认情况下,结构元素的中心作为锚点,但可以根据需要调整。

  • 迭代次数:控制腐蚀操作的强度。增加迭代次数会使腐蚀效果更明显,可能导致物体面积显著减小或边缘更加细化。

  • 边界处理:定义图像边缘外像素如何处理,如使用常数值填充(BORDER_CONSTANT)、复制边缘像素(BORDER_REPLICATE)等。选择合适的边界处理方式可以避免边缘效应影响腐蚀结果。

示例用法:

// 读取输入图像
cv::Mat src = cv::imread("input_image.png", cv::IMREAD_GRAYSCALE);

// 创建一个矩形结构元素,尺寸为 3x3,锚点位于中心
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));

// 执行一次腐蚀操作
cv::Mat dst;
cv::erode(src, dst, kernel);

// 显示结果
cv::imshow("Original Image", src);
cv::imshow("Eroded Image", dst);
cv::waitKey();

图像膨胀dilate 

        cv::dilate 是 OpenCV 库中用于执行图像膨胀(dilation)操作的函数。图像膨胀是一种形态学图像处理技术,用于增强边缘、连接断裂的边界、填补物体内部的小空洞等。

函数声明:

void cv::dilate(
    InputArray src,
    OutputArray dst,
    InputArray kernel,
    Point anchor = Point(-1, -1),
    int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue());

参数说明:

  • InputArray src: 输入图像,可以是单通道 8-bit、16-bit 或 32-bit 浮点型图像,或者是三通道 8-bit 图像。

  • OutputArray dst: 输出图像,与输入图像 src 具有相同的尺寸和类型。

  • InputArray kernel: 膨胀所使用的结构元素(structuring element)。通常为方形、圆形或其他形状的二值矩阵,定义了膨胀操作中影响像素邻域的形状。结构元素决定了哪些相邻像素将参与到膨胀过程中,共同决定中心像素是否被改变。推荐使用 cv::getStructuringElement 函数来创建结构元素,它可以生成矩形(cv::MORPH_RECT)、椭圆(cv::MORPH_ELLIPSE)或十字形(cv::MORPH_CROSS)等常见形状。

  • Point anchor: 结构元素的锚点(anchor point),即结构元素相对于其作用像素的基准点。默认值为 Point(-1, -1),表示结构元素的中心作为锚点。根据需要,可以指定其他位置作为锚点。

  • int iterations: 膨胀操作的迭代次数。默认值为 1,即执行一次膨胀。若设置为大于 1 的整数,将连续多次应用膨胀操作,每次迭代的结果作为下一次迭代的输入。

  • int borderType: 边界填充类型,定义了如何处理图像边缘以外的像素。可选值包括:

    • BORDER_CONSTANT: 使用指定的 borderValue 填充边缘。
    • BORDER_REPLICATE: 复制边缘像素值。
    • BORDER_REFLECT: 反射边缘像素。
    • BORDER_WRAP: 包裹边缘像素。
    • 其他边界模式,具体参见 OpenCV 文档。
  • const Scalar& borderValue: 当 borderType 为 BORDER_CONSTANT 时,用于填充图像边缘的值。默认情况下,使用 morphologyDefaultBorderValue() 提供的值,通常为黑色(对于 8-bit 图像,为 0)。

功能概述:

  • 增强边缘:膨胀操作可以扩大物体边缘,使原本模糊或弱化的边缘变得更宽、更明显。这对于后续的边缘检测和轮廓提取任务有积极作用。

  • 连接断裂的边界:当物体的边界因噪声、光照变化等原因出现断裂时,膨胀可以“弥合”这些断裂,使得原本分开的部分重新连接起来。这对于保持物体完整性、提高物体识别准确性很有帮助。

  • 填补物体内部的小空洞:对于物体内部存在的小空洞或孔隙,膨胀操作能够用周围像素的颜色填充这些区域,使物体内部变得更加连续和平滑。

工作原理:

  1. 结构元素应用cv::dilate 函数使用用户指定的结构元素(structuring element)对输入图像中的每个像素进行操作。结构元素通常是一个二值矩阵,代表了影响中心像素判断的邻域形状和大小。例如,一个 3x3 的矩形结构元素可以表示以当前像素为中心的 3x3 邻域。

  2. 条件判断:对于输入图像中的每个像素,将其邻域与结构元素进行比较。在二值图像中,判断条件通常是邻域内是否存在至少一个像素值为 1(前景)。如果是彩色图像,通常先将其转化为灰度或二值图像再进行膨胀。

  3. 像素值更新:如果邻域内有任何一个像素满足膨胀条件,则将中心像素值设置为前景色(例如,在二值图像中,设为 1)。这意味着即使只有一个“支持”像素(即满足膨胀条件的像素),中心像素也会被“膨胀”。

  4. 迭代处理:根据用户指定的迭代次数,重复执行上述过程。多次膨胀可以进一步增大物体面积,强化边缘连接效果,或更彻底地填充物体内部空洞。

参数控制:

  • 结构元素:通过 cv::getStructuringElement 函数创建,可以是矩形、圆形、十字形或其他自定义形状,以适应不同的应用场景。

  • 锚点:指定结构元素相对于其作用像素的基准点。默认情况下,结构元素的中心作为锚点,但可以根据需要调整。

  • 迭代次数:控制膨胀操作的强度。增加迭代次数会使膨胀效果更明显,可能导致物体面积显著增大或边缘更加粗厚。

  • 边界处理:定义图像边缘外像素如何处理,如使用常数值填充(BORDER_CONSTANT)、复制边缘像素(BORDER_REPLICATE)等。选择合适的边界处理方式可以避免边缘效应影响膨胀结果。

示例用法:

// 读取输入图像并转为灰度
cv::Mat src = cv::imread("input_image.png", cv::IMREAD_GRAYSCALE);

// 创建一个矩形结构元素,尺寸为 3x3,锚点位于中心
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));

// 执行一次膨胀操作
cv::Mat dst;
cv::dilate(src, dst, kernel);

// 显示结果
cv::imshow("Original Image", src);
cv::imshow("Dilated Image", dst);
cv::waitKey();

综合形态学morphologyEx 

        cv::morphologyEx 是 OpenCV 库中提供的一组综合形态学图像处理功能的函数。它封装了一系列高级形态学操作,如腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽(Top Hat)、黑帽(Black Hat)变换等。这些操作基于基本的腐蚀和膨胀技术,但通过组合和/或对比这些基础操作的结果,实现了更复杂和多样化的图像形态学变换。

函数声明:

void cv::morphologyEx(
    InputArray src,
    OutputArray dst,
    int op,
    InputArray kernel,
    Point anchor = Point(-1, -1),
    int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue());

参数说明:

  • InputArray src: 输入图像,可以是单通道 8-bit、16-bit 或 32-bit 浮点型图像,或者是三通道 8-bit 图像。

  • OutputArray dst: 输出图像,与输入图像 src 具有相同的尺寸和类型。

  • int op: 形态学运算标识符,指定要执行的具体形态学操作。可选值包括:

    • cv::MORPH_ERODE:腐蚀。
    • cv::MORPH_DILATE:膨胀。
    • cv::MORPH_OPEN:开运算(先腐蚀后膨胀)。
    • cv::MORPH_CLOSE:闭运算(先膨胀后腐蚀)。
    • cv::MORPH_GRADIENT:形态学梯度(膨胀图与腐蚀图之差)。
    • cv::MORPH_TOPHAT:顶帽变换(原图与开运算结果之差)。
    • cv::MORPH_BLACKHAT:黑帽变换(闭运算结果与原图之差)。
  • InputArray kernel: 用于形态学操作的结构元素(structuring element)。通常为方形、圆形或其他形状的二值矩阵,由 cv::getStructuringElement 函数生成。结构元素决定了参与运算的像素邻域形状。

  • Point anchor: 结构元素的锚点(anchor point),即结构元素相对于其作用像素的基准点。默认值为 Point(-1, -1),表示结构元素的中心作为锚点。可根据需要指定其他位置作为锚点。

  • int iterations: 进行形态学操作的迭代次数。默认值为 1,即执行一次指定的操作。若设置为大于 1 的整数,将连续多次应用该操作,每次迭代的结果作为下一次迭代的输入。

  • int borderType: 边界填充类型,定义了如何处理图像边缘以外的像素。可选值同 cv::dilate 和 cv::erode 函数中的 borderType 参数。

  • const Scalar& borderValue: 当 borderType 为 BORDER_CONSTANT 时,用于填充图像边缘的值。默认情况下,使用 morphologyDefaultBorderValue() 提供的值,通常为黑色(对于 8-bit 图像,为 0)。

功能概述:

1. 腐蚀与膨胀:

  • 腐蚀 (`cv::MORPH_ERODE):该功能模拟了物理侵蚀过程,通过比较输入图像中每个像素及其邻域与结构元素的关系,去除那些邻域内不符合特定规则(如在二值图像中邻域内没有足够前景像素)的像素。腐蚀常用于消除孤立像素噪声、细化边缘以及分离紧密相连的物体。

  • 膨胀 (`cv::MORPH_DILATE):与腐蚀相反,膨胀操作模拟了物理扩张过程,将输入图像中每个像素的邻域内符合规则(如在二值图像中邻域内只要有任意一个前景像素)的像素值传播到中心像素。膨胀功能适用于增强边缘、连接断裂的边界以及填补物体内部的小空洞。

2. 组合操作:

  • 开运算 (`cv::MORPH_OPEN):先对输入图像进行腐蚀,再进行膨胀。开运算可以有效去除小物体、平滑边缘、分离粘连物体,同时保持大物体的基本形状。它对于消除噪声和分离独立物体特别有用,因为它既消除了小噪声点,又不会过度改变物体的真实轮廓。

  • 闭运算 (`cv::MORPH_CLOSE):与开运算顺序相反,先膨胀后腐蚀。闭运算主要用于连接断裂的边界、填补小空洞、消除小孔洞,并保持大物体的基本形状。它对于恢复断裂的边缘、合并接近但未完全接触的物体以及消除内部小孔洞非常有效。

3. 特征提取与增强:

  • 形态学梯度 (`cv::MORPH_GRADIENT):计算膨胀图像与腐蚀图像之间的差异。结果图像中,每个像素的值反映了原图像中相应位置边缘的强度。形态学梯度常用于边缘检测和边缘增强,因为它能突出显示图像中的边缘信息,同时对噪声有一定的抑制作用。

  • 顶帽 (`cv::MORPH_TOPHAT):计算原图像与开运算结果之间的差值。顶帽变换会突出显示原图像中比结构元素尺寸小的细节特征,如小物体或细线。这些细节在开运算中会被消除,因此在顶帽变换结果中,这些细节表现为正差值。

  • 黑帽 (`cv::MORPH_BLACKHAT):计算闭运算结果与原图像之间的差值。黑帽变换强调的是原图像中比结构元素尺寸大的暗区细节,如孔洞或凹陷。这些细节在闭运算中会被填补,因此在黑帽变换结果中,这些细节表现为负差值。

参数控制与通用特性:

cv::morphologyEx 函数接受以下关键参数以控制形态学操作的执行:

  • 结构元素 (kernel):定义了参与形态学运算的像素邻域形状和大小。结构元素通常为二值矩阵,可以通过 cv::getStructuringElement 函数创建,支持矩形、椭圆、十字形等形状,以及自定义形状。

  • 锚点 (anchor):结构元素相对于其作用像素的基准点,默认为结构元素中心。可以调整锚点位置以适应特定的形态学需求。

  • 迭代次数 (iterations):指定进行形态学操作的迭代次数。增加迭代次数可以增强形态学操作的效果,但可能会导致物体面积显著变化或边缘过度平滑。

  • 边界处理 (borderType 和 borderValue):定义图像边缘外像素如何处理,如常数值填充、复制边缘像素等,以避免边缘效应影响形态学处理结果。

应用示例:

// 读取输入图像
cv::Mat src = cv::imread("input_image.png", cv::IMREAD_GRAYSCALE);

// 创建一个矩形结构元素,尺寸为 3x3,锚点位于中心
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));

// 执行形态学开运算
cv::Mat openResult;
cv::morphologyEx(src, openResult, cv::MORPH_OPEN, kernel);

// 执行形态学梯度计算
cv::Mat gradientResult;
cv::morphologyEx(src, gradientResult, cv::MORPH_GRADIENT, kernel);

// 显示结果
cv::imshow("Original Image", src);
cv::imshow("Open Result", openResult);
cv::imshow("Morphological Gradient", gradientResult);
cv::waitKey();

效果展示

腐蚀与膨胀

综合形态学

  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Opencv中的分水岭算法(watershed algorithm)是一种自动图像分割算法,常用于分离图像中的前景和背景。下面是使用Opencv中的分水岭算法进行图像分割的步骤: 1. 读入图像并进行预处理,如去噪、灰度化等。 2. 对图像进行二值化处理,得到前景和背景的二值图像。 3. 对二值图像进行距离变换(distance transform),得到每个像素离最近的背景像素的距离。 4. 对距离变换后的图像进行阈值处理,得到图像的分水岭标记(watershed markers)。 5. 对分水岭标记进行修正,确保标记不会重叠或出现空洞。 6. 对分水岭标记应用分水岭算法,得到分割后的图像。 下面是使用Opencv实现分水岭算法的示例代码: ```python import cv2 import numpy as np # 读取图像并进行预处理 img = cv2.imread('input.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # 进行距离变换 dist_transform = cv2.distanceTransform(thresh,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # 获取分水岭标记 sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(thresh,sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers+1 markers[unknown==255] = 0 # 修正分水岭标记 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] # 显示分割结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码中,我们首先读入一张图像并进行预处理,然后进行距离变换,得到每个像素到最近的背景像素的距离。接着使用阈值处理得到分水岭标记,修正分水岭标记并应用分水岭算法,最后显示分割结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值