I tried to calculate contour perimeter using arcLength
. The contour is read from the file into Mat
which is a black and white picture of contour only.
However, when I pass this Mat
into function it throws an error:
Assertion failed (curve.checkVector(2) >= 0 && (curve.depth() == CV_32F || curve.depth() == CV_32S)) in arcLength
I have figured out that the actual cause is that curve.checkVector(2)
returns -1. Although I have read the documentation about this method I still do not understand how to fix this error.
Here is the test image with corner points (1,1), (1,21), (21,21), (21,1)
The contour should be (from OpenCV doc):
Input vector of 2D points, stored in std::vector or Mat.
not a b/w image.
You can compute the perimeter is different ways. The most robust is to use findContours
to find external contours only (RETR_EXTERNAL
), and call arcLength
on that contour.
A few examples:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Method 1: length of unsorted points
// NOTE: doesn't work!
vector<Point> points;
findNonZero(img, points);
double len1 = arcLength(points, true);
// 848.78
// Method 2: length of the external contour
vector<vector<Point>> contours;
findContours(img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); // Retrieve only external contour
double len2 = arcLength(contours[0], true);
// 80
// Method 3: length of convex hull of contour
// NOTE: convex hull based methods work reliably only for convex shapes.
vector<Point> hull1;
convexHull(contours[0], hull1);
double len3 = arcLength(hull1, true);
// 80
// Method 4: length of convex hull of unsorted points
// NOTE: convex hull based methods work reliably only for convex shapes.
vector<Point> hull2;
convexHull(points, hull2);
double len4 = arcLength(hull2, true);
// 80
// Method 5: number of points in the contour
// NOTE: this will simply count the number of points in the contour.
// It works only if:
// 1) findContours was used with option CHAIN_APPROX_NONE.
// 2) the contours is thin (has thickness of 1 pixel).
double len5 = contours[0].size();
// 80
return 0;
}