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

   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

最佳答案

这可能只是巧合,但你展示的肿块看起来相当抛物线。 “知道肿块区域的大致尺寸”是什么意思并不完全清楚,但是如果您的意思是您知道它大约有多宽(即它占据了多少 x 轴),您可以简单地滑动一个窗口沿 x 轴的宽度,并对适合窗口中每个点的所有数据进行抛物线拟合(又名 polyfit 度数为 2)。然后,计算每个点的 r^2 拟合优度值,r^2 最接近 1.0 的点将是最佳拟合。为了理智,您可能需要一个阈值并丢弃 x^2 系数为正的那些(以找到肿块而不是下降),但这可能是一种可行的方法。

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

编辑:在 下面尝试实现

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

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:

评论:

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

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

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



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

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

10-10 09:35