【发布时间】:2013-03-21 16:29:39
【问题描述】:
我正在使用 opencv 进行对象检测。 我想在用鼠标单击对象后在对象周围绘制一个矩形。 我可以使用什么样的技术?我尝试了 SURF,但没有成功。
任何帮助将不胜感激。
【问题讨论】:
-
这是一个非常开放的问题,完整的解决方案仍然是一个活跃的研究领域。您可以研究阈值或图形切割来帮助您入门。
标签: c++ opencv object-detection
我正在使用 opencv 进行对象检测。 我想在用鼠标单击对象后在对象周围绘制一个矩形。 我可以使用什么样的技术?我尝试了 SURF,但没有成功。
任何帮助将不胜感激。
【问题讨论】:
标签: c++ opencv object-detection
您想使用什么样的图片? 如果图像是一种简单的图像(例如白纸上的铅笔,普通墙上的标记),您会考虑使用以下方法吗?我认为这是非常经典的方法,但在情况有限时效果很好。
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);
}
【讨论】:
必须先检测到一个对象,然后才能找到它的边界矩形。通过单击对象,您只需指定属于该对象的像素。这还不够,因为您对物体的形状一无所知。所以点击物体不等于物体检测。
如何检测对象取决于应用程序。找到对象轮廓(边缘)的一种方法是分割。查看 OpenCV 中的 watershed 或 grabcut 分割算法。它将为您提供对象的轮廓(如果对象从其背景中突出)。一般来说,目标检测方法取决于应用程序,是一个活跃的研究领域。了解检测到的对象类型可以极大地帮助检测和分割。
一旦你有了对象的轮廓,你就可以使用boundingRect 函数找到它的边界矩形。绘制矩形很简单,只需使用rectangle 函数即可。
【讨论】:
如果对象比较简单且只有一种颜色,您可以尝试使用watershed algorithm。它应该适用于像铅笔这样的一种颜色的物体,但在更复杂的情况下肯定会失败。
【讨论】:
我最好的建议是首先使用一些 OpenCV 图像处理技术来检测对象,例如......阈值来二进制图像,使用模糊来增强边缘检测,使用 canny 过滤器可能会腐蚀和膨胀。
一旦你得到一个合适的阈值,让你的 ROI 从背景中脱颖而出,我会使用一个名为 findcontours 的函数来获取图像中存在的所有斑点的轮廓,如果你得到一些不常见的轮廓,你可以指定仅在以下情况下绘制轮廓面积比 X 大。
一旦您存储了 ROI 的轮廓(在向量中),下一步就是使用 Rect 函数在这些轮廓周围绘制边界框。
OpenCV 是一个非常开放的领域,可以解决每一个问题,您可以选择多种解决方案或路径。我强烈建议您访问OpenCv Documentation
但首先要检查你已经安装或使用的opencv的版本
【讨论】:
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) ;
【讨论】: