使用Matlab从图像中的指定行向上扫描,基于强度变化检测新区域

使用Matlab从图像中的指定行向上扫描,基于强度变化检测新区域,matlab,image-processing,image-segmentation,scanning,Matlab,Image Processing,Image Segmentation,Scanning,以下是我正在处理的图像类型: 您可以看到我使用以下代码绘制的粉红色线: 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'); t

以下是我正在处理的图像类型:

您可以看到我使用以下代码绘制的粉红色线:

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)向上扫描到图像的第一行,以检测暗区域,一旦检测到该区域,我希望在暗区域的中点绘制另一条线,类似于第一条线(整个图像)


我希望这样做的原因是,一旦检测到这两个区域的中点,我希望从这两条线中获得统计信息,例如标准偏差和平均值,以尝试处理这两个线段,为周围的行或线段提供一个总体平均值

乔纳斯几乎告诉过你如何解决这个问题。然而,因为我喜欢玩图像,我决定写一个答案。我要做的是从第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行的平均值,第二个元素是第2行的平均值,依此类推。如果我们在普通图上绘制这些平均值,其中行号是横轴,平均强度是纵轴,这就是我们得到的结果:

plot(1:315, avgs);

正如你所看到的,在250处有一个明显的尖峰,在我设计的图像中,在第250行的右边是我使灰色方块出现的地方。我们可以通过结合计算数组中元素之间的成对距离来确定该峰值出现的位置
diff
工作时,第一个输出是第二个元素减去第一个,然后第二个元素是第三对减去第二个,依此类推。在这种情况下,因为我们正在从低向高过渡,这意味着无论什么位置给我们最大的差异,都意味着我们从右(或边的最高值)到左取一个数字(或边的最小值。因此,我们找到两两距离并确定两两距离可能最大的点。因此,执行以下操作:

[~,ind] = max(diff(avgs));
max
的好处在于,如果数据中有多个值共享同一个最大值,我们只返回第一个出现的值。这很好,因为一旦我们在绘图中检测到峰值,我们会立即找到这个结果。如果你做得正确,
ind
应该是250

我要注意的一点是,上面的语法假设您正在从黑色过渡到白色。如果您有相反的行为,您可能希望查看使用
min
,或者如果您希望这与您正在经历的渐变类型无关,请将
max
abs。这样,当我们找到最大的差异时,如果从黑到白,它将是一个大的正数,如果从白到黑,它将是一个大的负数。如果我们用
abs
删除所有的负值,这意味着无论符号是什么,我们都会将其视为一个大的正值,因此we应该能够检测到跳转。因此,您应该做的是:

[~,ind] = max(abs(diff(avgs)));
现在,您只需显示此图像,然后在此位置绘制一条直线:

figure;
imshow(AR);
hold on;
plot([1 size(AR,2)], [ind ind], 'r', 'LineWidth', 2);
我将线条的厚度设为2个像素,这样你可以清楚地看到线条,我将它设为红色。这是我们得到的:

plot(1:315, avgs);


因此,如果您想将其复制并粘贴到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);

你能提供原始图像而不是图像的截图吗?为什么不沿着维度2求和(或求平均值),然后在强度分布中找到较大的变化?另外,如果你只想给每个区域一个平均值,你可能需要研究各向异性扩散,这将“均匀化”在保留边缘的同时保留区域。哇!@rayryeng感谢您的帮助,非常感谢!令人印象深刻的东西。@SeánMcNeill-没问题。Ta:)继续提问,小心!@SeánMcNeill-我已经使代码更容易复制并粘贴到MATLAB中。我已经将所有代码放在帖子底部的一块中。