C++ 如何使用一些 openCV 算法围绕对象绘制矩形

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15729210/
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-27 19:42:20  来源:igfitidea点击:

How to draw a rectangle around an object using some openCV algorithm

c++opencvobject-detection

提问by Tomazi

I am working on object detection with opencv. I want to draw a rectangle around an object after clicking on it by mouse. What kind of technique can I use? I tried with SURF but in vain.

我正在使用 opencv 进行对象检测。我想在用鼠标单击对象后在对象周围绘制一个矩形。我可以使用什么样的技术?我尝试过 SURF 但徒劳无功。

Any help will be appreciated.

任何帮助将不胜感激。

回答by yosei

What kind of images you want to use? If the image is a sort of simple one(e.g. a pencil on white paper, a mark on plain wall), would you consider using following approach? I think it is very classical approach but works good when the situation is limited.

你想使用什么样的图像?如果图像是一种简单的图像(例如白纸上的铅笔,普通墙上的标记),您会考虑使用以下方法吗?我认为这是非常经典的方法,但在情况有限时效果很好。

cv::Mat img = // your image.
double threshold = 128; // needs adjustment.
int n_erode_dilate = 1; // needs adjustment.

cv::Mat m = img.clone();
cv::cvtColor(m, m, CV_RGB2GRAY); // convert to glayscale image.
cv::blur(m, m, cv::Size(5,5));
cv::threshold(m, m, threshold, 255,CV_THRESH_BINARY_INV);
cv::erode(m, m, cv::Mat(),cv::Point(-1,-1),n_erode_dilate);
cv::dilate(m, m, cv::Mat(),cv::Point(-1,-1),n_erode_dilate);

std::vector< std::vector<cv::Point> > contours;
std::vector<cv::Point> points;
cv::findContours(m, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (size_t i=0; i<contours.size(); i++) {
    for (size_t j = 0; j < contours[i].size(); j++) {
        cv::Point p = contours[i][j];
        points.push_back(p);
    }
}
// And process the points or contours to pick up specified object.

// for example: draws rectangle on original image.
if(points.size() > 0){
    cv::Rect brect = cv::boundingRect(cv::Mat(points).reshape(2));
    cv::rectangle(img, brect.tl(), brect.br(), cv::Scalar(100, 100, 200), 2, CV_AA);
}

回答by Tomazi

My best advice would be to detect the object first using some OpenCV image processing techniques such as..... Threshold to binaries your image, use blur it to enhance edges detection, use canny filter perhaps erode and dilation.

我最好的建议是首先使用一些 OpenCV 图像处理技术检测对象,例如..... 将图像二进制化的阈值,使用模糊它来增强边缘检测,使用精明的过滤器可能会腐蚀和膨胀。

Once you get a decent threshold where your ROI's stand out from the background I would use a function called findcontours to get the contours of all blobs present in your image, if you get some unwonted contours you could specifies to only draw contour if the are is bigger than X.

一旦你得到一个合适的阈值,你的 ROI 从背景中脱颖而出,我会使用一个名为 findcontours 的函数来获取图像中存在的所有 blob 的轮廓,如果你得到一些不寻常的轮廓,你可以指定只绘制轮廓,如果是比X大。

Once you have the contours of the ROI's stored (in a vector) next step would be to draw bounding boxes around these contours using Rect function.

一旦您存储了 ROI 的轮廓(在向量中),下一步就是使用 Rect 函数围绕这些轮廓绘制边界框。

OpenCV is a very open field for every problem there is plenty of solutions or paths you could choose to take. I would highly recommend to visit OpenCv Documentation

对于每个问题,OpenCV 都是一个非常开放的领域,您可以选择多种解决方案或路径。我强烈建议访问OpenCv 文档

But first check the version of the opencv you have installed or using

但首先检查你安装或使用的opencv的版本

回答by Wayne Chen

after cvtColor erode dilate

在 cvtColor 侵蚀扩张后

// get the contours
std::vector< std::vector< cv::Point> > contours;
cv::findContours(imageMat, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);

// http://blog.csdn.net/corcplusplusorjava/article/details/20536251
// draw contours
cv::drawContours(imageMat , allContours ,-1 , cv::Scalar(0) , 2) ; 

回答by Alexey

An object has to be detected first before you can find its bounding rectangle. By clicking on the object you only specify a pixel that belongs to the object. That's not enough because you know nothing about the shape of the object. So clicking on the object does not equal object detection.

在找到它的边界矩形之前,必须首先检测一个对象。通过单击对象,您只能指定属于该对象的像素。这还不够,因为您对物体的形状一无所知。所以点击对象不等于对象检测。

How you detect an object depends on the application. One way to find the object's outline (edges) is by segmentation. Look into watershedor grabcutsegmentation algorithms in OpenCV. It will give you a contour of the object (if the object stands out from its background). In general, a method for object detection depends on the application, and it's an active research area. Knowing what kind of object is being detected can greatly aid in detection and segmentation.

检测对象的方式取决于应用程序。找到对象轮廓(边缘)的一种方法是通过分割。查看OpenCV 中的分水岭抓取分割算法。它将为您提供对象的轮廓(如果对象从其背景中突出)。一般来说,物体检测的方法取决于应用,这是一个活跃的研究领域。知道正在检测什么样的对象可以极大地帮助检测和分割。

Once you have the object's contour you can find its bounding rectangle using boundingRectfunction. Drawing the rectangle is easy, just use rectanglefunction.

获得对象的轮廓后,您可以使用boundingRect函数找到其边界矩形。绘制矩形很容易,只需使用矩形功能。

回答by cyriel

If the object is rather simple and in one color, you can try to use the watershed algorithm. It should work fine for one color objects like pencil but definitely will fail in more complex situations.

如果对象相当简单且只有一种颜色,您可以尝试使用分水岭算法。它应该适用于像铅笔这样的一种颜色对象,但在更复杂的情况下肯定会失败。