【问题标题】:Using Matlab's computer vision toolbox to count specific objects within another object使用 Matlab 的计算机视觉工具箱计算另一个对象中的特定对象
【发布时间】:2016-07-21 04:39:04
【问题描述】:

我有两个独立的图像,它们都来自同一个起始图像。我想基本上将两者重叠并计算一个图像中有多少个圆圈落在第二个图像中的每个较大圆圈内:以下是我正在谈论的一些图像:

小圈子:-


更大的圈子:-

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

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

【问题讨论】:

  • 你在圆圈的质心上试过pdist2吗?黑圈必须完全在红圈内,还是部分地?
  • @beaker 他们通常会完全在圈子内。 pdist2 也会对这两个图像采取行动吗?我不知道我是否完全理解它是如何工作的——它似乎有点低效,因为它似乎计算了每个 dist。
  • 我将编写一些快速代码来向您展示我在说什么。我们只想比较每个圆圈的一个点。
  • @beaker 我刚刚注意到,如果坐标矩阵的大小不同,它就不起作用,这有什么办法吗?也感谢您的帮助!
  • 什么不行,pdist2pdist2 适用于不同大小的矩阵(只要它们具有相同的列数),但是我在 Octave 上并且存在一些差异。 MATLAB 文档还说,参数可以有不同的行数...mx 行用于Xmy 行用于Y

标签: image matlab image-processing overlay


【解决方案1】:

好的,这是加快我认为您正在做的事情的简单方法。 (有更快的方法,但当然它们更复杂一些。)

% 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 找出每个红点中有多少个黑点。 (您也可以使用较新的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

【讨论】:

  • 我对@9​​87654341@ 有点困惑。该矩阵中的那些究竟代表什么? (我知道它们对于某个半径大小是合乎逻辑的)但是有没有办法指定每个较大圆圈中的点数 - (确定有两个圆圈包含一个点)。这太棒了,而且它的代码比我所拥有的要简洁得多——我只是没有完全理解 connectedDots 中包含的信息。
  • sum(connectedDots, 2) 将为您提供每个红点中黑点的数量。我将添加更多关于 connectedDots 的实际含义的解释。
  • @Sam 我想到了一个替代实现,如果你有兴趣,它可能会稍微快一点。
  • 我很想看看。
  • @Sam 你去。我怀疑除非你有很多点,否则它会在计算时间上有很大的不同,但这是看待问题的另一种方式。
猜你喜欢
  • 2011-09-13
  • 2014-09-22
  • 2015-01-30
  • 1970-01-01
  • 2014-07-02
  • 2013-05-07
  • 1970-01-01
  • 2013-12-11
  • 2021-10-10
相关资源
最近更新 更多