使用 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
我有两个独立的图像,它们都来自同一个起始图像。我想基本上将两者叠加起来,并计算第二张图片中每个较大圆圈中有多少张图片中的圆圈:以下是我所说的一些图片:
小圆圈:-
大圆圈:-
理想情况下,我能够跟踪每个较大的圆圈,并用一定数量的较小嵌套圆圈对其进行标记。到目前为止,我已经尝试使用较大圆圈的半径,并根据坐标逐一检查所有内容。
这似乎非常昂贵,我想知道是否有更好的方法。
好的,这里有一个简单的方法可以加快我认为你正在做的事情。 (有更快的方法,但当然它们有点复杂。)
% 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