通过检测图像中的特定大对象或斑点来裁剪图像?

时间:2014-06-19 15:22:29

标签: c++ matlab opencv image-processing

请有人帮我解决我的问题。我正在从事基于图像处理的项目,我坚持了一点。经过一些处理后我得到了这个图像,为了进一步处理,我需要裁剪或检测只鹿并删除图像的其他部分。

这是我的初始形象:

enter image description here

我的结果应该是这样的:

enter image description here

如果我在图像中只获得一个最大的斑点并将其保存为图像,那将会更好。

3 个答案:

答案 0 :(得分:6)

看起来你图像中的鹿几乎是连接和关闭的。我们可以做的是使用regionprops查找图像中的所有边界框。一旦我们这样做,我们就可以找到给出最大区域的边界框,这可能是你的鹿。一旦我们找到这个边界框,我们就可以裁剪你的图像并完全专注于鹿。因此,假设您的图片存储在im中,请执行以下操作:

im = im2bw(im); %// Just in case...
bound = regionprops(im, 'BoundingBox', 'Area'); 

%// Obtaining Bounding Box co-ordinates
bboxes = reshape([bound.BoundingBox], 4, []).';

%// Obtain the areas within each bounding box
areas = [bound.Area].';

%// Figure out which bounding box has the maximum area
[~,maxInd] = max(areas);

%// Obtain this bounding box
%// Ensure all floating point is removed
finalBB = floor(bboxes(maxInd,:));

%// Crop the image
out = im(finalBB(2):finalBB(2)+finalBB(4), finalBB(1):finalBB(1)+finalBB(3));

%// Show the images
figure;
subplot(1,2,1);
imshow(im);
subplot(1,2,2);
imshow(out);

让我们慢慢浏览一下这段代码。我们首先将图像转换为二进制以防万一。您的图像可能是强度为0或255的RGB图像......我无法肯定地说,所以让我们进行二进制转换以防万一。然后,我们使用regionprops属性调用BoundingBox,以查找图像中每个唯一对象的每个边界框。此边界框是最小跨越边界框,以确保对象包含在其中。每个边界框都是一个4元素数组,结构如下:

[x y w h]

每个边界框的边界由其左上角的原点描绘,表示为xy,其中x是水平坐标,而{{1是垂直坐标。 y从左到右积极增加,而x从上到下积极增加。 y是边界框的宽度和高度。因为这些点在一个结构中,我提取它们并将它们放入一个1D向量中,然后对其进行整形,使其成为w,h矩阵。请记住,这是我所知道的唯一方法,可以在没有任何M x 4循环的情况下有效地为每个结构元素提取数组中的值。这将有助于我们更快地进行搜索。我也为for属性做了同样的事情。对于我们在图像中的每个边界框,我们还具有封装在边界框内的总面积的属性。

感谢@Shai当场,我们不能简单地使用边界框坐标来确定某个区域内是否有最大的区域,因为我们可以有一条可以驱动边界的细对角线盒子坐标要高一些。因此,我们还需要依赖于对象在边界框内占据的总面积。简而言之,它只是对象中包含的所有像素的总和。

因此,我们搜索我们创建的整个区域向量,以查看哪个区域具有最大区域。这对应于你的鹿。找到此位置后,提取边界框位置,然后使用此位置裁剪图像。请记住,边界框值可能具有浮点数。由于图像坐标是基于整数的,我们需要在决定裁剪之前删除这些浮点值。我决定使用Area。然后我编写显示原始图像的代码,并显示裁剪结果。

请记住,如果图像中只有一个对象,这将有效。如果要查找多个对象,请在MATLAB中检查bwboundaries。否则,我相信这应该让你开始。

为了完整起见,我们得到以下结果:

enter image description here

答案 1 :(得分:1)

虽然对象检测是一项非常通用的CV任务,但如果假设足够强大,您可以从简单的事情开始,并且可以保证输入图像将包含由边界框描述的单个突出的白色斑点。

一个非常简单的想法是将图片细分为3x3 = 9个补丁,计算每个补丁的统计数据并计算一些目标函数。在最简单的情况下,您只需对各个分区进行网格搜索,然后选择具有最高客观指标的分区。这是一个例子:

enter image description here

如果每一行都是参数x_1,x_2,y_1和y_2,那么你想优化

enter image description here

通过

目标函数F可以定义补丁的统计数据,例如像这样

F(9 patches) {
  brightest_patch = max(patches)
  others          = patches \ brightest_patch
  score           = brightness(brightest_patch) - 1/8 * brightness(others)
  return score
}

或其他任何包含补丁相关统计数据及其大小的内容。这也允许包含先前的知识":如果你希望blob出现在图像的中间,那么你可以定义一个"正则化"如果参数x_i和y_i偏离预期位置太多,将会惩罚F的术语。

答案 2 :(得分:1)

感谢所有回答和评论我的问题的人。在你的帮助下我得到了我的确切解决方案我正在为其他人发布我的最终代码和结果。

img = im2bw(imread('deer.png'));
[L, num] = bwlabel(img, 4);

 %%//  Get biggest blob or object
count_pixels_per_obj = sum(bsxfun(@eq,L(:),1:num));
[~,ind] = max(count_pixels_per_obj);
biggest_blob = (L==ind);

%%// crop only deer
bound = regionprops(biggest_blob, 'BoundingBox');

%// Obtaining Bounding Box co-ordinates
bboxes = reshape([bound.BoundingBox], 4, []).';

%// Obtain this bounding box
%// Ensure all floating point is removed
finalBB = floor(bboxes);
out = biggest_blob(finalBB(2):finalBB(2)+finalBB(4),finalBB(1):finalBB(1)+finalBB(3));

%%// Show images
figure;
imshow(out);

enter image description here