【问题标题】:Grayscale segmentation/feature extraction/blob detection?灰度分割/特征提取/斑点检测?
【发布时间】:2015-07-04 06:29:31
【问题描述】:

我试图找到一个起点,但我似乎找不到正确的答案。我将非常感谢一些指导。我也不知道正确的术语,因此标题。

  1. 我拍了一张背后有黑色背景的包的照片。
  2. 我想提取包,类似于this
  3. 如果可能的话,找到中心,比如this

本质上,我希望能够提取像素块,然后找到中心点。

我知道这是两个独立的问题,但我认为如果有人可以做后者,那么他们就可以做第一个。我正在使用 MATLAB,但想编写自己的代码,而不是使用他们的图像处理函数,如 edge()。我可以使用哪些方法/算法?任何论文/链接都会很好(:

【问题讨论】:

    标签: matlab image-processing feature-detection image-segmentation feature-extraction


    【解决方案1】:

    好吧,假设您的图像仅由黑色背景和其中的一个袋子组成,执行您所要求的操作的一种非常常见的方法是对图像进行阈值处理,然后找到所有白色像素的质心。

    我做了一个谷歌搜索,我能想到的最接近你想要的东西看起来像这样:

    http://ak.picdn.net/shutterstock/videos/3455555/preview/stock-footage-single-blank-gray-shopping-bag-loop-rotate-on-black-background.jpg

    由于某种原因,这张图片是 RGB,尽管它是灰度的,所以我们将把它转换为灰度。我假设你不能使用任何内置的 MATLAB 函数,所以 rgb2gray 已经出局了。尽管rgb2gray 实现了SMPTE Rec. 709 标准,您仍然可以自己实现它。

    读入图像后,您可以对图像进行阈值处理,然后找到所有白色像素的质心。这可以使用find 来确定非零的行和列位置,然后您只需分别找到它们的平均值。一旦我们这样做了,我们就可以显示图像并在质心所在的位置绘制一个红色圆圈。因此:

    im = imread('http://ak.picdn.net/shutterstock/videos/3455555/preview/stock-footage-single-blank-gray-shopping-bag-loop-rotate-on-black-background.jpg');
    %// Convert colour image to grayscale
    im = double(im);
    im = 0.299*im(:,:,1) + 0.587*im(:,:,2) + 0.114*im(:,:,3);
    im = uint8(im);
    
    thresh = 30; %// Choose threshold here
    
    %// Threshold image
    im_thresh = im > thresh;
    
    %// Find non-zero locations
    [rows,cols] = find(im_thresh);
    
    %// Find the centroid
    mean_row = mean(rows);
    mean_col = mean(cols);
    
    %// Show the image and the centroid
    imshow(im); hold on;
    plot(mean_col, mean_row, 'r.', 'MarkerSize', 18);
    

    当我运行上面的代码时,我们得到的是:

    还不错!现在您的下一个问题是处理多个对象的情况。正如您已智能确定的那样,此代码仅检测到一个对象。对于多个对象的情况,我们将不得不做一些不同的事情。您需要做的是通过 ID 识别图像中的所有对象。这意味着我们需要创建一个 ID 矩阵,其中该矩阵中的每个像素表示该对象属于 哪个 对象。之后,我们遍历每个对象 ID 并找到每个质心。这是通过为每个 ID 创建一个掩码、找到该掩码的质心并保存此结果来执行的。这就是所谓的查找connected components

    regionprops 是在 MATLAB 中执行此操作的最常用方法,但由于您想自己实现此功能,我将把您推迟到我不久前写的关于如何找到二进制图像的连通分量的帖子:

    How to find all connected components in a binary image in Matlab?

    请注意,该算法不是最有效的算法,因此可能需要几秒钟,但我相信您不介意等待 :) 所以现在让我们处理多个对象的情况。我还在 Google 上找到了这张图片:

    我们将图像作为正常阈值,然后不同的是执行连通分量分析,然后我们遍历每个标签并找到质心。但是,我要强制执行的另一个约束是,我们将检查在连接组件结果中找到的每个对象的区域。如果它小于某个数字,这意味着对象可能归因于量化噪声,我们应该跳过这个结果。

    因此,假设您将上述链接帖子中的代码放入一个名为 conncomptest 的函数中,该函数具有以下原型:

    B = conncomptest(A);
    

    因此,将引用帖子中的代码放入一个名为conncomptest.m 的函数中,函数头如下:

    function B = conncomptest(A)
    

    其中A 是输入二值图像,B 是 ID 矩阵,您可以这样做:

    im = imread('http://cdn.c.photoshelter.com/img-get2/I0000dqEHPhmGs.w/fit=1000x750/84483552.jpg');
    
    im = double(im);
    im = 0.299*im(:,:,1) + 0.587*im(:,:,2) + 0.114*im(:,:,3);
    im = uint8(im);
    
    thresh = 30; %// Choose threshold here
    
    %// Threshold image
    im_thresh = im > thresh;
    
    %// Perform connected components analysis
    labels = conncomptest(im_thresh);
    
    %// Find the total number of objects in the image
    num_labels = max(labels(:));
    
    %// Find centroids of each object and show the image
    figure;
    imshow(im);
    hold on;
    
    for idx = 1 : num_labels
        %// Find the ith object mask
        mask = labels == idx;
    
        %// Find the area
        arr = sum(mask(:));
    
        %// If area is less than a threshold
        %// don't process this object
        if arr < 50
            continue;
        end
    
        %// Else, find the centroid normally
        %// Find non-zero locations
        [rows,cols] = find(mask);
    
        %// Find the centroid
        mean_row = mean(rows);
        mean_col = mean(cols);
    
        %// Show the image and the centroid
        plot(mean_col, mean_row, 'r.', 'MarkerSize', 18);
    end
    

    我们得到:

    【讨论】:

    • 哥们太棒了!!如果图像中有多个对象怎么办?例如,2 袋。通过查找整个图像,您只能得到一个质心正确吗?如果我想找到每个包的质心,我该怎么做呢?另外,我不介意使用一些内置函数,例如 rgb2gray(),我只是不希望特征提取部分成为单个 MATLAB 函数。
    • @BadProgrammer - 谢谢 :) 是的。一种常见的做法是执行连通分量分析并遍历每个不同的对象并找到其质心。你能用regionprops吗?我还会用形态学进一步扩展这一点。你能用imfill之类的东西吗? imclose?
    • 我可以在技术上使用任何功能。我只是希望能够在可能的情况下纠正自己的问题,因为它可以帮助我了解正在发生的事情。我想如果我有 MATLAB 函数的示例,我可以弄清楚算法是如何工作的,然后再编写自己的。
    • @BadProgrammer - 好的。我只是假设你不能使用任何东西哈哈。不久前,我从第一原理写了一篇关于连接组件的文章,我会推迟到那里了解算法和代码。我将针对多个对象更新我的帖子
    • 说真的,这是我得到的最好的答案。永远。
    【解决方案2】:

    我无意贬低 Ray (@rayryeng) 的出色建议,并且像往常一样,精心制作、推理和说明的答案,但是我注意到您对 Matlab 以外的解决方案感兴趣并且实际上想要开发自己的代码,所以我想为您提供一些额外的选项。

    您可以查看出色的 ImageMagick,它安装在大多数 Linux 发行版中,可用于 OS X、其他优秀的操作系统和 Windows。它包括一个“Connected Components”方法,如果你将它应用到这个图像上:

    像这样在命令行中:

    convert bags.png -threshold 20%                     \
      -define connected-components:verbose=true         \
      -define connected-components:area-threshold=600   \
      -connected-components 8 -auto-level output.png
    

    输出将是:

      Objects (id: bounding-box centroid area mean-color):
      2: 630x473+0+0 309.0,252.9 195140 srgb(0,0,0)
      1: 248x220+0+0 131.8,105.5 40559 srgb(249,249,249)
      7: 299x231+328+186 507.5,304.8 36620 srgb(254,254,254)
      3: 140x171+403+0 458.0,80.2 13671 srgb(253,253,253)
      12: 125x150+206+323 259.8,382.4 10940 srgb(253,253,253)
      8: 40x50+339+221 357.0,248.0 1060 srgb(0,0,0)
    

    显示 6 个对象,每行一个,并给出每个对象的边界框、质心和平均颜色。因此,第 3 行表示一个 299 像素宽 x 231 像素高的框,其左上角距图像左上角 328 度,距左上角 186 像素。

    如果我在边界框内绘制,你可以在这里看到它们:

    质心也会为您列出。

    上面命令的输出图像是这样的,每个形状都显示为不同的灰色阴影。请注意,最暗的已经变成黑色,所以很难看到 - 几乎不可能:-)

    如您所说,如果您希望编写自己的连接组件代码,您可以在我的另一个答案中查看我的代码...here

    无论如何,我希望这会有所帮助,并且您将其视为对 Ray 已经提供的出色答案的补充。

    【讨论】:

    • 谢谢马克!这也是一个很好的方法,我会搞砸。我在此标记@rayreng,因为我还有一个问题,如果你们中的一个人能回答,我将不胜感激。我的总体目标是跟踪袋子/斑点,并在相机移动时通过帧匹配它们。这是我目前的结果:link。您可以看到特征在帧中移动,我想跟踪帧之间的距离变化。但是,由于当物体离开视场时中心点会发生变化,这种方法会起作用吗?我应该使用另一个吗?
    • ehhhhhh - 使用 ImageMagick!
    • @BadProgrammer - 我没有意识到你正在执行的是对象跟踪。不,如果任何对象离开您的视图然后重新进入,此方法将不起作用。您需要添加有关 blob 的其他信息,以便跟踪在进入视图后重新启动。正如您所说,移出框架并重新进入的对象将提供模棱两可的信息,因为如果您只是查看质心本身,您不知道该质心属于哪个对象。我建议您在质心检测之上查看对象跟踪算法。
    • 您可以考虑添加对象的区域和/或颜色,以便在它们离开和重新进入框架时帮助它们与以前的自己重新关联。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2021-05-16
    • 1970-01-01
    • 2013-08-21
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多