Rotate Opencv Matrix by 90, 180, 270 degrees
Solution 1
Use warpAffine.:
Try:
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());
dst
is the final image
Solution 2
The above answers are too complex and hog your CPU. Your question was not arbitrary rotation, but 'Rotate Opencv Matrix by 90, 180, 270 degrees'.
UPDATE 30 JUN 2017:
This functionality is supported by OpenCV, but not documented: https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core.hpp#L1041
void rotate(InputArray src, OutputArray dst, int rotateCode);
with
enum RotateFlags {
ROTATE_90_CLOCKWISE = 0, //Rotate 90 degrees clockwise
ROTATE_180 = 1, //Rotate 180 degrees clockwise
ROTATE_90_COUNTERCLOCKWISE = 2, //Rotate 270 degrees clockwise
};
Original Answer & Arbitrary degree rotation:
You can also do this by using flip and transpose operation, ie for 90CW:
transpose(matSRC, matROT);
flip(matROT, matROT,1); //transpose+flip(1)=CW
etc. Figure out the other commands yourself (thinking=learning) by introducing yourself with the transpose and flip operation form the Docs.
void rot90(cv::Mat &matImage, int rotflag){
//1=CW, 2=CCW, 3=180
if (rotflag == 1){
transpose(matImage, matImage);
flip(matImage, matImage,1); //transpose+flip(1)=CW
} else if (rotflag == 2) {
transpose(matImage, matImage);
flip(matImage, matImage,0); //transpose+flip(0)=CCW
} else if (rotflag ==3){
flip(matImage, matImage,-1); //flip(-1)=180
} else if (rotflag != 0){ //if not 0,1,2,3:
cout << "Unknown rotation flag(" << rotflag << ")" << endl;
}
}
So you call it like this, and note the matrix is passed by reference.
cv::Mat matImage;
//Load in sensible data
rot90(matImage,3); //Rotate it
//Note if you want to keep an original unrotated version of
// your matrix as well, just do this
cv::Mat matImage;
//Load in sensible data
cv::Mat matRotated = matImage.clone();
rot90(matImage,3); //Rotate it
Rotate by arbitrary degrees While I'm at it, here is how to rotate by an arbitrary degree, which i expect to be 50x more expensive. Note that rotation in this manner will include black padding, and edges will be rotated to oustide of the image's original size.
void rotate(cv::Mat& src, double angle, cv::Mat& dst){
cv::Point2f ptCp(src.cols*0.5, src.rows*0.5);
cv::Mat M = cv::getRotationMatrix2D(ptCp, angle, 1.0);
cv::warpAffine(src, dst, M, src.size(), cv::INTER_CUBIC); //Nearest is too rough,
}
Calling this for a rotation of 10.5 degrees then is obviously:
cv::Mat matImage, matRotated;
//Load in data
rotate(matImage, 10.5, matRotated);
I find it remarkable that these kind of extremely basic functions are not part of OpenCV, while OpenCV does have native things like face detection (that's not really maintained with questionable performance). Remarkable.
Cheers
Solution 3
@Abhishek Thakur's answer only works well for rotating the image by 180 degrees. It does not handle the rotation by 90 degrees because
- the center of rotation supplied to
getRotationMatrix2D
is incorrect, and - output matrix size passed to
warpAffline
is incorrect.
Here's the code that rotates an image by 90 degrees:
Mat src = imread("image.jpg");
Mat dst;
double angle = 90; // or 270
Size src_sz = src.size();
Size dst_sz(src_sz.height, src_sz.width);
int len = std::max(src.cols, src.rows);
Point2f center(len/2., len/2.);
Mat rot_mat = cv::getRotationMatrix2D(center, angle, 1.0);
warpAffine(src, dst, rot_mat, dst_sz);
Edit: Another approach to rotate images by 90,180 or 270 degrees involves doing matrix transpose
and then flip
. This method is probably faster.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on July 01, 2020Comments
-
Admin almost 4 years
I'm capturing image from webcam and I need to rotate it by right angle. I found myself theese functions:
getRotationMatrix2D
- to create rotation matrix (whatever it is)transform
- transform one matrix to another by rotation matrix
But, I don't get anything but black area. This is my code:
if(rotate_button.click%4>0) { double angle = (rotate_button.click%4)*90; //button increments its click by 1 per click Mat transform_m = getRotationMatrix2D(Point(cam_frame_width/2, cam_frame_height/2), angle, 1); //Creating rotation matrix Mat current_frame; transform(cam_frame, current_frame, transform_m); //Transforming captured image into a new one cam_frame = Mat((int)current_frame.cols,(int)current_frame.rows, cam_frame_type) = Scalar(0,128,0); //resizing captured matrix, so I can copy the resized one on it current_frame.copyTo(cam_frame); //Copy resized to original }
Outputs just black screen.
-
TimZaman about 10 yearsThis is not in the correct language.
-
TimZaman almost 10 yearsThis answer is valid and great for arbitrary rotation, however, the question was for a 90deg (modulo) rotation. i.e. your affine transform will be i guess dozens of times more computationally intensive than a transpose and flip combination. (see my answer below).
-
Razvan about 8 yearsThanks for the tip, it was really helpful for my use case!
-
marcman almost 8 yearsThis should be the accepted answer for this specific question
-
TimZaman almost 8 yearsThis answer is way too complicated compared to the obvious simple solution given above. The edit refers to a link that uses the simple solution but in a loop and is therefore also slower than my answer already given above.
-
rayryeng about 7 yearsThis is what I was looking for. This is the only answer that specifically focused on rotating the image by multiples of 90 degrees without the need for
warpAffine
. -
tdp2110 almost 7 years@TimZaman: actually it does appear to be in opencv, though I could only find it in source code, not in the docs: github.com/opencv/opencv/blob/master/modules/core/include/…. See
void rotate(InputArray src, OutputArray dst, int rotateCode)
in core.hpp -
tdp2110 almost 7 years@TimZaman: also, I'm not sure about this, but you might need to be careful in your approach that you're reading and writing from the same Mat. It's possible opencv does the right thing here, but it may not.
-
TimZaman almost 7 years@tdp2110 in-place is fine. Thanks for you suggestion! Ipdated the answer.
-
Derek 朕會功夫 over 6 yearsCan confirm
cv2.rotate(img, 1)
works on Python. -
Vlad over 5 yearsTerrible! Affine will interpolate and use a lot of floating point arithmetics. and it is not even Euclidean rigid transform that was asked for. Flipping will be much more effective.
-
ch271828n almost 5 yearsHi! This rotate 90 degree is still very slow... Is there any method to make it faster?
-
Boris Verkhovskiy over 4 yearsEven rotating by 360 degrees with
warpAffine
blurs the image. You can addflags=cv2.INTER_NEAREST
to reduce the blur somewhat, but it's still a noticable degredation.