【问题标题】:Cases where Morphological Opening and Closing yields the same results?形态开闭产生相同结果的情况?
【发布时间】:2014-11-23 04:48:12
【问题描述】:

我想知道是否有任何示例或案例表明对单个图像的打开和关闭形态学操作会产生相同的结果。

例如,假设我们有一个图像X,并且我们已经完成了打开操作以生成Y。同样,我们对原始的X 进行了关闭操作以生成相同的Y。我想知道这些类型的图像是否有示例X。 Python 或 MATLAB 中的编程示例也值得赞赏。

【问题讨论】:

    标签: python matlab opencv image-processing computer-vision


    【解决方案1】:

    是的,有。作为一个小例子,如果你有一个二进制图像,它由一堆不连贯且不同的正方形组成。如果您指定一个正方形的结构元素,并选择结构元素使其小于图像中最小的正方形,那么执行任一操作都会得到相同的结果。

    如果您在此图像上打开并在此图像上关闭,您将产生相同的结果。请记住,开口是腐蚀后膨胀,闭合是膨胀后腐蚀。在分析形状方面,腐蚀会稍微缩小图像的面积,而膨胀会稍微扩大图像的面积。

    通过先腐蚀再膨胀(打开),您可以缩小对象,然后再将其放大。只要您像我们之前讨论的那样选择结构元素,这将使图像恢复到以前的位置。同样,如果您先进行膨胀然后再进行侵蚀(关闭),您将扩大对象然后再次缩小它,同时将图像恢复到之前的位置......当然遵循我刚才谈到的相同准则.

    如果您要选择一个大于最小对象的结构元素,则打开该对象将从图像中移除该对象,因此您不会得到原始图像。此外,您需要确保对象彼此相距很远,并且当您滑过并进行形态学操作时,结构元素的大小不会与任何对象重叠。原因是如果你要关闭,你会将这两个对象连接在一起,这样也不会得到相同的结果!


    这是我生成的二进制示例图像:

    要在 MATLAB 中生成此图像,您可以:

    A = false(200,200);
    A(30:60,30:60) = true;
    A(90:110,90:110) = true;
    A(10:30, 135:155) = true;
    A(150:180,100:120) = true;
    

    在 Python 中,您可以使用 numpy

    import numpy as np
    A = np.zeros((200,200), dtype='uint8')
    A[29:60,29:60] = 255
    A[89:110,89:110] = 255
    A[9:30, 134:155] = 255
    A[149:180, 99:120] = 255
    

    我必须在numpy 中将数组创建为uint8 的原因是因为当我们要显示此图像时,我将使用OpenCV,并且它要求图像至少为uint8输入。

    现在,让我们选择一个 5 x 5 的方形结构元素,并使用此图像执行关闭和打开操作。我们将在一个图中从左到右显示结果:

    se = strel('square', 5);
    A_close = imclose(A, se);
    A_open = imopen(A, se);
    figure;
    subplot(1,3,1);
    imshow(A);
    title('Original');
    subplot(1,3,2);
    imshow(A_close);
    title('Closed');
    subplot(1,3,3);
    imshow(A_open);
    title('Open');
    

    这是结果:

    看起来确实一样!为了真正显示差异,让我们从原始图像中减去关闭和打开的结果。如果它们都与原始图像相同,您最终应该会得到一个空白图像。

    figure;
    subplot(1,2,1);
    imshow(abs(double(A) - double(A_close)));
    subplot(1,2,2);
    imshow(abs(double(A) - double(A_open)));
    

    请记住,我将图像转换为double 以方便减法,并使用abs 确保反映负面差异。这是我得到的:

    如您所见,两个结果都是空白的,这意味着它们是每个结果后原始图像的精确副本。

    Python 中第一部分的等效代码如下:

    import cv2
    se = np.ones((5,5), dtype='uint8')
    A_close = cv2.morphologyEx(A, cv2.MORPH_CLOSE, se)
    A_open = cv2.morphologyEx(A, cv2.MORPH_OPEN, se)
    cv2.imshow('Original', A)
    cv2.imshow('Close', A_close)
    cv2.imshow('Open', A_open)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    这是我得到的:

    您需要为此 Python 代码安装 OpenCV 包。我将所有图像显示为三个单独的图形,然后将窗口留在那里,直到您选择其中任何一个并按下一个键。执行此操作后,所有窗口都将关闭。如果你想显示减法的东西,这是 Python 中的代码:

    A_close_diff = A - A_close
    A_open_diff = A - A_open
    cv2.imshow('Close Diff', A_close_diff)
    cv2.imshow('Open Diff', A_open_diff)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    我没有在 MATLAB 中为图形命名,因为我们展示的内容很明显,但对于 OpenCV,您需要命名窗口,因此我输入的名称描述了我们为每个展示的内容。我也不需要取绝对值,因为在numpy 中,进行导致上溢或下溢的算术运算将简单地环绕自身,而对于 MATLAB,值会被截断。这就是为什么对于 MATLAB,我需要转换为 double 并取绝对值,因为 imshow 不显示负强度,或者如果我们遇到 0 - 1 的情况,输出将为 0 而你无法证明这个位置有区别。使用 Python,对 uint8 执行 0 - 1 将得到 255,因此我们当然可以在这里看到不同之处......所以没有必要像在 MATLAB 中那样做任何 abs 和强制转换。这是我得到的:


    一般来说,你可以用任何形状和任何大小的形状复制我所做的,只要你选择一个模仿图像中形状属性的结构元素,并且选择一个结构元素,小于该图像中看到的最小形状。我敢肯定还有更多示例不必遵循这些特定准则,但这是我目前能想到的最佳示例。


    希望这可以帮助您入门。

    祝你好运!

    【讨论】:

    • 感谢您回答我的问题。这总结了一切。谢谢
    【解决方案2】:

    是的,有这样的图像。开的特性之一(例如wiki 文章中提到的)是它是一种反扩展操作,即如果 Y 是 X 的开,则 Y ⊆ X。同样,闭是一种扩展操作(即X ⊆ Y),因此对于任何这样的图像 X = Y。任何对打开和关闭都不变的图像将满足您的要求(并且,正如我刚刚展示的那样,只有这样的图像会)。

    具体示例取决于执行腐蚀或膨胀时使用的结构元素。例如,如果它是一个所有元素都等于 1 的正方形 n x n 矩阵,那么任何高度和宽度都大于 n 的矩形(并且距离图像边缘足够远,即至少 n/2 个像素)将满足此要求.

    【讨论】:

    • 感谢您回答我的问题,起初理解起来有点复杂,但我有点明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多