Rotate cv::Mat using cv::warpAffine offsets destination image
I've found a solution that doesn't involve warpAffine()
.
But before that, I need to state (for future references) that my suspicion was right, you needed to pass the size of the destination when calling warpAffine()
:
warpAffine(image, rotated_img, rot_matrix, rotated_img.size());
As far as I can tell, the black border (caused by writing at an offset) drawed by this function seems to be it's standard behavior. I've noticed this with the C interface and also with the C++ interface of OpenCV running on Mac and Linux, using the versions 2.3.1a and 2.3.0.
The solution I ended up using is much simpler than all this warp thing. You can use cv::transpose()
and cv::flip()
to rotate an image by 90 degrees. Here it is:
Mat src = imread(argv[1], 1);
cv::Mat dst;
cv::transpose(src, dst);
cv::flip(dst, dst, 1);
imwrite("rotated90.jpg", dst);
----I>
OpenCV: how to rotate IplImage?
If you use OpenCV > 2.0 it is as easy as
using namespace cv;
Mat rotateImage(const Mat& source, double angle)
{
Point2f src_center(source.cols/2.0F, source.rows/2.0F);
Mat rot_mat = getRotationMatrix2D(src_center, angle, 1.0);
Mat dst;
warpAffine(source, dst, rot_mat, source.size());
return dst;
}
Note: angle is in degrees, not radians.
See the C++ interface documentation for more details and adapt as you need:
- getRotationMatrix
- warpAffine
Rotate an image without cropping in OpenCV in C++
My answer is inspired by the following posts / blog entries:
- Rotate cv::Mat using cv::warpAffine offsets destination image
- http://john.freml.in/opencv-rotation
Main ideas:
- Adjusting the rotation matrix by adding a translation to the new image center
- Using
cv::RotatedRect
to rely on existing opencv functionality as much as possible
Code tested with opencv 3.4.1:
#include "opencv2/opencv.hpp"
int main()
{
cv::Mat src = cv::imread("im.png", CV_LOAD_IMAGE_UNCHANGED);
double angle = -45;
// get rotation matrix for rotating the image around its center in pixel coordinates
cv::Point2f center((src.cols-1)/2.0, (src.rows-1)/2.0);
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
// determine bounding rectangle, center not relevant
cv::Rect2f bbox = cv::RotatedRect(cv::Point2f(), src.size(), angle).boundingRect2f();
// adjust transformation matrix
rot.at<double>(0,2) += bbox.width/2.0 - src.cols/2.0;
rot.at<double>(1,2) += bbox.height/2.0 - src.rows/2.0;
cv::Mat dst;
cv::warpAffine(src, dst, rot, bbox.size());
cv::imwrite("rotated_im.png", dst);
return 0;
}
Combining two warpAffine, shift and rotate image
You have to multiply the matrices. Add third row [0,0,1] to the 2x3 matrices. This is called homogeneous coordinates.
M = np.float32([[1,0,20],[0,1,10],[0,0,1]]) // shift matrix
center_of_rot = (500, 500)
Rot = cv2.getRotationMatrix2D(center_of_rot, 1.23, 1.0)
Rot = np.vstack([Rot, [0,0,1]])
TransfomMatrix = np.matmul(M, Rot)
rotated = cv2.warpPerspective(img, TransformMatrix, (y_size, x_size),flags=cv2.INTER_LANCZOS4) // note - warpPerspective is used here, because the matrix is now 3x3 not 3x2
Related Topics
How to Specify Setprecision Rounding
What Would Be C++ Limitations Compared C Language
C++ Templates Specialization Syntax
Is #Pragma Once Part of the C++11 Standard
Do Current X86 Architectures Support Non-Temporal Loads (From "Normal" Memory)
What Is Decltype with Two Arguments
C/C++ Changing the Value of a Const
Why Lifetime of Temporary Doesn't Extend Till Lifetime of Enclosing Object
The Behaviour of Floating Point Division by Zero
Efficient Bitwise Operations for Counting Bits or Find the Right|Left Most Ones
Gcc Linker Can't Find Standard Library
Override Compile Flags for Single Files
Why Is Std::Min Failing When Windows.H Is Included
When Should You Use the "This" Keyword in C++
In C++11, Does 'I += ++I + 1' Exhibit Undefined Behavior
Cuda How to Get Grid, Block, Thread Size and Parallalize Non Square Matrix Calculation