1 | initial version |
Just another solution. You can specify an arbitrary angle but not the center point of the rotation. The output size of the image is automatically calculated.
#include <iostream>
#include "opencv2/opencv.hpp"
// Return the rotation matrices for each rotation
void rotate(cv::Mat& src, double angle, cv::Mat& dst) {
cv::Mat r = getRotationMatrix2D(cv::Point2f(), angle, 1.0);
//4 coordinates of the image
std::vector<cv::Point2f> corners(4);
corners[0] = cv::Point2f(0, 0);
corners[1] = cv::Point2f(0, src.rows);
corners[2] = cv::Point2f(src.cols, 0);
corners[3] = cv::Point2f(src.cols, src.rows);
std::vector<cv::Point2f> cornersTransform(4);
cv::transform(corners, cornersTransform, r);
//Copy the 2x3 transformation matrix into a 3x3 transformation matrix
cv::Mat H = cv::Mat::eye(3, 3, CV_64F);
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 3; j++) {
H.at<double>(i, j) = r.at<double>(i, j);
}
}
double offsetX = 0.0, offsetY = 0.0, maxX = 0.0, maxY = 0.0;
//Get max offset outside of the image and max width / height
for(size_t i = 0; i < 4; i++) {
if(cornersTransform[i].x < offsetX) {
offsetX = cornersTransform[i].x;
}
if(cornersTransform[i].y < offsetY) {
offsetY = cornersTransform[i].y;
}
if(cornersTransform[i].x > maxX) {
maxX = cornersTransform[i].x;
}
if(cornersTransform[i].y > maxY) {
maxY = cornersTransform[i].y;
}
}
offsetX = -offsetX;
offsetY = -offsetY;
maxX += offsetX;
maxY += offsetY;
cv::Size size_warp(maxX, maxY);
//Create the transformation matrix to be able to have all the pixels
cv::Mat H2 = cv::Mat::eye(3, 3, CV_64F);
H2.at<double>(0,2) = offsetX;
H2.at<double>(1,2) = offsetY;
warpPerspective(src, dst, H2*H, size_warp);
}
int main() {
// Read in the image
cv::Mat input;
cv::VideoCapture capture("http://answers.opencv.org/upfiles/14303105806441826.jpg");
if(!capture.isOpened()) {
return -1;
}
capture >> input;
if(input.empty()) {
return -1;
}
cv::resize(input, input, cv::Size(), 0.5, 0.5);
imshow("input", input);
cv::Mat rotated;
for(double angle = 0; angle < 360; angle += 1.0) {
rotate(input, angle, rotated);
cv::imshow("rotated", rotated);
char c = cv::waitKey(30);
if(c == 27) {
break;
}
}
return 0;
}