形态开放和关闭的结果会产生相同的结果?

时间:2014-11-23 04:48:13

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

我想知道是否有任何示例或情况,单个图像上的打开和关闭形态操作会产生相同的结果。

举个例子,我们假设我们有一个图片X,我们已经完成了打开操作以生成Y。同样,我们对原始X执行了结算操作,以生成相同的Y。我想知道是否有这些类型的图像的例子X。 Python或MATLAB中的编程示例也很受欢迎。

2 个答案:

答案 0 :(得分:3)

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

如果您在此图片上打开并关闭此图片,则会产生相同的结果。请记住,开口是侵蚀,然后是扩张,其中关闭是扩张,然后是侵蚀。在分析形状方面,侵蚀略微缩小了图像的面积,而扩张则略微扩大了它。

通过进行侵蚀然后进行扩张(打开),您可以缩小对象,然后再次进行生长。这将使图像恢复到之前的状态,只要您选择结构元素就像我们之前谈到的那样。同样地,如果你进行了扩张,然后进行了侵蚀(关闭),你就会重新生长物体然后再缩小它,同时将图像带回原来的状态......遵循我刚才谈到的同样的指导方针当然。

如果你要选择一个大于最小物体的结构元素,那么在图像中删除这个对象会让你无法获得原始图像背部。此外,您需要确保对象远离彼此,并且当您滑过并执行形态学操作时,结构元素的大小不会与任何对象重叠。原因是因为如果你要关闭,你会把这两个对象加在一起,这样就不会给你带来相同的结果!


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

enter image description here

要在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');

结果如下:

enter image description here

它看起来一样!为了真正显示差异,让我们从原始图像中减去已关闭和打开的结果。如果它们都等于原始图像,那么最终应该得到一张空白图像。

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来确保反映出负面差异。这就是我得到的:

enter image description here

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

第一部分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()

这是我得到的:

enter image description here

您需要为此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中做的事情。这就是我得到的:

enter image description here


通常,您可以使用任何形状和任何大小的形状重现我所做的,只要您选择模仿图像中形状属性的结构元素,并选择一个结构元素,小于该图像中看到的最小形状。我确信还有更多的例子不必遵循这些具体的指导原则,但这是我现在能想到的最好的例子。


这应该可以让你开始。

祝你好运!

答案 1 :(得分:1)

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

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