#include <opencv2opencv.hpp> /* @param o The customer origin @param x The customer x @Note The return matrix include translation */ cv::Mat ZRotationMatrix(const cv::Point2d o, const cv::Point2d x) { cv::Mat Rz = cv::Mat::zeros(3, 3, CV_32FC1); Rz.at<float>(2, 2) = 1.0; double theta = std::atan((x.y - o.y) / (x.x - o.x)); Rz.at<float>(0, 0) = std::cos(theta); Rz.at<float>(1, 0) = std::sin(theta); Rz.at<float>(0, 1) = -Rz.at<float>(1, 0); Rz.at<float>(1, 1) = Rz.at<float>(0, 0); // Adding Translation Rz.at<float>(0, 2) = static_cast<float>(x.x); Rz.at<float>(1, 2) = static_cast<float>(x.y); Rz.at<float>(2, 2) = 0; return Rz; } /* Called by Rotation() */ std::pair<int, int> dstImageRegion(const cv::Mat points ) { CV_Assert(points.size() == cv::Size(4, 3)); float maxRow(0.0), maxCol(0.0); for (size_t i=0; i<4; ++i) { // x maxCol = maxCol < points.at<float>(0, i) ? points.at<float>(0, i) : maxCol; // y maxRow = maxRow < points.at<float>(1, i) ? points.at<float>(1, i) : maxRow; } return {maxRow, maxCol}; } /* @Param Rz It includes the translation also! */ cv::Mat Rotation(const cv::Mat src, const cv::Mat Rz) { // get region of dst cv::Mat Corners_src((cv::Mat_<float>(3,4) << 0, src.cols, 0, src.cols, 0, 0, src.rows, src.rows, 1, 1, 1, 1 )); cv::Mat Corners_dst = Rz * Corners_src; std::pair<int, int> size_dst = dstImageRegion(Corners_dst); cv::Mat dst = cv::Mat::zeros(size_dst.first, size_dst.second, src.type()); // Rz is the matrix from src to dst. The inverse matrix is needed to reconstruct dst. cv::Mat Rz_inv = Rz.clone(); // The inverse matrix of Rotation is the same as its transpose matrix. Rz_inv.at<float>(0, 1) = Rz.at<float>(1, 0); Rz_inv.at<float>(1, 0) = Rz.at<float>(0, 1); // Set pixels value for (size_t j=0; j<dst.rows; ++j) { for (size_t i = 0; i < dst.cols; ++i) { cv::Mat tp_src = Rz_inv * cv::Mat((cv::Mat_<float>(3,1) << i,j,1)); int Idx_src(cvRound(tp_src.at<float>(0))), Idy_src(cvRound(tp_src.at<float>(1))); if (Idx_src<0.0 || Idx_src>=src.cols || Idy_src<0.0 || Idy_src>=src.rows) continue; dst.at<float>(j, i) = src.at<float>(Idy_src, Idx_src); } } return dst; } int main() { cv::Mat img = cv::imread("1.PNG", CV_LOAD_IMAGE_GRAYSCALE); img.convertTo(img, CV_32FC1); // cv::Mat Rz = ZRotationMatrix(cv::Point2d(10,10), cv::Point2d(20, 5)); cv::Mat img_d = Rotation(img, Rz); return 0; }