如何根据强度值创建蒙版或检测图像部分?

时间:2017-06-29 22:50:07

标签: algorithm matlab image-processing matrix matlab-figure

我有一个名为figmat的矩阵,我从中获得了以下pcolor图(Matlab-Version R 2016b)。

基本上我只想从这个图中提取底部红色高强度线。

我想过以某种方式从矩阵中提取最大值并在主矩阵上创建某种掩码。但我不了解实现这一目标的可行方法。可以借助任何边缘/图像检测算法来完成吗?

我正在尝试使用以下代码创建一个掩码

A=max(figmat);
figmat(figmat~=A)=0;
imagesc(figmat);

但是这只给出了最大值的边界。我还需要整个红色带。

pcolor plot

2 个答案:

答案 0 :(得分:3)

好吧,我假设红线是线性的,它的值可以唯一地与图片的其余部分分开。让我们生成一些测试数据......

[x,y] = meshgrid(-5:.2:5, -5:.2:5);
n = size(x,1)*size(x,2);
z = -0.2*(y-(0.2*x+1)).^2 + 5 + randn(size(x))*0.1;
figure
surf(x,y,z);

此脚本生成表面函数。其最大值(x,y)的集合可以用线性函数y = 0.2 * x + 1来描述。我为它添加了一点噪音,使其更加真实。

Test Data

我们现在选择z小于,比如说最大值的95%的所有点。因此可以使用find。后来,我们想要使用一维数据,所以我们reshape一切。

thresh = min(min(z)) + (max(max(z))-min(min(z)))*0.95;
mask = reshape(z > thresh,1,n);
idx = find(mask>0);
xvec = reshape(x,1,n);
yvec = reshape(y,1,n);

xvecyvec现在包含所有值的坐标>脱粒。

Filtered points

最后一步是在所有点上做一些线性多项式。

pp = polyfit(xvec(idx),yvec(idx),1)

pp =

    0.1946    1.0134

显然,这些应该是y = 0.2 * x + 1的系数。

Fitted line

我不知道,如果这也适用于您的数据,因为我做了一些假设。必须仔细选择阈值水平。如果您真的想自动处理图像,可能必须进行一些预处理以动态检测此级别。可能还有一种更简单的方法可以做到这一点......但对我来说,这个方法很简单,不需要任何工具箱。

答案 1 :(得分:2)

假设:

  1. 只有一个乐队可以提取。
  2. 它始终具有最大值。
  3. 是线性的。
  4. 我也可以对这个案例采用my previous answer,只做一些小改动:

    首先,我们得到矩阵中值的分布,并在顶部值中查找可以与较小值区分的总体。这是通过在柱状图上找到最大值x(i)来完成的:

    1. 是本地最大值(其仓位高于x(i+1)x(i-1)
    2. 其上方的值多于其中的值(箱子的高度x(i+1)x(end)的高度之和<箱子的高度x):
    3. 这是如何完成的:

      [h,x] = histcounts(figmat); % get the distribution of intesities
      d = diff(fliplr(h)); % The diffrence in bin height from large x to small x
      band_min_ind = find(cumsum(d)>size(figmat,2) & d<0, 1); % 1st bin that fit the conditions
      flp_val = fliplr(x); % the value of x from large to small
      band_min = flp_val(band_min_ind); % the value of x that fit the conditions
      

      现在我们继续像往常一样。屏蔽所有不需要的值,插入线性线:

      mA = figmat>band_min; % mask all values below the top value mode
      [y1,x1] = find(mA,1); % find the first nonzero row 
      [y2,x2] = find(mA,1,'last'); % find the last nonzero row
      m = (y1-y2)/(x1-x2); % the line slope
      n = y1-m*x1; % the intercept
      f_line = @(x) m.*x+n; % the line function
      

      如果我们绘制它,我们可以看到用于检测的波段的红线:

      line a

      接下来,我们可以使这条线更粗,以更好地表示这一行:

      thick = max(sum(mA)); % mode thickness of the line
      tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
      rows = bsxfun(@plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each column
      rows(rows<1) = 1; % make sure to not get out of range
      rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
      inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
      mA(inds) = true; % add the interpolation to the mask
      result = figmat.*mA; % apply the mask on figmat
      

      最后,我们可以在屏蔽后绘制该结果,排除不需要的区域:

      imagesc(result(any(result,2),:))
      

      line b