1 | initial version |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// vector<RotatedRect> minEllipse;
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// second argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or non-convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.
2 | No.2 Revision |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// vector<RotatedRect> minEllipse;
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// second the third argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or non-convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.
3 | No.3 Revision |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// vector<RotatedRect> minEllipse;
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// the third argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or non-convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
imshow("contours", dst);
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.
4 | No.4 Revision |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// vector<RotatedRect> minEllipse;
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// the third argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or non-convex convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
imshow("contours", dst);
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.
5 | No.5 Revision |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// vector<RotatedRect> minEllipse;
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// the third argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
imshow("contours", dst);
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.
6 | No.6 Revision |
Actually, you can use the approxPolyDP() function and approximate your contours with accuracy proportional to the contour perimeter. Here is some code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/// Load image
Mat src = imread( "holes.jpg");
if( !src.data )
{ return -1; }
// Show source image
imshow("src", src);
// Create binary image from source image
Mat bw;
cvtColor(src, bw, CV_BGR2GRAY);
threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("bin", bw);
// Find contours
vector<Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = Mat::zeros(bw.size(), CV_8UC1);
// Loop through detected contours, and process accordingly
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter with approxPolyDP. In this,
// the third argument is called epsilon, which is maximum
// distance from contour to approximated contour. It is
// an accuracy parameter. A wise selection of epsilon is
//needed to get the correct output.
double epsilon = cv::arcLength(cv::Mat(contours[i]), true) * 0.1; // epsilon = 10% of arc length
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
epsilon,
true
);
// Skip small or convex objects
if (std::fabs(cv::contourArea(contours[i])) < 500 || cv::isContourConvex(approx))
continue;
drawContours(dst, contours, i, Scalar(255, 255, 255), CV_FILLED, 8, hierarchy, 0, Point());
}
imshow("contours", dst);
// sum two images
dst += bw;
imshow("output", dst);
waitKey(0);
return 0;
}
of course you should play with the epsilon value in order to pick a value robust enough for all of your cases. Enjoy.