使用Matlab从图像中的指定行向上扫描以根据强度变化检测新区域
Using Matlab to scan up from a specified row in an image to detect a new region based on intensity variation
这是我正在处理的图像类型:
您可以看到我使用以下代码绘制的粉红色线条:
A=imread('b20.bmp');
AR=A(:,:,1);
[rows, columns] = size(AR);
y1 = 200;
y2 = 315;
row1 = AR(y1, :); % Extract this line of gray levels from the image.
figure, image(AR,'CDataMapping','scaled'); colormap('gray');
title('Input Image in Grayscale')
hold on;
plot([0, columns], [y2, y2], 'm');
我希望从突出显示的行 (315) 向上扫描到图像的第一行以检测暗区,一旦检测到该区域,我希望在中点绘制另一条线黑暗区域,类似于第一个(整个图像)。
我想要这样做的原因是,一旦检测到 2 个区域的中点,我希望从 2 条线中获取统计信息,例如标准差和均值,以尝试处理 2 段以给周围的行或段一个整体平均值。
Jonas 几乎已经告诉您如何解决它。但是,因为我喜欢玩图像,所以我决定写一个答案。我要做的是提取一个从第 1 行到第 315 行的子图像,然后我会独立地找到每个 行 的平均值。这将为您提供一个包含 315 个元素的向量...然后从这个结果来看,无论哪个位置给我们一个巨大的尖峰,这都可能是细分开始的地方。这是一个人为的例子。我试着用一些最少的代码重新创建你的。我要创建一个黑白图像,其中上半部分为黑色,下半部分为白色。完成后,我将向其添加一些随机高斯噪声,振幅为 10,平均值为 0,标准差为 1。之后,我将对图像进行归一化,使其在 [0,1]
之间动态范围:
%// Set random seed generator
rng(123);
%// Create black and white image. First 250 rows is black, next 250 rows is gray
im = [zeros(250, 256); 128*ones(250,256)];
%// Add Gaussian random noise of amplitude 10, mean 0, std.dev = 1
im_noise = im + 10*randn(size(im));
%// Normalize image so it's between [0,1]
AR = (im_noise - min(im_noise(:))) / (max(im_noise(:)) - min(im_noise(:)));
我已经将嘈杂的图像存储在 AR
中,以便您可以复制并粘贴我接下来要尝试的内容。为了完整起见,这就是图像的样子:
魔法开始了。让我们找出第 1 行和第 315 行之间每一行的平均值:
avgs = mean(AR(1:315,:), 2);
2
参数的意思是沿着列进行运算,也就是说我们会求每一行的平均值。这意味着我们将得到一个 315 元素的向量,其中每个元素都是一行的 平均值...。所以第一个元素是第 1 行的平均值,第二个元素是第 1 行的平均值第 2 行,依此类推。如果我们在正常图上绘制这些平均值,其中行号是水平轴,平均强度在垂直轴上,这就是我们得到的:
plot(1:315, avgs);
如您所见,在 250 处有一个明显的尖峰,在我设计的图像中,就在第 250 行,我使灰色方块出现的位置。我们可以通过 diff
combined with max
计算数组中元素之间的成对距离来确定 这个尖峰出现的位置 。 diff
的工作原理是第一个输出是第二个元素减去第一个,然后第二个元素是第三对减去第二个,依此类推。在这种情况下,因为我们正在从低到高过渡,这意味着无论位置给我们最高的差异意味着我们从右边(或边缘的最高值)到左边(或最低值)取一个数字边的。因此,我们找到成对距离并确定我们拥有最大可能成对距离的点。因此,执行如下操作:
[~,ind] = max(diff(avgs));
max
的好处在于,如果数据中有 多个 值共享相同的最大值,我们只 return 第一个 出现的值。这很好,因为一旦我们在图中检测到尖峰,我们就会立即找到这个结果。如果你这样做正确,ind
应该是 250。
我想指出的一件事是,上面的语法假设您正在从黑色过渡到白色。如果你有 相反 行为,你要么想研究使用 min
,要么如果你希望它与你正在经历的渐变类型无关,请使用max
结合 abs
。这样,当我们找到最大的差异时,如果从黑到白,它将是一个大的正数;如果从白到黑,它将是一个大的负数。如果我们用 abs
删除所有负值,这意味着无论符号是什么,我们都会将其视为一个大的正值,因此无论如何我们都应该能够检测到跳跃。因此,你应该做的是:
[~,ind] = max(abs(diff(avgs)));
现在,您所要做的就是显示此图像,然后在该位置所在的位置画一条线:
figure;
imshow(AR);
hold on;
plot([1 size(AR,2)], [ind ind], 'r', 'LineWidth', 2);
我将线条的粗细设置为 2 个像素,以便您可以清楚地看到线条,并且我将其设置为红色。这就是我们得到的:
因此,如果您想将其复制并粘贴到 MATLAB 中以供您 运行,请使用以下代码:
avgs = mean(AR(1:315,:), 2);
[~,ind] = max(abs(diff(avgs)));
figure;
imshow(AR);
hold on;
plot([1 size(AR,2)], [ind ind], 'r', 'LineWidth', 2);
这是我正在处理的图像类型:
您可以看到我使用以下代码绘制的粉红色线条:
A=imread('b20.bmp');
AR=A(:,:,1);
[rows, columns] = size(AR);
y1 = 200;
y2 = 315;
row1 = AR(y1, :); % Extract this line of gray levels from the image.
figure, image(AR,'CDataMapping','scaled'); colormap('gray');
title('Input Image in Grayscale')
hold on;
plot([0, columns], [y2, y2], 'm');
我希望从突出显示的行 (315) 向上扫描到图像的第一行以检测暗区,一旦检测到该区域,我希望在中点绘制另一条线黑暗区域,类似于第一个(整个图像)。
我想要这样做的原因是,一旦检测到 2 个区域的中点,我希望从 2 条线中获取统计信息,例如标准差和均值,以尝试处理 2 段以给周围的行或段一个整体平均值。
Jonas 几乎已经告诉您如何解决它。但是,因为我喜欢玩图像,所以我决定写一个答案。我要做的是提取一个从第 1 行到第 315 行的子图像,然后我会独立地找到每个 行 的平均值。这将为您提供一个包含 315 个元素的向量...然后从这个结果来看,无论哪个位置给我们一个巨大的尖峰,这都可能是细分开始的地方。这是一个人为的例子。我试着用一些最少的代码重新创建你的。我要创建一个黑白图像,其中上半部分为黑色,下半部分为白色。完成后,我将向其添加一些随机高斯噪声,振幅为 10,平均值为 0,标准差为 1。之后,我将对图像进行归一化,使其在 [0,1]
之间动态范围:
%// Set random seed generator
rng(123);
%// Create black and white image. First 250 rows is black, next 250 rows is gray
im = [zeros(250, 256); 128*ones(250,256)];
%// Add Gaussian random noise of amplitude 10, mean 0, std.dev = 1
im_noise = im + 10*randn(size(im));
%// Normalize image so it's between [0,1]
AR = (im_noise - min(im_noise(:))) / (max(im_noise(:)) - min(im_noise(:)));
我已经将嘈杂的图像存储在 AR
中,以便您可以复制并粘贴我接下来要尝试的内容。为了完整起见,这就是图像的样子:
魔法开始了。让我们找出第 1 行和第 315 行之间每一行的平均值:
avgs = mean(AR(1:315,:), 2);
2
参数的意思是沿着列进行运算,也就是说我们会求每一行的平均值。这意味着我们将得到一个 315 元素的向量,其中每个元素都是一行的 平均值...。所以第一个元素是第 1 行的平均值,第二个元素是第 1 行的平均值第 2 行,依此类推。如果我们在正常图上绘制这些平均值,其中行号是水平轴,平均强度在垂直轴上,这就是我们得到的:
plot(1:315, avgs);
如您所见,在 250 处有一个明显的尖峰,在我设计的图像中,就在第 250 行,我使灰色方块出现的位置。我们可以通过 diff
combined with max
计算数组中元素之间的成对距离来确定 这个尖峰出现的位置 。 diff
的工作原理是第一个输出是第二个元素减去第一个,然后第二个元素是第三对减去第二个,依此类推。在这种情况下,因为我们正在从低到高过渡,这意味着无论位置给我们最高的差异意味着我们从右边(或边缘的最高值)到左边(或最低值)取一个数字边的。因此,我们找到成对距离并确定我们拥有最大可能成对距离的点。因此,执行如下操作:
[~,ind] = max(diff(avgs));
max
的好处在于,如果数据中有 多个 值共享相同的最大值,我们只 return 第一个 出现的值。这很好,因为一旦我们在图中检测到尖峰,我们就会立即找到这个结果。如果你这样做正确,ind
应该是 250。
我想指出的一件事是,上面的语法假设您正在从黑色过渡到白色。如果你有 相反 行为,你要么想研究使用 min
,要么如果你希望它与你正在经历的渐变类型无关,请使用max
结合 abs
。这样,当我们找到最大的差异时,如果从黑到白,它将是一个大的正数;如果从白到黑,它将是一个大的负数。如果我们用 abs
删除所有负值,这意味着无论符号是什么,我们都会将其视为一个大的正值,因此无论如何我们都应该能够检测到跳跃。因此,你应该做的是:
[~,ind] = max(abs(diff(avgs)));
现在,您所要做的就是显示此图像,然后在该位置所在的位置画一条线:
figure;
imshow(AR);
hold on;
plot([1 size(AR,2)], [ind ind], 'r', 'LineWidth', 2);
我将线条的粗细设置为 2 个像素,以便您可以清楚地看到线条,并且我将其设置为红色。这就是我们得到的:
因此,如果您想将其复制并粘贴到 MATLAB 中以供您 运行,请使用以下代码:
avgs = mean(AR(1:315,:), 2);
[~,ind] = max(abs(diff(avgs)));
figure;
imshow(AR);
hold on;
plot([1 size(AR,2)], [ind ind], 'r', 'LineWidth', 2);