如何根据矩阵值检测图像的一部分? [英] How to detect a portion of an image based upon the matrix values?

查看:161
本文介绍了如何根据矩阵值检测图像的一部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Matlab(版本R 2016b)中有一个简单的 pcolor 图,我已经上传,如下图所示。我只需要获得蓝色斜线,它从最左边的中间延伸到最右边的角,而不对矩阵值进行硬编码。



例如:可以看到所需的斜率线的值大约介于 20 来自pcolor图的 45 。 (仅通过查看图表粗略猜测)



我在

解决方案

这是另一个建议:


  1. 删除所有背景。

  2. 假设这个线导致数据的双峰分布(在删除零之后),找到较低的模式。

  3. 假设线的值是总是低于背景,应用一个逻辑掩码,设置为将所有值置于最小+ 2nd_mode之上,如下图所示(红色圆圈):



以下是它的工作原理:

  A = Slant(any(Slant,2),:); %只保存A只有非零数据

现在我们有 A 看起来像这样:



  [y,x] = findpeaks(histcounts(A)); %找到A 
sorted_x = sortrows([x。'y。'], - 2)的直方图中的所有模式; %按高度顺序对它们进行排序
mA = A< min(A(:))+ sorted_x(2,1); %掩码高于第二模式的所有值
result = A. * mA; %在A
上应用掩码

我们得到结果








结果行中有一些洞,因此您可能希望从结果中插入整行。这可以通过索引的简单数学来完成:

  [y1,x1] = find(mA,1); %找到第一个非零行
[y2,x2] = find(mA,1,'last'); %找到最后一个非零行
m =(y1-y2)/(x1-x2);线斜率%b $ b n = y1-m * x1; %截距
f_line = @(x)m。* x + n;行函数

所以我们得到一个行函数 f_line 像这样(下面红色):





现在我们想让这条线更粗,就像数据中的线一样,所以我们采用厚度模式(通过计算每列中的值,你可能想要 max 代替),并将该系数的一半扩展到双方:

  thick = mode(sum(嘛));行的%模式厚度
tmp =(1:thick)-ceil(thick / 2); %helper vector用于扩展
rows = bsxfun(@ plus,tmp。',floor(f_line(1:size(A,2))));每个coloumn
行(行< 1)= 1的所有行的百分比; %确保不超出范围
行(行>大小(A,1))= size(A,1); %确保不超出范围
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); %转换为线性indecies
mA(inds)= 1; %将插值添加到掩码
result = A. * mA; %在A
上应用掩码

现在结果看起来像这样:




I have a simple pcolor plot in Matlab (Version R 2016b) which I have uploaded as shown in the image below. I need to get only the blue sloped line which extends from the middle of the leftmost corner to the rightmost corner without hard-coding the matrix values.

For instance: One can see that the desired slope line has values somewhere approximately between 20 to 45 from the pcolor plot. (From a rough guess just by looking at the graph)

I'm applying the following code on the matrix named Slant which contains the plotted values.

load('Slant.mat');
Slant(Slant<20|Slant>50)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;

As one can see I hard-coded the values which I don't want to. Is there any method of detecting certain matrix values while making the rest equal to zero?

I used an other small algorithm of taking half the maximum value from the matrix and setting it to zero. But this doesn't work for other images.

[maxvalue, row] = max(Slant);
max_m=max(maxvalue);
Slant(Slant>max_m/2)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;

解决方案

Here is another suggestion:

  1. Remove all the background.
  2. Assuming this "line" results in a Bimodal distribution of the data (after removing the zeros), find the lower mode.
  3. Assuming the values of the line are always lower than the background, apply a logic mask that set to zeros all values above the minimum + 2nd_mode, as demonstrated in the figure below (in red circle):

Here is how it works:

A = Slant(any(Slant,2),:); % save in A only the nonzero data

Now we have A that looks like this:

[y,x] = findpeaks(histcounts(A)); % find all the mode in the histogram of A
sorted_x = sortrows([x.' y.'],-2); % sort them by their hight in decendet order
mA = A<min(A(:))+sorted_x(2,1); % mask all values above the second mode
result = A.*mA; % apply the mask on A

And we get the result:


The resulted line has some holes within it, so you might want to interpolate the whole line from the result. This can be done with simple math on the indices:

[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

So we get a line function f_line like this (in red below):

Now we want to make this line thicker, like the line in the data, so we take the mode of the thickness (by counting the values in each column, you might want to take max instead), and 'expand' the line by half of this factor to both sides:

thick = mode(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 coloumn
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) = 1; % add the interpolation to the mask
result = A.*mA; % apply the mask on A

And now result looks like this:

这篇关于如何根据矩阵值检测图像的一部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