C++ OpenCV 边界框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14733042/
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
OpenCV Bounding Box
提问by Tomazi
I am working on software using OpenCV in C++ environment. The objective is to detect a boxing glove and draw a bounding box around gloves contours.
我正在 C++ 环境中使用 OpenCV 开发软件。目标是检测拳击手套并在手套轮廓周围绘制边界框。
The problem I am running into is that the bounding box is drown more than once in fact multiple boxes are drawn. What I was trying to do over the past few days is to somehow eliminate the number of boxes drawn and have only one big bounding box drawn.
我遇到的问题是边界框被淹没不止一次,实际上绘制了多个框。过去几天我试图做的是以某种方式消除绘制的框的数量并且只绘制一个大的边界框。
I was looking at some techniques to fill in the object int its whole which i believe would really help in this case.
我正在研究一些技术来填充整个对象,我相信这在这种情况下真的很有帮助。
Below I have posted the code i used to achieve the result displayed in the image:
下面我发布了我用来实现图像中显示的结果的代码:
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<Vec3f> vecCircles;
vector<Vec3f>::iterator itrCircles;
while(1)
{
Mat frame;
cap >> frame; // get a new frame from camera
/////////////////////
Mat imgHSV;
cvtColor( frame, imgHSV, CV_BGR2HSV );
////////////////////
Mat blur_out;
GaussianBlur(imgHSV, blur_out, Size(1,1),2.0,2.0);
////////////////////
Mat range_out;
inRange(blur_out, Scalar(100, 100, 100), Scalar(120, 255, 255), range_out);
////////////////////
findContours(range_out, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
}
/// Draw polygonal contour + bonding rects
Mat drawing = Mat::zeros( range_out.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar(255,0,255);
drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
}
If anyone could suggest some tips or provide some source of information where i can find answers for my problem.
如果有人可以建议一些提示或提供一些信息来源,我可以在其中找到我的问题的答案。
EDIT(quick update):
编辑(快速更新):
I managed to improve the output image quiet gradually to a point am quiet happy with the result. The Key was the usage of erode & dilation as well as in my findContours()
function. I changed the CV_RETR_TREE
to CV_RETR_EXTERNAL
. There were a few other minor things i tackled but the result is good:
我设法逐渐将输出图像安静地改善到对结果感到满意的程度。关键是在我的findContours()
函数中使用了侵蚀和膨胀。我将其更改CV_RETR_TREE
为 CV_RETR_EXTERNAL
. 我还解决了其他一些小问题,但结果很好:
Dont know if i should write this here or open new thread....But now I need some help with component labeling and extracting parameters such as center points and area. :)
不知道我应该在这里写这个还是打开新线程....但现在我需要一些帮助来标记组件和提取参数,例如中心点和面积。:)
回答by karlphillip
Take a look at my other answerin this subject. Compile that code and remember to activate the code that is commented out.
看看我在这个主题中的另一个答案。编译该代码并记住激活被注释掉的代码。
Result:
结果:
回答by HugoRune
You currently draw a bounding box around each contour, and findContour will find a contour around each connected white or black component, of which there are many in your picture.
您当前在每个轮廓周围绘制一个边界框, findContour 将在每个连接的白色或黑色组件周围找到一个轮廓,其中有很多在您的图片中。
So the first thing I would do is filter all that noise with some morphological operations on the thresholded image: do some opening and closing, both of which are combinations of dilation and erosion.
所以我要做的第一件事就是在阈值图像上用一些形态学操作过滤掉所有的噪音:做一些开和关,这两者都是dilation 和erosion 的组合。
In your case something like cvDilate (2 times); cvErode(4 times); cvDilate(2 times)
在你的情况下像 cvDilate (2 次); cvErode(4 次); cvDilate(2 次)
This should merge all white blobs into one smooth blob, but the black hole in the middle will remain. You could find the right one by size, but it is easier to call findContours with the CV_RETR_EXTERNAL instead of CV_RETR_TREE, then it will only return the outermost contours.
这应该将所有白色斑点合并成一个光滑的斑点,但中间的黑洞将保留。您可以按大小找到合适的,但使用 CV_RETR_EXTERNAL 而不是 CV_RETR_TREE 调用 findContours 会更容易,那么它只会返回最外层的轮廓。
回答by b_m
Before finding the contours you should apply morphological filter like erodeand dilate. After that, you can find the contours and leave out the small ones by calculating its size, or the with and height of the bounding box. Finally you can eliminate those that are inside an other contour using the hierarchy.
在找到轮廓之前,您应该应用形态过滤器,如erode和dilate。之后,您可以通过计算其大小或边界框的宽度和高度来找到轮廓并忽略小的轮廓。最后,您可以使用层次结构消除其他轮廓内的那些。
回答by Abhishek Thakur
as b_m mentioned, you need to apply the morphological operations. Then I'd do something like finding the largest contour in the image and draw the bounding box around that contour only. I had created the following function for a project of mine which I think will help you if used in a correct manner
正如 b_m 提到的,你需要应用形态学操作。然后我会做一些事情,比如在图像中找到最大的轮廓并只在该轮廓周围绘制边界框。我为我的一个项目创建了以下功能,我认为如果以正确的方式使用它会帮助你
CvSeq* findLargestContour(CvSeq* contours){
CvSeq* current_contour = contours;
double largestArea = 0;
CvSeq* largest_contour = NULL;
// check we at least have some contours
if (contours == NULL){return NULL;}
while (current_contour != NULL){
double area = fabs(cvContourArea(current_contour));
if(area > largestArea){
largestArea = area;
largest_contour = current_contour;
}
current_contour = current_contour->h_next;
}
// return pointer to largest
return largest_contour;
}