您可以使用PCA獲取矩形方位(第1和第2部分)的邊,使這些軸方向可以計算旋轉角度。例如這裏:http://docs.opencv.org/3.1.0/d1/dee/tutorial_introduction_to_pca.html
只是做另一種變體的草圖:
#include <iostream>
#include <vector>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
void getSamplePoints(Mat& src,vector<Point2f>& pts)
{
pts.clear();
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
uchar v = src.at<uchar>(i, j);
if (v > 0)
{
pts.push_back(Point2f(j, i));
}
}
}
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
double distance_to_Line(cv::Point2f line_start, cv::Point2f line_end, cv::Point2f point)
{
double normalLength = _hypot(line_end.x - line_start.x, line_end.y - line_start.y);
double distance = (double)((point.x - line_start.x) * (line_end.y - line_start.y) - (point.y - line_start.y) * (line_end.x - line_start.x))/normalLength;
return distance;
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
void getPointsFromVector(vector<Point2f>& pts,Point2f p1, Point2f p2, float dist, vector<Point2f>& pts_res)
{
for (int i = 0; i < pts.size(); ++i)
{
double d = distance_to_Line(p1, p2, pts[i]);
if (fabs(d) < dist)
{
pts_res.push_back(pts[i]);
}
}
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
int main(int argc, unsigned int** argv)
{
string fname = "../../data/rect_to_fit.png";
Mat src = imread(fname, 1);
if (src.empty())
{
return 0;
}
cvtColor(src, src, COLOR_BGR2GRAY);
vector<Point2f> pts;
getSamplePoints(src, pts);
RotatedRect R = minAreaRect(pts);
Point2f r_pts[4];
R.points(r_pts);
for (int j = 0; j < 4; j++)
{
vector<Point2f> res_pts;
Point2f p1 = r_pts[j];
Point2f p2 = r_pts[(j + 1) % 4];
getPointsFromVector(pts,p1,p2,20, res_pts);
for (auto p : res_pts)
{
circle(src, p, 3, Scalar::all(255), -1);
}
// imshow("src", src);
// waitKey(0);
Vec4f L;
fitLine(res_pts, L, cv::DIST_L2, 0, 0.01, 0.01);
float x = L[2];
float y = L[3];
float vx = L[0];
float vy = L[1];
float lefty = int((-x*vy/vx) + y);
float righty = int(((src.cols - x)*vy/vx) + y);
line(src, Point2f(src.cols - 1, righty), Point2f(0, lefty), Scalar::all(255), 2);
}
imshow("src", src);
imwrite("result.jpg", src);
waitKey(0);
return 0;
}
我得到的結果是:
謝謝!我首先嚐試PCA。一旦我得到我的第一個結果,我會給你反饋! – areify
PCA給出了點的最長分佈的方向,如果是方形的,它可能會給出對角線的方向。 PCA將適用於重塑或其他細長物體。對於正方形的你可能需要使用RANSAC方法。 –
PCA不給我任何好的方法,你可以在這裏看到:[例子](http://i68.tinypic.com/2cs72bt.png)。我認爲這也是一個糟糕的對角線接近... – areify