How to determine the angle of rotation?
There is a square in an image with equal sides (that is inside another square).

Does OpenCV have functions which can help to efficiently calculate the angle?
you can use minAreaRect() function that returns a RotatedRect having angle
you can test the code below
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, gray;
src = imread("e:/test/rr.jpg");
if (src.empty())
return -1;
cvtColor(src, gray, COLOR_BGR2GRAY);
gray = gray > 100;
imshow("gray", gray);
vector<vector<Point> > contours;
findContours(gray.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
RotatedRect _minAreaRect;
for (size_t i = 0; i < contours.size(); ++i)
{
_minAreaRect = minAreaRect(contours[i]);
Point2f pts[4];
_minAreaRect.points(pts);
cout << "minAreaRect.angle: " << _minAreaRect.angle << endl;
for (int j = 0; j < 4; j++)
line(src, pts[j], pts[(j + 1) % 4], Scalar(0, 0, 255), 1, LINE_AA);
}
imshow("result", src);
waitKey(0);
return 0;
}
also see the code below (adopted from the code on stackoverflow)
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
//! Compute the distance between two points
/*! Compute the Euclidean distance between two points
*
* @Param a Point a
* @Param b Point b
*/
static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b)
{
double xDiff = a.x - b.x;
double yDiff = a.y - b.y;
return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}
int main(int argc, char** argv)
{
Mat src, gray;
src = imread(argv[1]);
if (src.empty())
return -1;
cvtColor(src, gray, COLOR_BGR2GRAY);
gray = gray > 100;
imshow("gray", gray);
vector<vector<Point> > contours;
findContours(gray.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
RotatedRect _minAreaRect;
for (size_t i = 0; i < contours.size(); ++i)
{
_minAreaRect = minAreaRect(contours[i]);
Point2f pts[4];
_minAreaRect.points(pts);
double dist0 = distanceBtwPoints(pts[0], pts[1]);
double dist1 = distanceBtwPoints(pts[1], pts[2]);
double angle = 0;
// if (dist0 > dist1 * 4)
angle = atan2(pts[0].y - pts[1].y, pts[0].x - pts[1].x) * 180.0 / CV_PI;
// if (dist1 > dist0 * 4)
// angle = atan2(pts[1].y - pts[2].y, pts[1].x - pts[2].x) * 180.0 / CV_PI;
cout << "minAreaRect.angle: " << _minAreaRect.angle << endl;
cout << "angle: " << angle;
for (int j = 0; j < 4; j++)
line(src, pts[j], pts[(j + 1) % 4], Scalar(0, 0, 255), 1, LINE_AA);
}
imshow("result", src);
waitKey(0);
return 0;
}
Just so it's clear, the slope of a line is defined as rise (change in y) over run (change in x). The arctan(rise/run) function returns the angle in radians. Multiplying that radians by 180 divided by pi gives you the angle in degrees. That is, if the rise over run equals 1, then the angle returned is 45 degrees.
Asked: 2018-12-20 12:55:19 -0600
Seen: 6,528 times
Last updated: Dec 20 '18