opencv—图像旋转函数,rotate与warpAffine运用(不裁剪crop方法)

本文介绍了OpenCV中图像旋转函数rotate与warpAffine的运用,阐述了图像旋转基本原理,包括背景处理和插值方法。讲解了两个函数的原型,还进行了代码演示。不过代码存在不足,图像四周有裁剪,问题主要出在旋转矩阵中心点平移和数值转换偏差上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

opencv—图像旋转函数,rotate与warpAffine运用(不裁剪crop方法)

引言Oo

图像旋转是图像几何变换中具有代表性的操作,直接调用opencv库函数很简单,但是叫你讲解一下,可能能多人会直接放弃。这里面包含了插值、背景处理、三角函数等一些知识,我也今早看了一篇推文,自己写了一下,发现还是有很多基础知识,于是作一次记录。

图像旋转基本原理

图像旋转之后大小会有变化,就会产生背景,背景一般默认填充为黑色,即0值。同时,原本的和新产生的像素会发生位置迁移,新的位置的像素需要进行插值进行处理,插值处理包括最近邻、线性插值和立方插值等方法(默认为二插值)。
这是旋转后的高度映射,
在这里插入图片描述

//h和w为原图像的高与宽,CV_PI/180等于弧度制中角度1度对应的值
int bound_w = (h * fabs(sin(angle * CV_PI / 180)) + w * fabs(cos(angle * CV_PI / 180))) ;
int bound_h = (h * fabs(cos(angle * CV_PI / 180)) + w * fabs(sin(angle * CV_PI / 180)));

这是简写的旋转矩阵,2*3的矩阵:
在这里插入图片描述
原本图像的左上角是 原点,要实现中心旋转,旋转 矩阵需要重新计算,
在这里插入图片描述
其中scale是表示支持旋转与放缩,第三列就是易错点,图像旋转之后中心位置的平移量

函数讲解

我们在opencv中找到两个函数支持旋转,其中一个是Rotate,另一个是WarpAffine
Rotate函数原型:

//函数原型,可以看出它只支持90、180、270这样的特殊角度旋转
CV_EXPORTS_W void rotate(InputArray src, OutputArray dst, int rotateCode);
//下面为源码解释
/** @brief Fills the output array with repeated copies of the input array.

The function cv::repeat duplicates the input array one or more times along each of the two axes:
\f[\texttt{dst} _{ij}= \texttt{src} _{i\mod src.rows, \; j\mod src.cols }\f]
The second variant of the function is more convenient to use with @ref MatrixExpressions.
@param src input array to replicate.
@param ny Flag to specify how many times the `src` is repeated along the
vertical axis.
@param nx Flag to specify how many times the `src` is repeated along the
horizontal axis.
@param dst output array of the same type as `src`.
@sa cv::reduce
*/
//第三个参数可选
ROTATE_180,
ROTATE_90_CLOCKWISE,
ROTATE_90_COUNTERCLOCKWISE 

可以看出它只支持90、180、270这样的特殊角度旋转。

函数warpAffine支持任意角度的旋转,但通过定义M矩阵实现,
函数原型:

CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,//输入与输出图像
                              InputArray M,//旋转矩阵 
                              Size dsize,//输出大小
                              int flags = INTER_LINEAR,插值方式 
                              int borderMode = BORDER_CONSTANT,背景填充默认为常量
                              const Scalar& borderValue = Scalar());//填充默认为黑色

到此我们可以看到,我们需要生成一个旋转矩阵M,opencv也提供了函数getRotationMatrix2D,
函数原型:


Mat getRotationMatrix2D(Point2f center, 
						double angle,
						 double scale);

代码演示

演示平台win10,vs2019,opencv4.4

//对图像进行旋转,不crop的方法,对旋转矩阵的参数修改,以及输出Size大小的确认
#include"opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv;
int main() {
	Mat src = imread("timg.jpg");
	Mat des,m;
	//des = src;
	//rotate(src, des, ROTATE_90_COUNTERCLOCKWISE);
	Point2f center = Point(src.cols / 2, src.rows / 2);
	double angle = 50,scale=0.5;
	int h = src.cols,w=src.rows;
	//目标图像的大小,避免crop,fabs(sin(angle * CV_PI / 180)
	int bound_w = (h * fabs(sin(angle * CV_PI / 180)) + w * fabs(cos(angle * CV_PI / 180))) * scale;
	int bound_h = (h * fabs(cos(angle * CV_PI / 180)) + w * fabs(sin(angle * CV_PI / 180))) * scale;
	m = getRotationMatrix2D(center, angle, scale);
	m.at<double>(0, 2) += (bound_w - src.cols) / 2;
	m.at<double>(1, 2) += (bound_h - src.rows) / 2;
	
	warpAffine(src,des,m,Size2i(bound_h,bound_w));
	imshow("image",des);
	waitKey();
	return 0;
}

原图
效果图
在这里插入图片描述

不足点

图像的四周还是有裁剪到,说明这个代码还是有bug的,但问题不大,主要就是在旋转矩阵中心点的平移上,还有就是不同类型的数值转换造成的数值偏差。暂时做一下记录,以后有空继续看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值