灰度segmentation/featureextraction/blob检测?

Grayscale segmentation/feature extraction/blob detection?

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

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

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

我知道这是两个不同的问题,但我想如果有人可以做后者,那么他们也可以做第一个。我正在使用 MATLAB,但想编写自己的代码而不使用他们的图像处理函数,如 edge()。我可以使用什么methods/algorithms?任何 papers/links 都很好 (:

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

我进行了 Google 搜索,我能想到的最接近您想要的内容如下所示:

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

由于某种原因,这张图片是 RGB,尽管它是灰度的,所以我们要把它转换成灰度。我假设您不能使用任何内置的 MATLAB 函数,因此 rgb2gray is out. You can still implement it yourself though as rgb2gray implements the 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 中执行此操作的最常见方法,但是由于您想自己实现它,我将推迟您到我的 post 前一段时间写的关于如何查找二值图像的连通分量:

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

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

上找到了这张图片

我们会像往常一样对图像进行阈值处理,然后不同之处在于执行连通分量分析,然后我们遍历每个标签并找到质心。但是,我要强制执行的另一个约束是我们要检查在连通分量结果中找到的每个对象的面积。如果它小于某个数字,这意味着该对象可能归因于量化噪声,我们应该跳过这个结果。

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

B = conncomptest(A);

因此,将引用的 post 中的代码放入一个名为 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

我们得到:

我无意贬低 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 像素。

如果我在边界框中绘制,您可以在此处看到它们:

质心也为您列出。

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

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

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