在 ROI 内查找轮廓
Find Contours inside ROI
我正在搜索这个问题,但没有收到任何具体答案。我已经找到了我的轮廓,也定义了我的投资回报率。
问题:如何才能仅在我的 ROI 内找到这些轮廓?
我一开始就定义了我的投资回报率。
代码如下:
int main( int argc, char** argv )
{
Mat img_prev, img_curr, result;
int counter = 0;
//string filename = "/home/zubair/Downloads/Contours/1.jpg";
//VideoCapture cap(filename);
//while(1)
//{
img_curr = imread(argv[1], CV_LOAD_IMAGE_COLOR);
//cap >> img_curr;
//counter++;
//img_curr.copyTo(img_prev);
while(1)
{
// SetImageRoi
cv::Rect roi(1,250, 640, 200);
cv::rectangle(img_curr,roi,cv::Scalar(255,255,255),1,8,0);
//cv::Mat image_roi = img_curr(roi); // note: this assignment does not copy data, frame and image_roi now share data
imshow ("current frame",img_curr);
if(! img_curr.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
//imshow("previous frame", img_prev);
cvtColor( img_curr, src_gray, CV_BGR2GRAY );
//--------------------------------------------------------------------------------------------------------------------------------------//
//----------------------------------- to find the contours AND Detect edges using Threshold---------------------------------------------//
//--------------------------------------------------------------------------------------------------------------------------------------//
Mat canny_output;
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using canny
Canny(src_gray, canny_output, thresh, thresh*2, 3 );
blur( src_gray, src_gray, Size(3,3) );
///threshold control
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
/// Find contours
findContours( threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Get the moments
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
cv::erode(threshold_output,threshold_output, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)));
cv::dilate(threshold_output, threshold_output, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)));
/// Get the mass centers:
vector<Point2f> mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
/// 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]) );
minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
}
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
bool is_inside = (roi & cv::Rect(0, 0, drawing.cols, drawing.rows)) == roi;
//printf("\t Info: Area and Contour Length \n");
for( int i = 0; i< contours.size(); i++ )
{
if(contourArea(contours[i]) > 2000 && contourArea(contours[i]) < 50000 )
{
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength ( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point(0,0) );
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
Point center_obstacle = (boundRect[i].br() + boundRect[i].tl())*0.5;
circle(drawing,center_obstacle,3,Scalar(0,0,255));
cout<<" obstale "<<i<<" position is at "<< center_obstacle.x <<" and "<< center_obstacle.y <<endl;
}
}
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh);
namedWindow( "Contours", WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
//--------------------------------------------------------------------------------------------------------------------------------------------
waitKey(0);
}
return 0;
}
解决方案:我想在绘制轮廓之前给出一个条件,轮廓应该在我的 ROI 范围内。我不知道该怎么做。
我定义了一个判断Rect rect
是否在Rect roi
中的函数
bool isInside(const Rect& rect, const Rect& roi) {
return (roi|rect) == roi;
}
这是测试示例:
//! 2018.01.18 09:37:20 CST
//! 2018.01.18 10:29:16 CST
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>
using namespace std;
using namespace cv;
// To judge whether rect is in roi or not?
bool isInside(const Rect& rect, const Rect& roi) {
return (roi|rect) == roi;
}
int main() {
Mat img(600,600, CV_8UC3, Scalar::all(0));
Rect roi(100, 100, 400, 400);
Rect rect1(200, 200, 200, 200);
Rect rect2(10,10, 200, 200);
Scalar blue(255,0,0), green(0,255,0), red(0,0,255);
string msg("Roi in blue; Inside in green, Outside in red!");
cout<<msg<<endl;
rectangle(img, roi, blue, 1);
rectangle(img, rect1, isInside(rect1, roi)?green:red, 1);
rectangle(img, rect2, isInside(rect2, roi)?green:red, 1);
imshow(msg, img);
waitKey();
}
好的,现在 return 回到您的程序,到 judge whether the contours is inside of roi or not
,只是 compare their boundingRect with roi
。
您的代码:
bool is_inside = (roi & cv::Rect(0, 0, drawing.cols, drawing.rows)) == roi;
修改:
for( int i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
// bool is_inside = (roi|rect) == roi;
if(!isInside(rect, roi)){
cout <<"Not in side, continue to the next."<<endl;
continue;
}
// ...
}
这是我的结果,把所有的轮廓都画成白色,然后把里面的(面积符合某个区域标准的)画成彩色:
我正在搜索这个问题,但没有收到任何具体答案。我已经找到了我的轮廓,也定义了我的投资回报率。
问题:如何才能仅在我的 ROI 内找到这些轮廓?
我一开始就定义了我的投资回报率。
代码如下:
int main( int argc, char** argv )
{
Mat img_prev, img_curr, result;
int counter = 0;
//string filename = "/home/zubair/Downloads/Contours/1.jpg";
//VideoCapture cap(filename);
//while(1)
//{
img_curr = imread(argv[1], CV_LOAD_IMAGE_COLOR);
//cap >> img_curr;
//counter++;
//img_curr.copyTo(img_prev);
while(1)
{
// SetImageRoi
cv::Rect roi(1,250, 640, 200);
cv::rectangle(img_curr,roi,cv::Scalar(255,255,255),1,8,0);
//cv::Mat image_roi = img_curr(roi); // note: this assignment does not copy data, frame and image_roi now share data
imshow ("current frame",img_curr);
if(! img_curr.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
//imshow("previous frame", img_prev);
cvtColor( img_curr, src_gray, CV_BGR2GRAY );
//--------------------------------------------------------------------------------------------------------------------------------------//
//----------------------------------- to find the contours AND Detect edges using Threshold---------------------------------------------//
//--------------------------------------------------------------------------------------------------------------------------------------//
Mat canny_output;
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using canny
Canny(src_gray, canny_output, thresh, thresh*2, 3 );
blur( src_gray, src_gray, Size(3,3) );
///threshold control
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
/// Find contours
findContours( threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Get the moments
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
cv::erode(threshold_output,threshold_output, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)));
cv::dilate(threshold_output, threshold_output, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5)));
/// Get the mass centers:
vector<Point2f> mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
/// 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]) );
minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
}
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
bool is_inside = (roi & cv::Rect(0, 0, drawing.cols, drawing.rows)) == roi;
//printf("\t Info: Area and Contour Length \n");
for( int i = 0; i< contours.size(); i++ )
{
if(contourArea(contours[i]) > 2000 && contourArea(contours[i]) < 50000 )
{
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength ( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point(0,0) );
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
Point center_obstacle = (boundRect[i].br() + boundRect[i].tl())*0.5;
circle(drawing,center_obstacle,3,Scalar(0,0,255));
cout<<" obstale "<<i<<" position is at "<< center_obstacle.x <<" and "<< center_obstacle.y <<endl;
}
}
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh);
namedWindow( "Contours", WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
//--------------------------------------------------------------------------------------------------------------------------------------------
waitKey(0);
}
return 0;
}
解决方案:我想在绘制轮廓之前给出一个条件,轮廓应该在我的 ROI 范围内。我不知道该怎么做。
我定义了一个判断Rect rect
是否在Rect roi
中的函数
bool isInside(const Rect& rect, const Rect& roi) {
return (roi|rect) == roi;
}
这是测试示例:
//! 2018.01.18 09:37:20 CST
//! 2018.01.18 10:29:16 CST
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>
using namespace std;
using namespace cv;
// To judge whether rect is in roi or not?
bool isInside(const Rect& rect, const Rect& roi) {
return (roi|rect) == roi;
}
int main() {
Mat img(600,600, CV_8UC3, Scalar::all(0));
Rect roi(100, 100, 400, 400);
Rect rect1(200, 200, 200, 200);
Rect rect2(10,10, 200, 200);
Scalar blue(255,0,0), green(0,255,0), red(0,0,255);
string msg("Roi in blue; Inside in green, Outside in red!");
cout<<msg<<endl;
rectangle(img, roi, blue, 1);
rectangle(img, rect1, isInside(rect1, roi)?green:red, 1);
rectangle(img, rect2, isInside(rect2, roi)?green:red, 1);
imshow(msg, img);
waitKey();
}
好的,现在 return 回到您的程序,到 judge whether the contours is inside of roi or not
,只是 compare their boundingRect with roi
。
您的代码:
bool is_inside = (roi & cv::Rect(0, 0, drawing.cols, drawing.rows)) == roi;
修改:
for( int i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
// bool is_inside = (roi|rect) == roi;
if(!isInside(rect, roi)){
cout <<"Not in side, continue to the next."<<endl;
continue;
}
// ...
}
这是我的结果,把所有的轮廓都画成白色,然后把里面的(面积符合某个区域标准的)画成彩色: