如何检测以下图像中的黑点? (我只粘贴一个测试图像,使问题看起来很紧凑。可以找到更多图像→here←)。
如上所示,背景颜色大致为蓝色,点颜色为"黑色"。如果选择一个黑色像素并测量其RGB颜色,则值可以是(0,44,65)或(14,69,89)....因此,我们无法设置告诉像素的范围是黑点或背景的一部分。
我测试了10张不同颜色的图像,但我希望我能找到一种方法来检测可能由三种或更多颜色组成的更复杂背景中的黑点,只要人眼可以轻松识别黑点。可以省略一些非常小或模糊的点。
上个月,我在stackoverflow上问了a similar question,但是还没有一个完美的解决方案,但是有一些很好的答案。如果您有兴趣,请详细了解我的工作。
以下是我尝试的方法:
转换为灰度或图像亮度。难点在于我找不到自适应阈值来进行二值化。显然,将彩色图像转换为灰度或使用亮度(HSV)将失去许多有用的信息。计算自适应阈值的Otsu algorithm也不起作用。
计算RGB直方图。在我的上一个问题中, natan 的方法是通过直方图估计黑色。节省时间,但自适应阈值也是一个问题。
聚类即可。我尝试了k-means clustering,发现它对于只有一种颜色的背景非常有效。缺点(参见我自己的答案)是我需要提前设置聚类中心的数量,但我不知道背景是怎样的。更重要的是,它太慢了!我的应用是在iPhone上实时捕捉,现在它可以使用k-means每秒处理7~8帧(我认为20 FPS是好的)。
我认为不仅相似的颜色而且相邻的像素应该是#34;聚集的#34;或"合并"为了提取黑点。请指导我解决问题的正确方法。任何建议或算法将不胜感激。没有免费的午餐,但我希望在成本和准确性之间做出更好的平衡。
答案 0 :(得分:12)
通过使用rgb2hsv
转换为HSV色彩空间,然后在价值渠道上使用图像处理工具箱函数imopen
和imregionalmin
,我能够获得一些非常好的第一遍结果:
rgb = imread('6abIc.jpg');
hsv = rgb2hsv(rgb);
openimg = imopen(hsv(:, :, 3), strel('disk', 11));
mask = imregionalmin(openimg);
imshow(rgb);
hold on;
[r, c] = find(mask);
plot(c, r, 'r.');
结果图像(问题中的图像和链接中的图像):
您可以看到一些误报和错过的点,以及一些用多个点标记的点,但是一些改进(例如修改打开步骤中使用的结构元素)可以清除这些点。< / p>
答案 1 :(得分:7)
我很高兴用我的旧版2d peak finder code测试图片没有任何阈值或任何颜色考虑因素,你认为真的粗糙吗?
im0=imread('Snap10.jpg');
im=(abs(255-im0));
d=rgb2gray(im);
filter=fspecial('gaussian',16,3.5);
p=FastPeakFind(d,0,filter);
imagesc(im0); hold on
plot(p(1:2:end),p(2:2:end),'r.')
我使用的代码是一个简单的2D局部最大值查找器,有一些误报,但总而言之,它捕获了大多数点而没有重复。我使用的滤镜是2d高斯宽度和标准,类似于典型的blob(最好的是为您的问题获得匹配的滤镜)。 处理颜色的更复杂版本(rgb2hsv?)可以进一步改善这一点......
答案 2 :(得分:3)
这是一个非常简化的版本,可以扩展为全RGB,也不使用图像处理库。基本上,您可以使用滤镜图像(这是您要查找的点的示例)进行二维卷积,并且从卷积返回最高值的点开始,这些点是点的最佳匹配。那么你当然可以达到门槛。这是一个简单的二进制图像示例。
%creating a dummy image with a bunch of small white crosses
im = zeros(100,100);
numPoints = 10;
% randomly chose the location to put those crosses
points = randperm(numel(im));
% keep only certain number of points
points = points(1:numPoints);
% get the row and columns (x,y)
[xVals,yVals] = ind2sub(size(im),points);
for ii = 1:numel(points)
x = xVals(ii);
y = yVals(ii);
try
% create the crosses, try statement is here to prevent index out of bounds
% not necessarily the best practice but whatever, it is only for demonstration
im(x,y) = 1;
im(x+1,y) = 1;
im(x-1,y) = 1;
im(x,y+1) = 1;
im(x,y-1) = 1;
catch err
end
end
% display the randomly generated image
imshow(im)
% create a simple cross filter
filter = [0,1,0;1,1,1;0,1,0];
figure; imshow(filter)
% perform convolution of the random image with the cross template
result = conv2(im,filter,'same');
% get the number of white pixels in filter
filSum = sum(filter(:));
% look for all points in the convolution results that matched identically to the filter
matches = find(result == filSum);
%validate all points found
sort(matches(:)) == sort(points(:))
% get x and y coordinate matches
[xMatch,yMatch] = ind2sub(size(im),matches);
我强烈建议您查看MATLAB网站上的conv2文档。