thanks for StevenPuttemans,I have get the final slove
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/photo.hpp"
using namespace std;
using namespace cv;
#define DEBUG FALSE
Point2f GetPointAfterRotate(Point2f inputpoint,Point2f center,double angle){
Point2d preturn;
preturn.x = (inputpoint.x - center.x)*cos(-angle) - (inputpoint.y - center.y)*sin(-angle)+center.x;
preturn.y = (inputpoint.x - center.x)*sin(-angle) + (inputpoint.y - center.y)*cos(-angle)+center.y;
return preturn;
}
Point GetPointAfterRotate(Point inputpoint,Point center,double angle){
Point preturn;
preturn.x = (inputpoint.x - center.x)*cos(-1*angle) - (inputpoint.y - center.y)*sin(-1*angle)+center.x;
preturn.y = (inputpoint.x - center.x)*sin(-1*angle) + (inputpoint.y - center.y)*cos(-1*angle)+center.y;
return preturn;
}
double getOrientation(vector<Point> &pts, Point2f& pos,Mat& img)
{
//Construct a buffer used by the pca analysis
Mat data_pts = Mat(pts.size(), 2, CV_64FC1);
for (int i = 0; i < data_pts.rows; ++i)
{
data_pts.at<double>(i, 0) = pts[i].x;
data_pts.at<double>(i, 1) = pts[i].y;
}
//Perform PCA analysis
PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
//Store the position of the object
pos = Point2f(pca_analysis.mean.at<double>(0, 0),
pca_analysis.mean.at<double>(0, 1));
//Store the eigenvalues and eigenvectors
vector<Point2d> eigen_vecs(2);
vector<double> eigen_val(2);
for (int i = 0; i < 2; ++i)
{
eigen_vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0),
pca_analysis.eigenvectors.at<double>(i, 1));
eigen_val[i] = pca_analysis.eigenvalues.at<double>(i,0);
}
return atan2(eigen_vecs[0].y, eigen_vecs[0].x);
}
int main( int argc, char** argv )
{
Mat img = imread("e:/sandbox/leaf.jpg");
pyrDown(img,img);
pyrDown(img,img);
Mat bw;
bool dRet;
cvtColor(img, bw, COLOR_BGR2GRAY);
threshold(bw, bw, 150, 255, CV_THRESH_BINARY);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (size_t i = 0; i < contours.size(); ++i)
{
double area = contourArea(contours[i]);
if (area < 1e2 || 1e5 < area) continue;
Point2f* pos = new Point2f();
double dOrient = getOrientation(contours[i], *pos,img);
int xmin = 99999;
int xmax = 0;
int ymin = 99999;
int ymax = 0;
for (size_t j = 0;j<contours[i].size();j++)
{
contours[i][j] = GetPointAfterRotate(contours[i][j],(Point)*pos,dOrient);
if (contours[i][j].x < xmin)
xmin = contours[i][j].x;
if (contours[i][j].x > xmax)
xmax = contours[i][j].x;
if (contours[i][j].y < ymin)
ymin = contours[i][j].y;
if (contours[i][j].y > ymax)
ymax = contours[i][j].y;
}
Point lt = Point(xmin,ymin);
Point ld = Point(xmin,ymax);
Point rd = Point(xmax,ymax);
Point rt = Point(xmax,ymin);
drawContours(img, contours, i, CV_RGB(255, 0, 0), 2, 8, hierarchy, 0);
lt = GetPointAfterRotate((Point)lt,(Point)*pos,-dOrient);
ld = GetPointAfterRotate((Point)ld,(Point)*pos,-dOrient);
rd = GetPointAfterRotate((Point)rd,(Point)*pos,-dOrient);
rt = GetPointAfterRotate((Point)rt,(Point)*pos,-dOrient);
line( img, lt, ld,Scalar(0,255,255),2);
line( img, lt, rt,Scalar(0,255,255),2);
line( img, rd, ld,Scalar(0,255,255),2);
line( img, rd, rt,Scalar(0,255,255),2);
}
return 0;
}
maybe:
and rotate back? i dont think it is Elegant.
and there is another proble
just give the orientation,but i also want the width and length.
Once you have the orientation, you can warp to a fixed upright position and then calculate width and height right?