OpenCV將圖像旋轉90度的倍數,如90度、180度、270度,一般有兩種方式:(1) 使用transpose()和flip()兩個函數的組合;(2) OpenCV3 以後可以使用rotate()函數實現圖像旋轉。
1. transpose() + flip()
transpose()實現矩陣的轉置,定義如下:
void cv::transpose( InputArray _src, OutputArray _dst )
flip()實現圖像的翻轉,定義如下:
@param src input array.
@param dst output array of the same size and type as src.
@param flipCode a flag to specify how to flip the array; 0 means
flipping around the x-axis and positive value (for example, 1) means
flipping around y-axis. Negative value (for example, -1) means flipping
around both axes.
*/
CV_EXPORTS_W void flip(InputArray src, OutputArray dst, int flipCode);
代碼中已經解釋得非常清楚,根據參數flipCode的不同,實現不同方向的翻轉:0 - 沿X軸翻轉,正整數 - 沿Y軸翻轉,負整數 - 沿X、Y軸翻轉。flipCode爲負數時,相當於將圖像旋轉180度。
接下來我們就用這兩個函數的組合分別實現圖像的90度、180度、270度旋轉。
定義旋轉函數rotateImage(),根據輸入的旋轉度數實現圖像90度倍數的旋轉。
void rotateImage(Mat &src_img, int degree, Mat &des_img)
{
Mat img_transpose, img_flip;
switch(degree)
{
case 90:
{
transpose(src_img, img_transpose);
imshow("img_transpose", img_transpose);
waitKey(0);
flip(img_transpose, img_flip, 1);
break;
}
case 180:
{
flip(src_img, img_flip, -1);
break;
}
case 270:
{
transpose(src_img, img_transpose);
flip(img_transpose, img_flip, 0);
break;
}
default:
{
printf("The input degree is invalid. \n");
img_flip = src_img;
break;
}
}
img_flip.copyTo(des_img);
}
在主函數中調用該旋轉函數,爲了統計旋轉算法的耗時,封裝了一個計算時間的函數get_time_interval(),精確到毫秒。
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <ctime>
#include <opencv2/opencv.hpp>
#include <opencv2/video/video.hpp>
#include "opencv/cv.h"
#include "opencv/cxcore.h"
using namespace cv;
using namespace std;
// Calculate time interval between current and t_start
int64_t get_time_interval(struct timeval t_start)
{
struct timeval t_curr;
gettimeofday(&t_curr, NULL);
return (t_curr.tv_sec * 1000) + (t_curr.tv_usec / 1000) - ((t_start.tv_sec * 1000) + (t_start.tv_usec / 1000));
}
int main()
{
Mat Img = imread("muyangnv.jpg");
imshow("Img", Img);
Mat outImg_90, outImg_180, outImg_270, outImg_other;
struct timeval t_start;
int64_t t_end;
/********************************* 90 *****************************************/
/* Test rotate 90 degree */
gettimeofday(&t_start, NULL);
rotateImage(Img, 90, outImg_90);
t_end = get_time_interval(t_start);
printf("Image rotate 90 degree uses %ld ms \n", t_end);
/* Save to local storage */
imwrite("outImg_90.bmp", outImg_90);
/********************************* 180 *****************************************/
/* Test rotate 180 degree */
gettimeofday(&t_start, NULL);
rotateImage(Img, 180, outImg_180);
t_end = get_time_interval(t_start);
printf("Image rotate 180 degree uses %ld ms \n", t_end);
imwrite("outImg_180.bmp", outImg_180);
/******************************** 270 ******************************************/
/* Test rotate 270 degree */
gettimeofday(&t_start, NULL);
rotateImage(Img, 270, outImg_270);
t_end = get_time_interval(t_start);
printf("Image rotate 270 degree uses %ld ms \n", t_end);
imwrite("outImg_270.bmp", outImg_270);
/******************************** other ******************************************/
/* Test rotate other degree */
rotateImage(Img, 50, outImg_other);
imwrite("outImg_other.bmp", outImg_other);
return 0;
}
來來,用一張博主的私照來做個測試,時間統計結果爲,每組旋轉算法耗時均爲1ms。
2. rotate()
該函數在我使用OpenCV 3.4.7的時候存在,而在2.4.9上是沒有的。函數相關的聲明如下:
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
};
/** @brief Rotates a 2D array in multiples of 90 degrees.
The function cv::rotate rotates the array in one of three different ways:
* Rotate by 90 degrees clockwise (rotateCode = ROTATE_90_CLOCKWISE).
* Rotate by 180 degrees clockwise (rotateCode = ROTATE_180).
* Rotate by 270 degrees clockwise (rotateCode = ROTATE_90_COUNTERCLOCKWISE).
@param src input array.
@param dst output array of the same type as src. The size is the same with ROTATE_180,
and the rows and cols are switched for ROTATE_90_CLOCKWISE and ROTATE_90_COUNTERCLOCKWISE.
@param rotateCode an enum to specify how to rotate the array; see the enum #RotateFlags
@sa transpose , repeat , completeSymm, flip, RotateFlags
*/
CV_EXPORTS_W void rotate(InputArray src, OutputArray dst, int rotateCode);
從以上聲明可以看出,通過一個函數即可實現對圖像90度、180度、270度(即-90度)的旋轉,至於好不好用,我們來試驗一下:
int main()
{
Mat Img = imread("muyangnv.jpg");
imshow("Img", Img);
Mat outImg_90, outImg_180, outImg_270, outImg_other;
rotate(Img, outImg_90, ROTATE_90_CLOCKWISE);
imwrite("rotate90.bmp", outImg_90);
rotate(Img, outImg_180, ROTATE_180);
imwrite("rotate180.bmp", outImg_180);
rotate(Img, outImg_270, ROTATE_90_COUNTERCLOCKWISE);
imwrite("rotate270.bmp", outImg_270);
return 0;
}
旋轉90度、180度、270度的結果如下,跟第一種方法是一樣的效果,由於一個函數搞定,簡潔了很多。