1

I was searching for this question and haven't received any specific answers. I am already finding my contours and also i have defined my ROI.

QUESTION: How can i find these contours only inside my ROI?

I have defined my ROI at the beginning.

Here is the code:

    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;
  }

SOLUTION: I wanted to give a condition before drawing my contours with that contours should be in my ROI range. I don't know how do this.

picciano
  • 22,341
  • 9
  • 69
  • 82

1 Answers1

1

I define a function to judge whether Rect rect is in Rect roi or not.

bool isInside(const Rect& rect, const Rect& roi) {
    return (roi|rect) == roi;
}

This is the test example:

enter image description here


//! 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();
}

Ok, now return back to your program, to judge whether the contours is inside of roi or not, just compare their boundingRect with roi.

Your code:

bool is_inside = (roi & cv::Rect(0, 0, drawing.cols, drawing.rows)) == roi;

Modified:

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;
    }

    // ...

}

Here is my result, draw all contours in white, then the inside ones(whose area is meet some area standard)in color:

enter image description here

Kinght 金
  • 17,681
  • 4
  • 60
  • 74
  • thanks for the answers @Silencer , i am still getting an error "isInside cannot be used a function" !! – Zubair Khan Jan 18 '18 at 16:54
  • It's ok for me, the results were post in the answer as you can see. You only give me the error info, without your error code, I can't figure out what is wrong. – Kinght 金 Jan 18 '18 at 16:58
  • https://pastebin.com/JsbFTxBr sorry, this is my modified code as you told and error message is "error: ‘isInside’ cannot be used as a function if(!isInside(rect, roi)){ " – Zubair Khan Jan 18 '18 at 17:02
  • Ok, i see. In my code, it is `if(!isInside(rect, roi))`, while you call in `if(!isInside(roi))`. – Kinght 金 Jan 18 '18 at 17:04
  • You original `is_inside` use `&`, while my `isInside` use `|`, that is the biggest different. Then your original `rect` is wrong for your purpose, that is the second difference. Third, you judge outside the loop, so it is not for every contour. Now, if you run the first example, does it success? If you can't run the first example "Roi in blue; Inside in green, Outside in red!" succesfully, then I can't help. If it successes, then my logic is OK. – Kinght 金 Jan 18 '18 at 17:12
  • yes without this modified code, my code was running without errors !! – Zubair Khan Jan 18 '18 at 17:13
  • its done !! i need to put that bool isInside before my main program. thanks a lot . – Zubair Khan Jan 18 '18 at 17:44