#include"opencv2/highgui/highgui.hpp"
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
void CalcRotateMatrix(const cv::Mat& img, float degree, cv::Mat& trans_mat, cv::Size& dst_size){
degree = fmod(degree + 360.0f, 360.0f);
double angle = degree * CV_PI / 180.;
int width = img.cols;
int height = img.rows;
double a = sin(angle), b = cos(angle);
int widthRotate = int(height * fabs(a) + width * fabs(b));
int heightRotate = int(width * fabs(a) + height * fabs(b));
// int widthRotate = width;
// int heightRotate = height;
// [ m0 m1 m2 ] ===> [ A11 A12 b1 ]
// [ m3 m4 m5 ] ===> [ A21 A22 b2 ]
trans_mat.create(2, 3, CV_32F);
float *map = (float *)trans_mat.ptr<float>();
CvPoint2D32f center = cvPoint2D32f(width / 2.0f, height / 2.0f);
CvMat mapMatrix = trans_mat;
cv2DRotationMatrix(center, degree, 1.0f, &mapMatrix);
map[2] += (widthRotate - width) / 2.0f;
map[5] += (heightRotate - height) / 2.0f;
dst_size = cv::Size(widthRotate, heightRotate);
}
std::vector<cv::Point> PointAffine(const std::vector<cv::Point>& points, const cv::Mat& trans_mat){
float *m = (float *)trans_mat.ptr<float>();
vector<Point> transPoints;
for(size_t i = 0; i < points.size(); i++)
{
Point p = points[i];
int x = p.x * m[0] + p.y * m[1] + m[2];
int y = p.x * m[3] + p.y * m[4] + m[5];
transPoints.push_back(Point(x, y));
}
return transPoints;
}
int main()
{
Mat img = imread("/data_2/everyday/1228/plane.png");
Point pt(285,67);
circle(img,pt,13,Scalar(0,0,255),2);
float angle = 32.5;
Mat M;
Mat img_rot, img_roi;
Size dst_size;
vector<Point> rot_points;
CalcRotateMatrix(img, angle, M, dst_size);
warpAffine(img, img_rot, M, dst_size, 1, 0, 0);
std::vector<cv::Point> points,points_rot;
points.push_back(pt);
points_rot = PointAffine(points, M);
Point pt_rot = points_rot[0];
circle(img_rot,pt_rot,13,Scalar(255,0,255),2);
imshow("img",img);
imshow("img_rot",img_rot);
waitKey(0);
return 0;
}
通過旋轉角度可以求得旋轉矩陣,然后原圖中的一個點通過旋轉矩陣可以對應到旋轉之后的圖。但是問題來了,已知旋轉矩陣,旋轉后的圖上的一個點,能對應到原圖上面去嗎???
經過分析原圖上面點通過防射變換矩陣旋轉到旋轉之后的圖上,這段代碼如下:
Point p = points[i];
int x = p.x * m[0] + p.y * m[1] + m[2];
int y = p.x * m[3] + p.y * m[4] + m[5];
我們現在是已知旋轉矩陣,旋轉后的圖上的一個點,即x,y已知,所有m已知,要求的是p.x,p.y,二元一次方程組可以求出來。所以代碼如下:
float *m = (float *)M.ptr<float>();
int xx = (m[4]*pt_rot.x-m[2]*m[4]-m[1]*pt_rot.y+m[1]*m[5])*1.0/MAX((m[0]*m[4]-m[1]*m[3]),0.01);
int yy = (pt_rot.y-m[5]-m[3]*xx)*1.0/MAX(m[4],0.01);
#include"opencv2/highgui/highgui.hpp"
#include"opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
void CalcRotateMatrix(const cv::Mat& img, float degree, cv::Mat& trans_mat, cv::Size& dst_size){
degree = fmod(degree + 360.0f, 360.0f);
double angle = degree * CV_PI / 180.;
int width = img.cols;
int height = img.rows;
double a = sin(angle), b = cos(angle);
int widthRotate = int(height * fabs(a) + width * fabs(b));
int heightRotate = int(width * fabs(a) + height * fabs(b));
// int widthRotate = width;
// int heightRotate = height;
// [ m0 m1 m2 ] ===> [ A11 A12 b1 ]
// [ m3 m4 m5 ] ===> [ A21 A22 b2 ]
trans_mat.create(2, 3, CV_32F);
float *map = (float *)trans_mat.ptr<float>();
CvPoint2D32f center = cvPoint2D32f(width / 2.0f, height / 2.0f);
CvMat mapMatrix = trans_mat;
cv2DRotationMatrix(center, degree, 1.0f, &mapMatrix);
map[2] += (widthRotate - width) / 2.0f;
map[5] += (heightRotate - height) / 2.0f;
dst_size = cv::Size(widthRotate, heightRotate);
}
std::vector<cv::Point> PointAffine(const std::vector<cv::Point>& points, const cv::Mat& trans_mat){
float *m = (float *)trans_mat.ptr<float>();
vector<Point> transPoints;
for(size_t i = 0; i < points.size(); i++)
{
Point p = points[i];
int x = p.x * m[0] + p.y * m[1] + m[2];
int y = p.x * m[3] + p.y * m[4] + m[5];
transPoints.push_back(Point(x, y));
}
return transPoints;
}
int main()
{
Mat img = imread("/data_2/everyday/1228/plane.png");
Point pt(285,67);
circle(img,pt,13,Scalar(0,0,255),2);
float angle = 32.5;
Mat M;
Mat img_rot, img_roi;
Size dst_size;
vector<Point> rot_points;
CalcRotateMatrix(img, angle, M, dst_size);
warpAffine(img, img_rot, M, dst_size, 1, 0, 0);
std::vector<cv::Point> points,points_rot;
points.push_back(pt);
points_rot = PointAffine(points, M);
Point pt_rot = points_rot[0];
circle(img_rot,pt_rot,13,Scalar(255,0,255),2);
float *m = (float *)M.ptr<float>();
int xx = (m[4]*pt_rot.x-m[2]*m[4]-m[1]*pt_rot.y+m[1]*m[5])*1.0/MAX((m[0]*m[4]-m[1]*m[3]),0.01);
int yy = (pt_rot.y-m[5]-m[3]*xx)*1.0/MAX(m[4],0.01);
circle(img,Point(xx,yy),33,Scalar(255,0,0),2);
imshow("img",img);
imshow("img_rot",img_rot);
waitKey(0);
return 0;
}