OpenCV图像逆时针旋转90度
updated @ 2022.1.28
方法
三种方法:
- 水平翻转 + 转置: flip + transpose。 先flip或先transpose均可
- 用仿射变换实现: warpAffine
- 调用 rotate 函数
方法3最简单,方法1其次。
对于不懂仿射变换的人来说,方法2有可能正确,也可能得到错误结果:
- 很多博客是用 n x n 的方形图像做测试,旋转前后的图像中心点没有变化, 也就是纯粹的旋转,结果确实正确
- 如果测试图像换成长方形的, 例如 100 x 200 的尺寸,需要考虑:
-
- 结果图的尺寸, 是原图尺寸颠倒过来: (w, h) -> (h, w)
-
- 图像中心点发生了平移: (w/2, h/2) -> (h/2, w/2), 需要手动改仿射变换矩阵M (增加中心点变化导致的平移向量)
- 图像中心点平移的解释: 图像左上角需要始终保持为(0,0)坐标,因而旋转后需要平移回来
-
代码
Python
#coding:utf-8
import cv2
def rotate_method1(src):
dst = cv2.flip(src, 1) #原型:cv2.flip(src, flipCode[, dst]) → dst flipCode表示对称轴 0:x轴 1:y轴. -1:both
dst = cv2.transpose(dst)
return dst
def rotate_method2(src):
height, width, channels = src.shape
src_center = (width/2, height/2)
print("src_center:", src_center)
angle = 90
scale = 1.0
rot_mat = cv2.getRotationMatrix2D(src_center, angle, scale)
dsize = (height, width)
dst_center = (src_center[1], src_center[0])
rot_mat[0, 2] += (dst_center[0] - src_center[0])
rot_mat[1, 2] += (dst_center[1] - src_center[1])
print("dsize:", dsize)
print("rot_mat:", rot_mat)
dst = cv2.warpAffine(src, rot_mat, dsize, flags=cv2.INTER_LINEAR)
return dst
def rotate_method3(src):
dst = cv2.rotate(src, cv2.ROTATE_90_COUNTERCLOCKWISE)
return dst
if __name__ == '__main__':
src = cv2.imread('../assets/1920x1080.jpg')
dst1 = rotate_method1(src)
cv2.imwrite("rotate90_method1.jpg", dst1)
dst2 = rotate_method2(src)
cv2.imwrite("rotate90_method2.jpg", dst2)
dst3 = rotate_method3(src)
cv2.imwrite("rotate90_method3.jpg", dst3)
C++
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include "plain/opencv_helper.hpp"
void rotate_method1(const cv::Mat& src, cv::Mat& dst)
{
cv::flip(src, dst, 1);
cv::transpose(dst, dst);
}
void rotate_method2(const cv::Mat& src, cv::Mat& dst)
{
cv::Size ssize = src.size();
int height = ssize.height;
int width = ssize.width;
cv::Point2f src_center(src.size()/2);
std::cout << "src_center:" << src_center << std::endl;
double angle = 90;
double scale = 1;
cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, angle, scale);
// manually do center point translation
cv::Point2f dst_center;
dst_center.x = src_center.y;
dst_center.y = src_center.x;
rot_mat.ptr<double>(0, 2)[0] += (dst_center.x - src_center.x);
rot_mat.ptr<double>(1, 2)[0] += (dst_center.y - src_center.y);
// std::cout << rot_mat << std::endl;
cv::Size dsize;
dsize.height = ssize.width;
dsize.width = ssize.height;
std::cout << "dsize:" << dsize << std::endl;
std::cout << "rot_mat:" << rot_mat << std::endl;
cv::warpAffine(src, dst, rot_mat, dsize, cv::INTER_LINEAR);
}
void rotate_method3(const cv::Mat& src, cv::Mat& dst)
{
cv::rotate(src, dst, cv::ROTATE_90_COUNTERCLOCKWISE);
}
int main()
{
std::string image_path = "1920x1080.jpg";
cv::Mat src = cv::imread(image_path);
cv::Mat dst1;
rotate_method1(src, dst1);
cv::imwrite("rotate90_method1.jpg", dst1);
cv::Mat dst2;
rotate_method2(src, dst2);
cv::imwrite("rotate90_method2.jpg", dst2);
cv::Mat dst3;
rotate_method3(src, dst3);
cv::imwrite("rotate90_method3.jpg", dst3);
return 0;
}
Greatness is never a given, it must be earned.