首页 > 解决方案 > 图像上的点密度

问题描述

我有两张表面上有多个点的图像

在此处输入图像描述

如何估计图像上这些点的密度,然后将它们与另一个具有不同点浓度的图像进行比较?我想知道在什么图像中点的密度更大。

我试图用 Emgu CV 做到这一点,但没有找到任何方法。

标签: c#opencvimage-processingemgucv

解决方案


有多种方法可以解决这个问题。

下面我使用 MATLAB 和DIPimage来演示这些方法。我不知道 C#,但 OpenCV(以及 EmguCV)有足够的方法来实现 #1 和 #2,尽管可能不像使用 DIPlib 那样容易。

所有演示都使用像素作为单位,如果您记录了适当的像素大小,您应该使用它来导出物理单位的距离和密度。

1.检测点和计数

精确地检测这些点并非易事,但要估计密度,我们不需要非常精确,一些失误就可以了。拉普拉斯高斯滤波器是理想的,输出中局部最大值的数量大约对应于图像中的点数。

img = readim('https://i.stack.imgur.com/TNj3p.jpg');
img = img{1}; % just one channel, all three are identical

% Approach 1: detect and count
dots = laplace(img, 3); % find the right filter size, depending on the noise in the image
dots = maxima(dots, 2);
overlay(img, dots) % display
density = max(label(dots)) / numel(img) % dots/pixel, use physical dimensions if known.

检测到的点

估计的密度为每像素 0.0065 个点。

2.傅里叶分析

这可能是最稳健的方法。我们将汉明窗函数应用于图像以避免边缘效应(任何窗函数都可以做得很好),计算离散傅里叶变换(使用 FFT),并取其大小。这将显示一个整齐的环,其大小由点的密度决定。接下来,我们计算每个半径(到原点的距离)的平均值,忽略前几个 bin(这些由窗口函数控制),并找到峰值。

F = abs(ft(window(img)));
F = radialmean(F);
F(0:3) = 0; % remove frequencies dominated by windowing function
plot(linspace(0, imsize(F)/2, imsize(F)), F) % display
[~,ii] = max(F);
distance = imsize(F) / ii / 2 % in pixels, use physical dimensions if known.

DFT 幅度的径向平均值

估计距离为 5.78 像素。

3.(半)变异函数

变异函数是一种用于分析空间依赖性的统计工具。我们可以用它来确定点之间的平均距离。

semi = semivariogram(img);
x = semi(:,1);
y = semi(:,2);
plot(x,y) % display
ii = find(maxima(y),1); % the first local maximum is the one we want
distance = x(ii) % in pixels, use physical dimensions if known.

半变异函数

半变异函数在进入固定趋势(基台)之前有一个小峰值。在这种情况下,峰值位于 7 个像素处。我认为如果我们在寻找峰值之前对半变异函数应用一个小的高斯平滑,结果可能会更加稳健。


推荐阅读