【问题标题】:how to detect number of contours in between two lines or specified region of image如何检测两行或图像指定区域之间的轮廓数
【发布时间】:2016-03-01 19:31:45
【问题描述】:

我正在使用 OpenCV C++ 来查找视频中的轮廓。我想计算视频中指定区域或视频中绘制的两条线之间存在的轮廓的数量。例如,轮廓流在视频中移动,我想在它们到达视频中的特定区域时对它们进行计数。当他们离开视频中的特定区域时,我会减少计数。我知道一些基本的东西来找到轮廓,计算面积等。但我没有得到任何编程技巧来计算指定区域内的轮廓数。请帮助我了解相关主题和一些编程技巧。 (我不想使用 cvBlob.h 库)

基本上我是在计算进入该地区的汽车数量。如果输入汽车,我将增加计数,如果它离开该区域,则我将减少计数。

【问题讨论】:

  • 请帮助我们为您提供帮助,包括一些图片、预期结果以及您拥有的代码。
  • @Miki 我已经更新了问题和图片。
  • 您的区域可以建模为 1) Rect,或 2) 掩码。在情况 1) 中,您可以检查轮廓的每个点(或仅质心)是否落入矩形。您可以为此使用rect.contains(point)。如果你有一个掩码,每个区域都有一个标签号,你可以检查轮廓(或质心)每个点的标签

标签: c++ opencv3.0 object-detection


【解决方案1】:

您可以将找到的轮廓近似为多边形或圆形:

for( int i = 0; i < contours.size(); i++ )
 { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
   boundRect[i] = boundingRect( Mat(contours_poly[i]) )
 }

然后使用直线方程y=a,比较矩形的角坐标或圆的center+radius,以确定轮廓是否通过直线。

【讨论】:

  • 非常感谢。我对我的问题有了一些线索。你能告诉我如何跟踪对象吗?假设如果有 2 或 3 辆车在移动,它应该跟踪每一辆车。
  • 这真的取决于你的问题,你的背景有多复杂。最简单的选择是使用 camshiftmeanshift ,有关于它们的教程音调,对于您的情况,它很容易使用,因为它们接受一个矩形并在视频中跟踪该矩形。如果它们不起作用,您可以尝试 Kalman Filter 或 TLD。
  • @pradeep 如果对您有帮助,请接受答案:) 谢谢
  • 更新了图片。请看一下并相应地给我建议。
【解决方案2】:

1.使用您的 Mat 图像的一部分。(如果您的 ROI 是矩形)

Mat src;  // suppose this is your source frame
Mat src_of_interest = src(Rect(Point(x1, y1), Point(x2, y2)));

// Do the rest of finding contour..

vector<vector<Point>> contours;
vector<Vec4i> hierarchy;

findContours(src_of_interest.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

//now you can do your job with contour vector.    
int count = contours.size();

Mat dst = Mat::zeros(src.size(), CV_8UC3);
for(int i=0; i< count; i++)
{
    drawContours(dst, contours, i, CV_RGB(255, 0, 0));   // draw contour in red
}


2. 如果您的感兴趣区域不是矩形,请尝试以下方法:

vector<Point> contour_of_interest;   // this contour is where you want to check
vector<vector<Point>> contours;   // this is the contours you found

Mat dst = Mat::zeros(src.size(), CV_8U);
for(int i=0; i< count; i++)
{
    drawContours(dst, contours, i, Scalar(255));   // set contour area to 255
}

Mat roi = Mat::zeros(src.size(), CV_8U);
vector<vector<Point>> coi_vector;
coi_vector.push_back(contour_of_interest);
drawContours(roi, coi_vector, 0, Scalar(255));

Mat and = dst & roi;    // where 2 mats are both TRUE(not zero)

findContours(and.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

//now you can do your job with contour vector.    
int count = contours.size();


3.如果你想计算4个点之间的轮廓,试试这个方法:

vector<Point> contour_of_interest;   // this contour is the area where you want to check
Point p1(x1, y1);
Point p2(x1, y2);
Point p3(x2, y2);
Point p4(x2, y1);
contour_of_interest.push_back(p1);
contour_of_interest.push_back(p2);
contour_of_interest.push_back(p3);
contour_of_interest.push_back(p4);

vector<vector<Point>> coi_list;
coi_list.push_back(contour_of_interest);

Mat mask = Mat:zeros(src.size(), CV_8U);
drawContours(mask, coi_list, 0, Scalar(255));

Mat src;  // suppose this is your source frame
Mat src_of_interest = src & mask;  // remove any pixels outside mask area

// Do the rest of finding contour..

vector<vector<Point>> contours;
vector<Vec4i> hierarchy;

findContours(src_of_interest.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

//now you can do your job with contour vector.    
int count = contours.size();

Mat dst = Mat::zeros(src.size(), CV_8UC3);
for(int i=0; i< count; i++)
{
    drawContours(dst, contours, i, CV_RGB(255, 0, 0));   // draw contour in red
}

【讨论】:

  • 我已经更新了新图片。编程风格很好。我想在我的程序中使用相同的。你能帮我根据我更新的新图像重写程序吗?我想知道轮廓的方向,为此我必须使用两条线。请不要说我没有使用任何矩形。如果轮廓进入两条线,我想计算轮廓。我希望你理解这个场景。如果不清楚,请告诉我。
  • @pradeep x1, x2, x3, x4 和 y1, y2, y3, y4 到底是什么意思?在您的图片中只有 2 个 y 坐标。
  • @pradeep 我添加了第三种方法,我认为你可以应用它。
  • 谢谢,我把坐标命名错了。却抓住了。我会实施并回复您。
  • @pradeep 有一些语法错误,我编辑了第三个。看看吧。
猜你喜欢
  • 2021-04-13
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
相关资源
最近更新 更多