检测2D阵列中的块区域

时间:2012-07-11 01:47:50

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

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

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

1 个答案:

答案 0 :(得分:7)

这可能只是巧合,但你表现出的肿块看起来相当抛物线。通过“了解肿块区域的大致尺寸”并不完全清楚你的意思,但是如果你的意思是你大致知道它有多宽(即它占用多少x轴),你可以简单地滑动一个窗口沿着x轴的那个宽度,并且对于在每个点处适合窗口的所有数据进行抛物线拟合(也称为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:

Data plot with lump fit drawn in

<强>注释:

我选择使用拟​​合抛物线与每个窗口内的原始数据之间的均方误差作为质量度量,而不是由于懒惰而比相关系数(r ^ 2值)更重要。我认为结果与其他方式不同。

输出严重依赖于为二次系数选择的阈值(参见循环结束时的bestMSE条件)。说实话,我在这里通过输出每个点的拟合系数来欺骗,然后根据已知的肿块形状选择阈值。这相当于使用@chaohuang建议的块模板,并且可能不是非常强大,具体取决于数据中预期的方差。

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

Best fit is not a "lump"

一个改进是添加一个检查,拟合抛物线在窗口间隔内至少有一个最大值(也就是说,检查窗口中的一阶导数是否为零,这样我们至少可以找到沿曲线的局部最大值) 。仅仅这一点是不够的,因为你仍然可能有一个比一个“明显的”大块更适合抛物线的小块,如给定的数据集所示。