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度的结果如下,跟第一种方法是一样的效果,由于一个函数搞定,简洁了很多。