如何从图像中裁剪出检测到的对象(圆圈)并存储它?

Posted

技术标签:

【中文标题】如何从图像中裁剪出检测到的对象(圆圈)并存储它?【英文标题】:How to crop out a detected object (circle) from image and store it? 【发布时间】:2019-05-24 17:17:36 【问题描述】:

下面的代码使用bwboundaries根据对象的圆度对对象进行分类。

它估计每个物体的面积和周长,并使用这些结果形成一个简单的指标,指示物体的圆度,指标如下:

metric = 4*pi*area/perimeter^2

此度量仅对于圆形等于 1,对于任何其他形状都小于 1。但是在这段代码中,我使用了 0.80 的阈值,这样只有度量值大于 0.80 的对象才会被归类为圆形。

我的问题是,当给定对象归类为圆形时,如何从原始图像img(不是Ibw)中将其裁剪并保存为新图像?

我认为使用标签矩阵和边界矩阵就足够了,但仍然不知道如何操作它们。

img=imread('cap.png');
I = rgb2gray(img);

% Step 2: Threshold the Image
bw1 = imbinarize(I);
bw = imcomplement(bw1);

% Step 3: Remove the Noise
bw = bwareaopen(bw,30);      % remove small objects
bw = imfill(bw,'holes');    


% Step 4: Find the Boundaries
[B,L] = bwboundaries(bw,'noholes');
imshow(label2rgb(L,@jet,[.5 .5 .5]))
hold on
for k = 1:length(B)
  boundary = Bk;
  plot(boundary(:,2),boundary(:,1),'w','LineWidth',2)
end



% Step 5: Determine which Objects are Round
stats = regionprops(L,'Area','Centroid');
threshold = 0.80;
% loop over the boundaries
for k = 1:length(B)

  % obtain (X,Y) boundary coordinates corresponding to label 'k'
  boundary = Bk;

  % compute a simple estimate of the object's perimeter
  delta_sq = diff(boundary).^2;    
  perimeter = sum(sqrt(sum(delta_sq,2)));

  % obtain the area calculation corresponding to label 'k'
  area = stats(k).Area;

  % compute the roundness metric
  metric = 4*pi*area/perimeter^2;

  % display the results
  metric_string = sprintf('%2.2f',metric);

  % Test if the current object classified as a round
  if metric > threshold
    % HERE, I want to crop the current object from the 'img' 
    % and save it as a new image 
  end

end

title(['Metrics closer to 1 indicate that ',...
       'the object is approximately round'])

【问题讨论】:

【参考方案1】:

您还可以将BoundingBox 属性添加到regionprops,这将有效地限制blob 在边界框内的延伸位置,您可以使用它们来裁剪图像并保存它。它将具有[x y width height] 的形式,其中xy 是边界框的左上角坐标,widthheight 当然是宽度和高度。 x 是列坐标,y 是行坐标。您可以使用imcrop 最终裁剪出图像。

img=imread('cap.png');
I = rgb2gray(img);

% Step 2: Threshold the Image
bw1 = imbinarize(I);
bw = imcomplement(bw1);

% Step 3: Remove the Noise
bw = bwareaopen(bw,30);      % remove small objects
bw = imfill(bw,'holes');    


% Step 4: Find the Boundaries
[B,L] = bwboundaries(bw,'noholes');
imshow(label2rgb(L,@jet,[.5 .5 .5]))
hold on
for k = 1:length(B)
  boundary = Bk;
  plot(boundary(:,2),boundary(:,1),'w','LineWidth',2)
end



% Step 5: Determine which Objects are Round
stats = regionprops(L,'Area','Centroid','BoundingBox'); % Change
threshold = 0.80;
% loop over the boundaries
for k = 1:length(B)

  % obtain (X,Y) boundary coordinates corresponding to label 'k'
  boundary = Bk;

  % compute a simple estimate of the object's perimeter
  delta_sq = diff(boundary).^2;    
  perimeter = sum(sqrt(sum(delta_sq,2)));

  % obtain the area calculation corresponding to label 'k'
  area = stats(k).Area;

  % compute the roundness metric
  metric = 4*pi*area/perimeter^2;

  % display the results
  metric_string = sprintf('%2.2f',metric);

  % Test if the current object classified as a round
  if metric > threshold
    % HERE, I want to crop the current object from the 'img' 
    % and save it as a new image 

    % New - crop image
    bb = stats(k).BoundingBox;
    img_crop = imcrop(img, bb);

    % New - Save the image
    imwrite(img_crop, sprintf('crop%d.png', k));
  end

end

title(['Metrics closer to 1 indicate that ',...
       'the object is approximately round'])

请注意,我使用imwrite 将裁剪保存到文件中,并根据您正在查看的 blob ID 命名。因此,如果有多个满足条件的 blob 或圆形对象,您将全部保存。

【讨论】:

非常感谢。它正在工作。除了它是: stats(k).BoundingBox 而不是 B(k).BoundingBox @TahaKamil 不客气。如果您没有更多问题或您的问题已得到解决,请通过接受此答案让社区知道。这意味着我们已经解决了您的问题。祝你好运! @TahaKamil 是的,很抱歉!我最初的编辑有B(k),但我不久前改变了它。您可能看到了第一个版本,但没有看到我的编辑。糟糕!

以上是关于如何从图像中裁剪出检测到的对象(圆圈)并存储它?的主要内容,如果未能解决你的问题,请参考以下文章

Matlab:从二值图像裁剪对象

Android自动裁剪相机捕获的图像

如何从图像中检测和裁剪对象?

通过在 imageview 中绘制圆圈裁剪图像

使用 OpenCV c++ 裁剪图像

如何在opencv java中裁剪检测到的面部图像