在下面绘制的二维数组中,我们有兴趣找到“块状”区域。如您所见,它不是连续图。此外,我们知道“肿块”区域的大致尺寸。下面给出一组数据。第一列包含 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/