Reputation: 91
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_image but 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...
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.
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
201
1390
1038
Upvotes: 1
Views: 42124
Reputation: 91
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;
}
Upvotes: 3
Reputation: 99
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.
More information 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" );
Upvotes: 9
Reputation: 1410
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).
Some of the OpenCV functions require the background to be black.
Upvotes: 1
Reputation: 717
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);
Upvotes: 2