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
Bounding box using 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 函数要求背景为黑色。