matlab - 检测二维阵列中的 block 状区域

标签 matlab image-processing computer-vision computational-geometry robotics

在下面绘制的二维数组中,我们有兴趣找到“ block 状”区域。如您所见,它不是连续图。此外,我们知道“肿 block ”区域的大致尺寸。下面给出一组数据。第一列包含 y 值,第二列包含 x 值。关于如何检测这样的肿 block 区域有什么建议吗?

enter image description here

   21048        -980
   21044        -956
   21040        -928
   21036        -904
   21028        -880
   21016        -856
   21016        -832
   21016        -808
   21004        -784
   21004        -760
   20996        -736
   20996        -712
   20992        -684
   20984        -660
   20980        -636
   20968        -612
   20968        -588
   20964        -564
   20956        -540
   20956        -516
   20952        -492
   20948        -468
   20940        -440
   20936        -416
   20932        -392
   20928        -368
   20924        -344
   20920        -320
   20912        -296
   20912        -272
   20908        -248
   20904        -224
   20900        -200
   20900        -176
   20896        -152
   20888        -128
   20888        -104
   20884         -80
   20872         -52
   20864         -28
   20856          -4
   20836          16
   20812          40
   20780          64
   20748          88
   20744         112
   20736         136
   20736         160
   20732         184
   20724         208
   20724         232
   20724         256
   20720         280
   20720         304
   20720         328
   20724         352
   20724         376
   20732         400
   20732         424
   20736         448
   20736         472
   20740         496
   20740         520
   20748         544
   20740         568
   20736         592
   20736         616
   20736         640
   20740         664
   20740         688
   20736         712
   20736         736
   20744         760
   20748         788
   20760         812
   20796         836
   20836         860
   20852         888
   20852         912
   20844         936
   20836         960
   20828         984
   20820        1008
   20816        1032
   20820        1056
   20852        1080
   20900        1108
   20936        1132
   20956        1156
   20968        1184
   20980        1208
   20996        1232
   21004        1256
   21012        1280
   21016        1308
   21024        1332
   21024        1356
   21028        1380
   21024        1404
   21020        1428
   21016        1452
   21008        1476
   21004        1500
   20992        1524
   20980        1548
   20956        1572
   20944        1596
   20920        1616
   20896        1640
   20872        1664
   20848        1684
   20812        1708
   20752        1728
   20664        1744
   20640        1768
   20628        1792
   20628        1816
   20620        1836
   20616        1860
   20612        1884
   20604        1908
   20596        1932
   20588        1956
   20584        1980
   20580        2004
   20572        2024
   20564        2048
   20552        2072
   20548        2096
   20536        2120
   20536        2144
   20524        2164
   20516        2188
   20512        2212
   20508        2236
   20500        2260
   20488        2280
   20476        2304
   20472        2328
   20476        2352
   20460        2376
   20456        2396
   20452        2420
   20452        2444
   20436        2468
   20432        2492
   20432        2516
   20424        2536
   20420        2560
   20408        2584
   20396        2608
   20388        2628
   20380        2652
   20364        2676
   20364        2700
   20360        2724
   20352        2744
   20344        2768
   20336        2792
   20332        2812
   20328        2836
   20332        2860
   20340        2888
   20356        2912
   20380        2940
   20428        2968
   20452        2996
   20496        3024
   20532        3052
   20568        3080
   20628        3112
   20652        3140
   20728        3172
   20772        3200
   20868        3260
   20864        3284
   20864        3308
   20868        3332
   20860        3356
   20884        3384
   20884        3408
   20912        3436
   20944        3464
   20948        3488
   20948        3512
   20932        3536
   20940        3564

最佳答案

这可能只是巧合,但您显示的肿 block 看起来很像抛物线。目前还不完全清楚你所说的“知道 block 区域的近似尺寸”是什么意思,但如果你的意思是你知道它大约有多宽(即它占据了多少 x 轴),你可以简单地滑动一个窗口沿 x 轴的那个宽度,并对在每个点适合窗口的所有数据进行抛物线拟合(也称为 2 阶多边形拟合)。然后,计算每个点的 r^2 拟合优度值,r^2 最接近 1.0 的点将是最佳拟合。您可能需要一个阈值并丢弃那些 x^2 系数为正的值(以找到 block 而不是凹陷)以保持理智,但这可能是一种可行的方法。

