是的,有。作为一个小例子,如果你有一个二进制图像,它由一堆不连贯且不同的正方形组成。如果您指定一个正方形的结构元素,并选择结构元素使其小于图像中最小的正方形,那么执行任一操作都会得到相同的结果。
如果您在此图像上打开并在此图像上关闭,您将产生相同的结果。请记住,开口是腐蚀后膨胀,闭合是膨胀后腐蚀。在分析形状方面,腐蚀会稍微缩小图像的面积,而膨胀会稍微扩大图像的面积。
通过先腐蚀再膨胀(打开),您可以缩小对象,然后再将其放大。只要您像我们之前讨论的那样选择结构元素,这将使图像恢复到以前的位置。同样,如果您先进行膨胀然后再进行侵蚀(关闭),您将扩大对象然后再次缩小它,同时将图像恢复到之前的位置......当然遵循我刚才谈到的相同准则.
如果您要选择一个大于最小对象的结构元素,则打开该对象将从图像中移除该对象,因此您不会得到原始图像。此外,您需要确保对象彼此相距很远,并且当您滑过并进行形态学操作时,结构元素的大小不会与任何对象重叠。原因是如果你要关闭,你会将这两个对象连接在一起,这样也不会得到相同的结果!
这是我生成的二进制示例图像:
要在 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 和强制转换。这是我得到的:
一般来说,你可以用任何形状和任何大小的形状复制我所做的,只要你选择一个模仿图像中形状属性的结构元素,并且选择一个结构元素,小于该图像中看到的最小形状。我敢肯定还有更多示例不必遵循这些特定准则,但这是我目前能想到的最佳示例。
希望这可以帮助您入门。
祝你好运!