Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Maybe you can use this:

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

void main()
{
  cv::Mat img = cv::imread("D:\\mahi images\\equation.jpg", 0);
  cv::imshow("", img);
  cv::waitKey(0);

  cv::Size size(3, 3);
  cv::GaussianBlur(img, img, size, 0);
  cv::adaptiveThreshold(img, img, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 75, 10);
  cv::bitwise_not(img, img);

  cv::Mat img2 = img.clone();

  std::vector<cv::Point> points;
  cv::Mat_<uchar>::iterator it = img.begin<uchar>();
  cv::Mat_<uchar>::iterator end = img.end<uchar>();
  for (; it != end; ++it)
  {
    if (*it)
    {
      points.push_back(it.pos());
    }
  }

  cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));

  double angle = box.angle;
  if (angle < -45.)
  {
    angle += 90.;
  }

  cv::Point2f vertices[4];
  box.points(vertices);
  for (unsigned int i = 0; i < 4; ++i)
  {
    cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(255, 0, 0), 1, CV_AA);  
  }

  cv::Mat rot_mat = cv::getRotationMatrix2D(box.center, angle, 1);
  cv::Mat rotated;
  cv::warpAffine(img2, rotated, rot_mat, img.size(), cv::INTER_CUBIC);

  cv::Size2f box_size = box.size;
  if (box.angle < -45.)
  {
    std::swap(box_size.width, box_size.height);
  }

  cv::Mat cropped;
  cv::getRectSubPix(rotated, box_size, box.center, cropped);
  cv::imshow("Cropped", cropped);
  cv::waitKey(0);
  cv::imwrite("example5.jpg", cropped);

  cv::Mat cropped2 = cropped.clone();
  cv::cvtColor(cropped2, cropped2, CV_GRAY2RGB);

  cv::Mat cropped3 = cropped.clone();
  cv::cvtColor(cropped3, cropped3, CV_GRAY2RGB);

  std::vector<std::vector<cv::Point> > contours;
  std::vector<cv::Vec4i> hierarchy;

  cv::findContours(cropped, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS, cv::Point(0, 0));

  std::vector<std::vector<cv::Point> > contours_poly(contours.size());
  std::vector<cv::Rect> boundRect(contours.size());
  std::vector<cv::Point2f> center(contours.size());
  std::vector<float> radius(contours.size());

  for (unsigned int i = 0; i < contours.size(); ++i)
  { 
    cv::approxPolyDP(cv::Mat(contours.at(i)), contours_poly.at(i), 3, true);
  }

  std::vector<std::vector<cv::Point> > validContours;
  for (unsigned int i = 0; i < contours_poly.size(); ++i)
  {
    cv::Rect r = cv::boundingRect(cv::Mat(contours_poly.at(i)));
    if (r.area() < 100)
    {
      continue;
    }
    bool inside = false;
    for (unsigned int j = 0; j < contours_poly.size(); ++j)
    {
      if (j == i)
      {
        continue;
      }

      cv::Rect r2 = cv::boundingRect(cv::Mat(contours_poly.at(j)));
      if (r2.area() < 100 || r2.area() < r.area())
      {
        continue;
      }
      if (r.x > r2.x && 
          r.x + r.width < r2.x + r2.width &&
          r.y > r2.y && 
          r.y + r.height < r2.y + r2.height)
      {
        inside = true;
      }
    }
    if (inside == true)
    {
      continue;
    }
    validContours.push_back(contours_poly.at(i));
  }

  // Get bounding rects
  for (unsigned int i = 0; i < validContours.size(); ++i)
  {
    boundRect.at(i) = cv::boundingRect(cv::Mat(validContours.at(i)));
  }

  // Display
  cv::Scalar color(0, 255, 0);
  for(unsigned int i = 0; i < validContours.size(); ++i)
  {
    if(boundRect.at(i).area() < 100)
    {
      continue;
    }
    cv::drawContours(cropped2, validContours, i, color, 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
    cv::rectangle(cropped2, boundRect.at(i).tl(), boundRect.at(i).br(), color, 2, 8, 0);
  }

  //cv::imwrite("example6.jpg", cropped2);
  cv::imshow("Contours", cropped2);
  //extractContours(cropped3, validContours); I don't have the implementation of extractContours
  cv::waitKey(0);
}