使用 Matlab 的计算机视觉工具箱计算另一个对象中的特定对象

Using Matlab's computer vision toolbox to count specific objects within another object

我有两个独立的图像,它们都来自同一个起始图像。我想基本上将两者叠加起来,并计算第二张图片中每个较大圆圈中有多少张图片中的圆圈:以下是我所说的一些图片:

小圆圈:-


大圆圈:-

理想情况下,我能够跟踪每个较大的圆圈,并用一定数量的较小嵌套圆圈对其进行标记。到目前为止,我已经尝试使用较大圆圈的半径,并根据坐标逐一检查所有内容。

这似乎非常昂贵,我想知道是否有更好的方法。

好的,这里有一个简单的方法可以加快我认为你正在做的事情。 (有更快的方法,但当然它们有点复杂。)

% Get the statistics for redDots.jpg
img = imread('redDots.jpg');   % You should really use a lossless image format like .png
gimg = rgb2gray(img);          % Convert to grayscale
bwimg = im2bw(gimg, .5);       % Convert to bw image (guessing at the threshold)
bwimg = ~bwimg;                % Invert the bw image so dots are white
stats = regionprops(bwimg);    % Find statistics of dots (centroid, area, bounding box)
redCentroids = reshape([stats(:).Centroid], 2, []).';   % Put centroids in format for pdist2

% Repeat the same basic procedure for blackDots.jpg
img2 = imread('blackDots.jpg');
bwimg2 = im2bw(img2, .5);      % blackDots.jpg is alread bw image
bwimg2 = ~bwimg2;
stats2 = regionprops(bwimg2);
blackCentroids = reshape([stats2(:).Centroid], 2, []).';

distMatrix = pdist2(redCentroids, blackCentroids);
radius = 38;                   % found from stats.BoundingBox
connectedDots = distMatrix < radius;

这只会生成一个数组,其中包含每个红点的质心,另一个数组包含每个黑点的质心。然后它使用pdist2计算每个红点和每个黑点之间的距离。

regionprops 也给了你边界框,所以我只是手动检查它以获得红点的直径并对半径进行硬编码。红点半径内的任何黑点都在里面。这是我的测试 运行:

connectedDots 的值
connectedDots =

   1   1   1   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   1   1   1   1   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   0   1   1

connectedDots矩阵中,每一行代表一个红点。每列代表一个黑点。因此,对于每一行,对应于该行的红点内的每个黑点都有一个 1。 (如果想知道是哪一个,可以回到stats结构看stats(rownumber).Centroid。)

求每个红点中黑点的个数,那么,你做:

>> sum(connectedDots,2)
ans =

   6
   2
   4
   3
   2
   1
   1
   4

替代方法

此方法通过将带有红点的图像转换为标记图像来避免 pdist2。然后,当我们找到黑点的质心坐标时,我们只需检查标记图像上的那些坐标(实际上是索引),看看那里有什么。这样,我们不必将每个红色质心与每个黑色质心 (O(n*m)) 进行比较,而只需检查每个黑色质心 (O(m)) 的值。最后我们用histc to find out how many black dots are in each red dot. (You could also use the newer histcounts.)

% Process the black dot image the same way as before
imgB = imread('blackDots.jpg');
bwimgB = im2bw(imgB, .5);
bwimgB = ~bwimgB;
statsB = regionprops(bwimgB);
% This time round to get integer subscripts
blackCentroids = round(reshape([statsB(:).Centroid], 2, []).');
% Get the corresponding indices... 
% Centroids are in (x,y) order instead of (row,col)
centroidIdx = sub2ind(size(imgB), blackCentroids(:,2), blackCentroids(:,1));

% Convert red dot image to bwimg as before
img = imread('redDots.jpg');
gimg = rgb2gray(img);
bwimg = im2bw(gimg, .5);
bwimg = ~bwimg;
% Instead of getting centroids, convert to labeled image
redLabelImage = bwlabel(bwimg);   % Label the connected components (red dots)

dotLocations = redLabelImage(centroidIdx);   % Get the label at each index
dotCounts = histc(dotLocations, 1:max(redLabelImage(:)))   % Count them up

结果:

dotCounts =

   6
   2
   4
   3
   2
   1
   1
   4