-5

Any thoughts where I might be going wrong. PS: New to coding and StackOverFlow.



#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/imgproc.hpp>

//Declare the image variables
cv::Mat img, imgGray, imgBlur, imgCanny, imgDil;

void GetContours(cv::Mat dilatedImg, cv::Mat originalImg);

int main(int argc, char** argv)
{
   std::string path="E://Trial//Resources//Resources//shapes.png";
   img= cv::imread(path);
 

   //pre=processing
   cv::cvtColor(img,imgGray,cv::COLOR_BGR2GRAY);
   cv::GaussianBlur(imgGray, imgBlur,cv::Size(3,3),3,0);
   cv::Canny(imgBlur,imgCanny,25,75);
   cv::Mat kernel= cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3,3)) ;
   cv::dilate(imgCanny,imgDil,kernel);

   //Processing
   GetContours(imgDil, img);
   
   //Display contours
   cv::imshow("Image",img);
   cv::waitKey(0);

   return 0;
}

void GetContours(cv::Mat dilatedImg, cv::Mat originalImg)
{
   std::vector<std::vector<cv::Point>> contours;
   std::vector<cv::Vec4i> hierarchy;
   std::vector<std::vector<cv::Point>> conPoly(contours.size());
   double area=0;


   //finds the contours in the shapes
   cv::findContours(dilatedImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
   
   for(int i=0; i<contours.size(); i++)
   {
      area = cv::contourArea(contours[i]);
      std::cout<<area<<std::endl;
      
      if(area>1000)
      {
         //Draw contours around shapes
         cv::drawContours(originalImg,contours, i,cv::Scalar(255,0,255),2);
         
         // create a bounding box around the shapes
         cv::approxPolyDP(cv::Mat(contours[i]), conPoly[i], 3, true);
        
         //draw contours using the contour points
         cv::drawContours(originalImg,conPoly, i,cv::Scalar(255,255,0),2);         
      }
   }
}



ApproxPollyDP is where I think the code is failing. I am getting an Assertion Failed error with vector out of range. I think I am doing some silly mistake but I have not been able to debug the issue.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Use a debugger. It will stop dead when the error is detected so that you can inspect the call stack and see how the program got into such a dire situation. – user4581301 Jan 31 '23 at 18:18
  • Discuss with [your rubber duck](https://en.wikipedia.org/wiki/Rubber_duck_debugging) what can be the only possible value of `contours.size()` at `std::vector> conPoly(contours.size());` and how large `conPoly` must be as a result. – user4581301 Jan 31 '23 at 18:21
  • Remember that C++ is not a spreadsheet. When you perform a computation it happens right then and there. If you change the value of one of the variables used in the computation, the computation is not rerun and no new results are pushed out. – user4581301 Jan 31 '23 at 18:23
  • 1
    *New to coding* -- Well, I suggest you learn the basics of C++ first. Libraries like the one you're using (opencv) assumes that the user of the library is an experienced programmer. If you make the very simple mistake that was pointed out, there will be a host of other similar "simple" mistakes later on, where those mistakes would be avoided by going through the formal process of learning C++. But that will be obscured if you have opencv library calls in multiple places. – PaulMcKenzie Jan 31 '23 at 18:40
  • Thanks. I did go through the basics and trying to apply them in different practical applications. – Mind Chants Jan 31 '23 at 18:46

2 Answers2

1

The vector conPoly declared as shown below

std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> conPoly(contours.size());

is an empty vector because initially contours.size() is equal tp 0 because the vector contours in turn is declared as empty.

So using the subscript operator with the vector

cv::approxPolyDP(cv::Mat(contours[i]), conPoly[i], 3, true);

invokes undefined behavior.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thanks, I solved it. You point got me thinking. I declared array of arrays conPoly after findContours. That way contours.size() will return a number. – Mind Chants Jan 31 '23 at 18:41
-3

So this works:

std::vector<std::vector<cv::Point>> contours;
   std::vector<cv::Vec4i> hierarchy;
   double area=0;


   //finds the contours in the shapes
   cv::findContours(dilatedImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
   
   std::vector<std::vector<cv::Point>> conPoly(contours.size());
  • 1
    This should be correct, but a good answer will explain what went wrong and how this solution fixes the problem. This helps future askers connect the dots between the question and the answer. – user4581301 Jan 31 '23 at 23:17