我想知道是否有任何示例或情况,单个图像上的打开和关闭形态操作会产生相同的结果。
举个例子,我们假设我们有一个图片X
,我们已经完成了打开操作以生成Y
。同样,我们对原始X
执行了结算操作,以生成相同的Y
。我想知道是否有这些类型的图像的例子X
。 Python或MATLAB中的编程示例也很受欢迎。
答案 0 :(得分:3)
是的。作为一个小例子,如果你有一个二进制图像,它由一堆断开且不同的正方形组成。如果指定一个正方形的结构元素,并选择结构元素使其小于图像中的最小正方形,那么执行任一操作都会得到相同的结果。
如果您在此图片上打开并关闭此图片,则会产生相同的结果。请记住,开口是侵蚀,然后是扩张,其中关闭是扩张,然后是侵蚀。在分析形状方面,侵蚀略微缩小了图像的面积,而扩张则略微扩大了它。
通过进行侵蚀然后进行扩张(打开),您可以缩小对象,然后再次进行生长。这将使图像恢复到之前的状态,只要您选择结构元素就像我们之前谈到的那样。同样地,如果你进行了扩张,然后进行了侵蚀(关闭),你就会重新生长物体然后再缩小它,同时将图像带回原来的状态......遵循我刚才谈到的同样的指导方针当然。
如果你要选择一个大于最小物体的结构元素,那么在图像中删除这个对象会让你无法获得原始图像背部。此外,您需要确保对象远离彼此,并且当您滑过并执行形态学操作时,结构元素的大小不会与任何对象重叠。原因是因为如果你要关闭,你会把这两个对象加在一起,这样就不会给你带来相同的结果!
这是我生成的二进制示例图像:
要在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
我必须在uint8
中创建numpy
数组的原因是因为当我们要显示此图像时,我将使用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
没有显示负强度,或者我们是否遇到过这样的情况{ {1}},输出为0,您将无法显示此位置有差异。使用Python,为0 - 1
执行0 - 1
将导致255,因此我们当然可以看到有所不同....所以没有必要执行任何此操作{{1}和我们在MATLAB中做的事情。这就是我得到的:
通常,您可以使用任何形状和任何大小的形状重现我所做的,只要您选择模仿图像中形状属性的结构元素,并选择一个结构元素,小于该图像中看到的最小形状。我确信还有更多的例子不必遵循这些具体的指导原则,但这是我现在能想到的最好的例子。
这应该可以让你开始。
祝你好运!答案 1 :(得分:1)
是的,有这样的图像。打开的一个属性(例如在wiki文章中提到)是它是一个反扩展操作,即如果Y打开X,那么Y⊆X。同样,关闭是一个广泛的操作(即X⊆Y),因此对于任何这样的图像X = Y.任何对打开和关闭都不变的图像将满足您的要求(并且,正如我刚才所示,仅这样的图像将)。
具体示例取决于执行侵蚀或扩张时使用的结构元素。例如,如果它是一个方形nxn矩阵,所有元素都等于1,则任何高度和宽度都大于n的矩形(并且距离图像边缘位置足够远,即至少n / 2像素)将满足此要求