即使抛物线看起来是巧合,我认为这也是一种合理的方法——根据我能想到的任何定义,向下的抛物线是对一般“ block ”的一个很好的描述。

编辑:下面尝试实现

我很好奇并继续实现我提出的解决方案(稍作修改)。首先,这是代码(丑陋但实用):

function [x, p] = find_lump(data, width)

  n = size(data, 1);

  f = plot(data(:,1),data(:,2), 'bx-');
  hold on;

  bestX = -inf;
  bestP = [];
  bestMSE = inf;
  bestXdat = [];
  bestYfit = [];

  spanStart = 0;
  spanStop = 1;
  spanWidth = 0;

  while (spanStop < n)
    if (spanStart > 0)
      % Drop first segment from window (since we'll advance x):
      spanWidth = spanWidth - (data(spanStart + 1, 1) - x);
    end

    spanStart = spanStart + 1;
    x = data(spanStart, 1);

    % Advance spanStop index to maintain window width:
    while ((spanStop < n) && (spanWidth <= width))
      spanStop = spanStop + 1;
      spanWidth = data(spanStop, 1) - x;
    end

    % Correct for overshoot:
    if (spanWidth > width) 
      spanStop = spanStop - 1;
      spanWidth = data(spanStop, 1) - x;
    end

    % Fit parabola to data in the current window:
    xdat = data(spanStart:spanStop, 1);
    ydat = data(spanStart:spanStop, 2);
    p = polyfit(xdat, ydat, 2);

    % Compute fit quality (mean squared error):
    yfit = polyval(p,xdat);
    r = yfit - ydat;
    mse = (r' * r) / size(xdat,1);

    if ((p(1) < -0.002) && (mse < bestMSE))
      bestMSE = mse;
      bestX = x;
      bestP = p;
      bestXdat = xdat;
      bestYfit = yfit;
    end
  end

  x = bestX;
  p = bestP;

  plot(bestXdat,bestYfit,'r-');

...这是使用给定数据的结果(我交换了列,因此第 1 列是 x 值,第 2 列是 y 值),窗口宽度参数为 750:

Data plot with lump fit drawn in

评论:

我选择使用拟​​合抛物线和每个窗口内的原始数据之间的均方误差作为质量指标,而不是由于懒惰而不是相关系数(r^2 值)。我不认为结果会有很大不同。

输出在很大程度上取决于为二次系数选择的阈值(请参阅循环末尾的最佳 MSE 条件)。说实话,我在这里通过输出每个点的拟合系数来作弊,然后根据已知的 block 形状选择阈值。这相当于使用@chaohuang 建议的 block 状模板,并且可能不是很稳健,具体取决于数据中的预期方差。

请注意,如果使用这种方法,某种形状控制参数似乎是必要的。原因是任何随机(平滑)的数据运行都可以很好地拟合某些抛物线,但不一定在最大值附近。这是我将阈值设置为零的结果,因此仅将拟合限制为指向下方的抛物线:

Best fit is not a "lump"

一个改进是添加一个检查,以确保拟合抛物线至少在窗口区间内具有最大值(即,检查一阶导数是否在窗口内变为零,以便我们至少找到沿曲线的局部最大值) .仅此一点是不够的,因为在给定的数据集中,您可能仍然有一个比“明显”的大块更适合抛物线的小块。

关于matlab - 检测二维阵列中的 block 状区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11424438/

相关文章:

python - 使用 ffmpeg 和 python 2.7 在 Fedora 26 25 24 23 或 22 上安装 OpenCV 2.4.13 或 3.x 时出现 VideoCapture 不工作错误

python - 如何仅使用python中的云视觉api检测特定语言而忽略其他语言?

python - 从 CVX 到 CVXPY 或 CVXOPT

Matlab:复制和乘以两个向量的最快方法

带 bsxfun 的结束循环的 matlab 复合体

c++ - 外部库的 undefined reference (C++、QT、Ubuntu 14、CCV)

python - Matlab 谱图和 matplotlib 谱图之间的区别?

image - 为 4 channel 图像中的对象添加填充

java - 非法状态异常 : getOutputStream() has already been called for this response on retrieving image

image - 将 RGB 转换为 sRGB?