如何从图像中删除连接的组件同时保留一些
How to remove connected components from an image while retaining some
假设我在来自 bwlabel
的名为 labelledImage
的图像中有 5 个连接的组件(标记的对象)。如何操作 labelledImage
使得标记为 1 和 4 的对象只显示,同时删除标记为 2、3 和 5 的对象。那么,如何操作原始 RGB 图像以便仅显示标记为 1 和 4 的连通分量。
我知道如何使用下面这行代码来保留单个连通分量。但是,我不知道如何为多个标记区域执行此操作。
有效。
connectedComponent1 = (labelledImage == 1);
imshow(connectedComponent1)
无效。
connectedComponent1and4 = (labelledImage == [1 4]);
imshow(connectedComponent1and4)
你不能那样做 logical
索引。最简单的方法可能是使用布尔语句来组合事物。
connectedCompoonent1and4 = labelledImage == 1 | labelledImage == 4;
一般来说,假设您有一个元素向量,表示要保留哪些组件,您可以使用 bsxfun
, permute
and any
来帮助您。这样的事情应该有效:
components = [1 4];
connected = any(bsxfun(@eq, labelledImage, permute(components, [1 3 2])), 3);
以上代码使用矩阵广播创建一个临时 3D 矩阵,其中每个切片 i
包含向量 components
的第 i
个值,其中包含您想要的所需标签保持。 labelledImage
也在三维中复制,因此使用 bsxfun
的结果创建了一个 3D 矩阵,其中每个切片 i
分割出您要保留的第 i
个对象。然后,我们使用 any
并在三维中查看将所有对象组合在一起。
如果您不喜欢单行代码,您甚至可以使用一个简单的 for
循环:
components = [1 4];
connected = false(size(labelledImage, 1), size(labelledImage, 2));
for ind = 1 : numel(components)
connected = connected | labelledImage == components(ind);
end
这将创建一个全部为 false
的输出图像,然后我们遍历要保留的组件向量中的每个值,并将这些结果附加到结果之上。最后会给你所有你想保留的组件。
最后,您还可以使用 ismember
并确定矩阵中可以在标签矩阵和分量向量之间找到的那些值,然后以这种方式简单地创建掩码:
connected = ismember(labelledImage, components);
现在您有了要提取的对象蒙版,要在原始图像上使用它,只需将每个通道与蒙版相乘即可。 bsxfun
的另一种用法可以为您做到这一点。假设您的 RGB 图像名为 img
,只需执行以下操作:
outImg = bsxfun(@times, img, cast(connected, class(img)));
要执行逐元素乘法,您必须确保要相乘的两个矩阵具有相同的类型。我将掩码转换为与输入图像相同的 class 并执行乘法。
使用ismember
.
例如:
A = randi(5,5); % your connected component matrix
B = [1 4] % list of components you want to keep
A =
4 2 1 3 5
2 4 2 5 1
3 4 5 1 4
1 4 1 3 5
4 3 5 1 5
A(~ismember(A,B)) = 0
A =
4 0 1 0 0
0 4 0 0 1
0 4 0 1 4
1 4 1 0 0
4 0 0 1 0
假设我在来自 bwlabel
的名为 labelledImage
的图像中有 5 个连接的组件(标记的对象)。如何操作 labelledImage
使得标记为 1 和 4 的对象只显示,同时删除标记为 2、3 和 5 的对象。那么,如何操作原始 RGB 图像以便仅显示标记为 1 和 4 的连通分量。
我知道如何使用下面这行代码来保留单个连通分量。但是,我不知道如何为多个标记区域执行此操作。
有效。
connectedComponent1 = (labelledImage == 1);
imshow(connectedComponent1)
无效。
connectedComponent1and4 = (labelledImage == [1 4]);
imshow(connectedComponent1and4)
你不能那样做 logical
索引。最简单的方法可能是使用布尔语句来组合事物。
connectedCompoonent1and4 = labelledImage == 1 | labelledImage == 4;
一般来说,假设您有一个元素向量,表示要保留哪些组件,您可以使用 bsxfun
, permute
and any
来帮助您。这样的事情应该有效:
components = [1 4];
connected = any(bsxfun(@eq, labelledImage, permute(components, [1 3 2])), 3);
以上代码使用矩阵广播创建一个临时 3D 矩阵,其中每个切片 i
包含向量 components
的第 i
个值,其中包含您想要的所需标签保持。 labelledImage
也在三维中复制,因此使用 bsxfun
的结果创建了一个 3D 矩阵,其中每个切片 i
分割出您要保留的第 i
个对象。然后,我们使用 any
并在三维中查看将所有对象组合在一起。
如果您不喜欢单行代码,您甚至可以使用一个简单的 for
循环:
components = [1 4];
connected = false(size(labelledImage, 1), size(labelledImage, 2));
for ind = 1 : numel(components)
connected = connected | labelledImage == components(ind);
end
这将创建一个全部为 false
的输出图像,然后我们遍历要保留的组件向量中的每个值,并将这些结果附加到结果之上。最后会给你所有你想保留的组件。
最后,您还可以使用 ismember
并确定矩阵中可以在标签矩阵和分量向量之间找到的那些值,然后以这种方式简单地创建掩码:
connected = ismember(labelledImage, components);
现在您有了要提取的对象蒙版,要在原始图像上使用它,只需将每个通道与蒙版相乘即可。 bsxfun
的另一种用法可以为您做到这一点。假设您的 RGB 图像名为 img
,只需执行以下操作:
outImg = bsxfun(@times, img, cast(connected, class(img)));
要执行逐元素乘法,您必须确保要相乘的两个矩阵具有相同的类型。我将掩码转换为与输入图像相同的 class 并执行乘法。
使用ismember
.
例如:
A = randi(5,5); % your connected component matrix
B = [1 4] % list of components you want to keep
A =
4 2 1 3 5
2 4 2 5 1
3 4 5 1 4
1 4 1 3 5
4 3 5 1 5
A(~ismember(A,B)) = 0
A =
4 0 1 0 0
0 4 0 0 1
0 4 0 1 4
1 4 1 0 0
4 0 0 1 0