我有一个名为figmat
的矩阵,我从中获得了以下pcolor
图(Matlab-Version R 2016b)。
基本上我只想从这个图中提取底部红色高强度线。
我想过以某种方式从矩阵中提取最大值并在主矩阵上创建某种掩码。但我不了解实现这一目标的可行方法。可以借助任何边缘/图像检测算法来完成吗?
我正在尝试使用以下代码创建一个掩码
A=max(figmat);
figmat(figmat~=A)=0;
imagesc(figmat);
但是这只给出了最大值的边界。我还需要整个红色带。
答案 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来描述。我为它添加了一点噪音,使其更加真实。
我们现在选择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);
xvec
和yvec
现在包含所有值的坐标>脱粒。
最后一步是在所有点上做一些线性多项式。
pp = polyfit(xvec(idx),yvec(idx),1)
pp =
0.1946 1.0134
显然,这些应该是y = 0.2 * x + 1的系数。
我不知道,如果这也适用于您的数据,因为我做了一些假设。必须仔细选择阈值水平。如果您真的想自动处理图像,可能必须进行一些预处理以动态检测此级别。可能还有一种更简单的方法可以做到这一点......但对我来说,这个方法很简单,不需要任何工具箱。
答案 1 :(得分:2)
假设:
我也可以对这个案例采用my previous answer,只做一些小改动:
首先,我们得到矩阵中值的分布,并在顶部值中查找可以与较小值区分的总体。这是通过在柱状图上找到最大值x(i)
来完成的:
x(i+1)
和x(i-1)
)x(i+1)
与x(end)
的高度之和<箱子的高度x
):这是如何完成的:
[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
如果我们绘制它,我们可以看到用于检测的波段的红线:
接下来,我们可以使这条线更粗,以更好地表示这一行:
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),:))