【问题标题】:Detect black dots from color background从彩色背景中检测黑点
【发布时间】:2014-07-22 20:19:13
【问题描述】:

我的简短问题

如何检测以下图像中的黑点? (我只贴了一张测试图,让问题看起来紧凑。更多图片可以找到→here←)。

我的长问题

如上图,背景色大致为蓝色,圆点颜色为“黑色”。如果选择一个黑色像素并测量它的RGB颜色,值可以是 (0, 44, 65) 或 (14, 69, 89)....因此,我们不能设置一个范围来告诉像素是黑点或背景的一部分。

我测试了10张不同颜色的图像,但我希望我能找到一种方法来检测可能由三种或更多颜色组成的更复杂背景中的黑点,只要人眼可以轻松识别黑点.一些极小或模糊的点可以省略。

以前的工作

上个月,我在 stackoverflow 上问过a similar question,但还没有得到完美的解决方案,不过有一些很好的答案。如果您有兴趣,请查找有关我的工作的更多详细信息。

以下是我尝试过的方法:

  1. 转换为灰度或图像的亮度。 困难在于我找不到自适应阈值来进行二值化。显然,将彩色图像转换为灰度或使用亮度 (HSV) 会丢失很多有用的信息。计算自适应阈值的Otsu algorithm也不起作用。

  2. 计算 RGB 直方图。在我的最后一个问题中,natan的方法是通过直方图来估计黑色。省时,但自适应阈值也是个问题。

  3. 集群。我试过k-means clustering,发现它对于只有一种颜色的背景非常有效。不足(见我自己的回答)是我需要提前设置聚类中心的数量但我不知道背景会如何。更何况太了!我的应用程序用于在 iPhone 上进行实时捕捉,现在它可以使用 k-means 每秒处理 7~8 帧(我认为 20 FPS 很好)。

总结

我认为不仅相似的颜色而且相邻的像素都应该“聚集”或“合并”以提取黑点。请指导我一个正确的方法来解决我的问题。任何建议或算法将不胜感激。没有免费的午餐,但我希望在成本和准确性之间做出更好的权衡。

【问题讨论】:

标签: algorithm matlab opencv image-processing computer-vision


【解决方案1】:

这是一个非常简化的版本,可以扩展为全RGB,而且它也不使用图像处理库。基本上,您可以使用过滤器图像(这是您正在寻找的点的示例)进行 2-D 卷积,并且从卷积返回最高值的点,是点的最佳匹配。然后,您当然可以设置阈值。这是一个简单的二进制图像示例。

%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 文档。

【讨论】:

    【解决方案2】:

    我很想用我的旧 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 局部最大值查找器,有一些误报,但总而言之,这捕获了大部分点,没有重复。我使用的过滤器是宽度和标准的二维高斯,类似于典型的 blob(最好的方法是为您的问题获得匹配的过滤器)。 处理颜色的更复杂的版本(rgb2hsv?)可以进一步改善这一点......

    【讨论】:

    • 感谢您再次回答我的问题。在接下来的工作中,我会参考您的寻峰器。
    【解决方案3】:

    通过使用rgb2hsv 转换为HSV 颜色空间,然后在值通道上使用图像处理工具箱函数imopenimregionalmin,我能够获得一些相当不错的首过结果:

    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.');
    

    以及生成的图像(对于问题中的图像和从您的链接中选择的图像):

    您可以看到一些误报和遗漏的点,以及一些标有多个点的点,但一些改进(例如修改打开步骤中使用的结构元素)可以清除这些点。

    【讨论】:

    • 非常干净的解决方案,处理最少。我的最爱和 +1。
    • 点赞!从没想过imopen可以做这样的工作。我将在 OpenCV 中实现你的方法。
    • @WangYudong,您可以使用opencv的adaptiveThreshold函数,然后执行形态学打开,得到与此答案大致相同的结果。 hsv 的 v 通道或 Lab 的 l 通道在我测试时效果很好。我认为灰色的效果同样好,但似乎没有那么好
    • @WangYudong,你有机会实现吗?
    猜你喜欢
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 2022-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多