如何根据矩阵值检测图像的一部分?

时间:2017-06-12 18:26:47

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

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

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

我在包含绘图值的matrix named Slant上应用以下代码。

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

正如我可以看到的那样,我对我不想要的值进行了硬编码。是否有任何方法可以检测某些矩阵值,同时使其余值等于零?

我使用了另一种小算法,从矩阵中取出一半的最大值并将其设置为零。但这对其他图像不起作用。

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

Slope Image

2 个答案:

答案 0 :(得分:1)

想法:使用霍夫变换:

首先,最好只创建一个只有我们感兴趣的行和列的新矩阵。

为了应用matlab内置的hough,我们必须创建一个二进制图像:由于该行的值总是低于其余的值,我们可以例如确定图片中亮度的最低四分位数(使用quantile,并将其设置为白色,其他一切设置为黑色。

然后,为了找到该行,我们可以直接在该BW图像上使用hough

答案 1 :(得分:1)

这是另一个建议:

  1. 删除所有背景。
  2. 假设此“行”导致数据的双峰分布(删除零后),找到较低的模式。
  3. 假设线的值始终低于背景值,请应用一个逻辑掩码,设置为将所有值置于最小值+ 2nd_mode之上,如下图所示(红色圆圈):
  4. line_hist

    以下是它的工作原理:

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

    现在我们有A,如下所示:

    A

    [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
    

    我们得到result

    result

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

    [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
    

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

    interp_line

    现在我们想让这条线变得更粗,就像数据中的线一样,所以我们采用厚度模式(通过计算每列中的值,你可能想要取max),并且将这一因素“扩大”到双方的一半:

    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
    

    现在result看起来像这样:

    inter and thick