C++ 使用 OpenCV 的边界框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3669611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:25:59  来源:igfitidea点击:

Bounding box using OpenCV

c++opencv

提问by supergranu

I want to get the bounding box of a filled black circle on a white background using opencv BoundingRect. I used the sample code from http://cgi.cse.unsw.edu.au/~cs4411/wiki/index.php?title=OpenCV_Guide#Finding_bounding_boxes_around_regions_of_a_binary_imagebut failed to get the properties of the bounding box and draw it into the image. Should be a simple problem, I think, but still I fail doing it...

我想使用 opencv BoundingRect 在白色背景上获取黑色实心圆圈的边界框。我使用了http://cgi.cse.unsw.edu.au/~cs4411/wiki/index.php?title=OpenCV_Guide#Finding_bounding_boxes_around_regions_of_a_binary_image 中的示例代码,但未能获取边界框的属性并将其绘制到图像中. 应该是一个简单的问题,我想,但我还是没能做到......

Would be nice, if you could write down some sample code.

如果您能写下一些示例代码,那就太好了。

Thanks.

谢谢。



The picture I'm using at the moment is an image of 1392x1040 pixels with a big black circle in the middle (diameter around 1000 pixels) and the rest of the image is white.

我目前使用的图片是 1392x1040 像素的图像,中间有一个大黑色圆圈(直径约 1000 像素),图像的其余部分是白色的。

My source code is:

我的源代码是:

#include <iostream>
#include <vector>
#include <cv.h>
#include <highgui.h>

using namespace std;

int main(int argc, char** argv){


IplImage* img_in = cvLoadImage("Schwarzer_Kreis.png",1);


IplImage* img_working = cvCreateImage(cvGetSize(img_in), 8, 1);
cvCvtColor(img_in, img_working, CV_BGR2GRAY);

CvSeq* seq;

vector<CvRect> boxes;

CvMemStorage* storage = cvCreateMemStorage(0);
cvClearMemStorage(storage);

cvFindContours(img_working, storage, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(600,200));

CvRect boundbox ;

for(; seq; seq = seq->h_next) {
 boundbox = cvBoundingRect(seq);
 boxes.push_back(boundbox);
}

for (int ii=0; ii<boxes.size(); ii++) {
cout << boxes[ii].x << endl;
cout << boxes[ii].y << endl;
cout << boxes[ii].width << endl;
cout << boxes[ii].height << endl;
}


cvWaitKey(0);

return 0;

}


The output that I geht from the program is:

我从程序中得到的输出是:

601

601

201

201

1390

1390

1038

1038

回答by David López

This code uses the functions of OpenCV 2.1 "findContours" and "boundingRect" to get the bounding box of a binarized image (0-255), which draws on the bounding-box. Avoid noise by calculating the bounding box around the shape of largest area.

这段代码使用OpenCV 2.1“findContours”和“boundingRect”的函数来获取二值化图像(0-255)的边界框,在边界框上绘制。通过计算最大区域形状周围的边界框来避免噪声。

More information http://www.davidlopez.es/?p=65

更多信息http://www.davidlopez.es/?p=65

// Declares a vector of vectors for store the contours
vector<vector<Point> > v;

Mat originalimage;
Mat image;

// Loads the original image
originalimage = imread("original.ppm");
// Converts original image to an 8UC1 image
cvtColor(originalimage, image, CV_BGR2GRAY);

// Finds contours
findContours(image,v,CV_RETR_LIST,CV_CHAIN_APPROX_NONE);

// Finds the contour with the largest area
int area = 0;
int idx;
for(int i=0; i<v.size();i++) {
    if(area < v[i].size())
        idx = i; 
}

// Calculates the bounding rect of the largest area contour
Rect rect = boundingRect(v[idx]);
Point pt1, pt2;
pt1.x = rect.x;
pt1.y = rect.y;
pt2.x = rect.x + rect.width;
pt2.y = rect.y + rect.height;
// Draws the rect in the original image and show it
rectangle(originalimage, pt1, pt2, CV_RGB(255,0,0), 1);

cvNamedWindow( "Ejemplo", CV_WINDOW_AUTOSIZE );
imshow("Ejemplo", originalimage );
cvWaitKey(0);

cvDestroyWindow("Ejemplo" );

回答by supergranu

I made my own code for calculating the bounding box:

我编写了自己的代码来计算边界框:

int* get_boundingbox(
        IplImage* img_input){

int width     = img_input->width;
int height    = img_input->height;

int* Output = NULL;
Output = new int[4];


//----- Top boundary -----
for(int ii = 0 ; ii < height ; ii++ ){

    int value;

    for(int jj = 0 ; jj < width ; jj++ ) {

        value = static_cast<int>(cvGetReal2D(img_input,1039-ii,jj));

        if (value == 0) {
            Output[1] = 1039-ii; // upper left corner, y-value
            break;
      }
    if (value == 0) break;
    }
}


//----- Left boundary -----
for(int ii = 0 ; ii < width ; ii++ ){

    int value;

    for(int jj = 0 ; jj < height ; jj++ ) {

        value = static_cast<int>(cvGetReal2D(img_input,jj,1391-ii));

        if (value == 0) {
            Output[0] = 1391-ii; //upper left corner. x-value
            break;
      }
    if (value == 0) break;
    }
}


//----- Right boundary -----
for(int ii = 0 ; ii < width ; ii++ ){

    int value;

    for(int jj = 0 ; jj < height ; jj++ ) {

        value = static_cast<int>(cvGetReal2D(img_input,jj,ii));

        if (value == 0) {
            Output[2] = ii+1; // lower right corner, x-value
            break;
      }
    if (value == 0) break;
    }
}


//----- Bottom boundary -----
for(int ii = 0 ; ii < height ; ii++ ){

    int value;

    for(int jj = 0 ; jj < width ; jj++ ) {

        value = static_cast<int>(cvGetReal2D(img_input,ii,jj));

        if (value == 0) {
            Output[3] = ii+1; // lower right corner, y-value
            break;
      }
    if (value == 0) break;
    }
}


Output[2] = Output[2] - Output[0] + 1; // width
Output[3] = Output[3] - Output[1] + 1; // height

return Output;
delete []Output;

}

回答by dnul

you can draw it using

你可以用它来画

boundingRect=cvBoundingRect(seq,0); 
cvRectangle(contourImage,cvPoint(boundingRect.x,boundingRect.y),
                    cvPoint(boundingRect.x+boundingRect.width,
                    boundingRect.y+boundingRect.height),
                    _GREEN,1,8,0);

回答by Vinayak Agarwal

You can consider taking the negative of the image you have(circle is white on a black background) and then trying your code. The command is cvNot(src, dst).

您可以考虑对您拥有的图像取底片(黑色背景上的圆圈为白色),然后尝试您的代码。命令是 cvNot(src, dst)。

Some of the OpenCV functions require the background to be black.

一些 OpenCV 函数要求背景为黑色。