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