MATLAB:找到二进制的底部对角线层
MATLAB: finding the bottom diagonal layer in binary
我有一个包含多个层的二值图像 - 通常是对角线的并且具有不同的宽度,我正在尝试找到底层。换句话说,我不能依赖图层、质心等的最小 Y 值。
我认为解决方案应该与查看多个层交叉的特定 Y 值有关,然后选择该值的底层.. 不确定如何对此进行编码-(特别是不确定如何找到那个 y 值)...也许还有更聪明的方法来做到这一点?
因此在所附图片中:这将以二进制形式开始,蓝线和绿线均为白色。我 运行 bwconncomps() 在二进制文件上。绿线是我想识别的那条。红线是我想我可以检查底层的地方——但我如何找到这个位置?
一种方法是在图像的每一列中找到最后一个 1
。然后,在 运行 bwconncomp
之后,您可以检查给定组件在每列中包含最后一个 1
的次数。
我们可以将其分解为以下步骤。
识别每列中包含最后一个 1
的行。 有许多不同的方法可以做到这一点,但一种方法是沿第一个维度取累计和 (cumsum
),并在每列中找到最大值的行(使用 max
)。这将告诉我们每行中包含最后一个 1
的行。
举个例子:
data = [1 0 0;
0 0 1;
1 1 0];
C = cumsum(data, 1);
% 1 0 0
% 1 0 1
% 2 1 1
[~, rows] = max(C, [], 1);
% 3 3 2
识别所有连通分量。这个很简单,因为我们可以只使用 bwconncomp
来获取连通分量。
判断每个连通分量有多少个成员在各自列的最后1
。我们可以转换rows
我们在步骤 1 中使用 sub2ind
找到了它们的线性索引。然后我们可以遍历所有连接的组件并使用 ismember
和 sum
来确定这些值中有多少出现在给定的连接组件中(使用 PixelIdxList
确定)。
使用其行中最后 1
像素最多的组件作为 "most distance" 组件。我们可以再次对步骤 3 的输出使用 max
来确定这一点。
综合起来
因此,如果我们为您的数据写出所有内容,它看起来将类似于以下内容(忽略前两行,因为只需要它们来根据您在 [=71= 中提供的图像创建二进制图像]).
% Load the image and convert to binary image
img = imread('http://i.stack.imgur.com/flpoC.jpg');
img = img(:,:,2) > 50 | img(:,:,3) > 50;
% Determine the row which contains the last 1 in each column
C = cumsum(img, 1);
[~, rows] = max(C, [], 1);
% Now convert these rows indices to linear indices
% (the ones that will appear in PixelIdxList)
inds = sub2ind(size(img), rows, 1:size(C, 1));
% Get connected components of the image
CC = bwconncomp(img);
% Determine the number of pixels in each component that were at the bottom
numAtBottom = cellfun(@(x)sum(ismember(inds, x)), CC.PixelIdxList);
% The one that has the most was the largest bottom-most component
[~, bottomComponent] = max(numAtBottom);
并显示该组件作为概念证明
% Just to show this, we will create a binary image of JUST that component
I = img;
I(CC.PixelIdxList{bottomComponent}) = 2;
figure, imagesc(I)
我有一个包含多个层的二值图像 - 通常是对角线的并且具有不同的宽度,我正在尝试找到底层。换句话说,我不能依赖图层、质心等的最小 Y 值。
我认为解决方案应该与查看多个层交叉的特定 Y 值有关,然后选择该值的底层.. 不确定如何对此进行编码-(特别是不确定如何找到那个 y 值)...也许还有更聪明的方法来做到这一点?
因此在所附图片中:这将以二进制形式开始,蓝线和绿线均为白色。我 运行 bwconncomps() 在二进制文件上。绿线是我想识别的那条。红线是我想我可以检查底层的地方——但我如何找到这个位置?
一种方法是在图像的每一列中找到最后一个 1
。然后,在 运行 bwconncomp
之后,您可以检查给定组件在每列中包含最后一个 1
的次数。
我们可以将其分解为以下步骤。
识别每列中包含最后一个
1
的行。 有许多不同的方法可以做到这一点,但一种方法是沿第一个维度取累计和 (cumsum
),并在每列中找到最大值的行(使用max
)。这将告诉我们每行中包含最后一个1
的行。举个例子:
data = [1 0 0; 0 0 1; 1 1 0]; C = cumsum(data, 1); % 1 0 0 % 1 0 1 % 2 1 1 [~, rows] = max(C, [], 1); % 3 3 2
识别所有连通分量。这个很简单,因为我们可以只使用
bwconncomp
来获取连通分量。判断每个连通分量有多少个成员在各自列的最后
1
。我们可以转换rows
我们在步骤 1 中使用sub2ind
找到了它们的线性索引。然后我们可以遍历所有连接的组件并使用ismember
和sum
来确定这些值中有多少出现在给定的连接组件中(使用PixelIdxList
确定)。使用其行中最后
1
像素最多的组件作为 "most distance" 组件。我们可以再次对步骤 3 的输出使用max
来确定这一点。
综合起来
因此,如果我们为您的数据写出所有内容,它看起来将类似于以下内容(忽略前两行,因为只需要它们来根据您在 [=71= 中提供的图像创建二进制图像]).
% Load the image and convert to binary image
img = imread('http://i.stack.imgur.com/flpoC.jpg');
img = img(:,:,2) > 50 | img(:,:,3) > 50;
% Determine the row which contains the last 1 in each column
C = cumsum(img, 1);
[~, rows] = max(C, [], 1);
% Now convert these rows indices to linear indices
% (the ones that will appear in PixelIdxList)
inds = sub2ind(size(img), rows, 1:size(C, 1));
% Get connected components of the image
CC = bwconncomp(img);
% Determine the number of pixels in each component that were at the bottom
numAtBottom = cellfun(@(x)sum(ismember(inds, x)), CC.PixelIdxList);
% The one that has the most was the largest bottom-most component
[~, bottomComponent] = max(numAtBottom);
并显示该组件作为概念证明
% Just to show this, we will create a binary image of JUST that component
I = img;
I(CC.PixelIdxList{bottomComponent}) = 2;
figure, imagesc(I)