组合算法:GetRotationMatrix2D + WarpAffine
一、GetRotationMatrix2D 函数(获取旋转矩阵)
函数作用
生成一个 2×3 的仿射旋转矩阵,用于描述:
- 绕哪个点旋转(中心点)
- 旋转多少度
- 旋转时是否缩放
Mat GetRotationMatrix2D(
Point2f center, // 旋转中心点
double angle, // 旋转角度(°)
double scale // 缩放系数
);
逐参数详解
表格
| 参数名 | 类型 | 含义 & 详细说明 |
|---|---|---|
| center | Point2f | 旋转中心点通常用 图像中心:new Point2f(cols/2f, rows/2f)x = 宽度 / 2,y = 高度 / 2 |
| angle | double | 旋转角度(度)✅ 正数 = 逆时针旋转❌ 负数 = 顺时针旋转例:90 → 逆时针转 90°;-45 → 顺时针转 45° |
| scale | double | 缩放比例1.0 = 不缩放0.5 = 缩小一半2.0 = 放大一倍 |
关键常识
- 返回的
Mat是 2 行 3 列 的旋转矩阵 - 这个矩阵不会自动处理画布大小,旋转后图像会被裁剪
GetRotationMatrix2D 参数
- center:旋转中心点,默认图像中心
- angle:旋转角度
- 范围:-360 ~ 360
- 正负效果:正数逆时针、负数顺时针
- scale:缩放系数
- 默认:1.0
- 范围:0.1 ~ 2.0
二、WarpAffine 函数(执行仿射变换 / 旋转)
函数作用
根据旋转矩阵,对图像做仿射变换,真正完成旋转。
void WarpAffine(
InputArray src, // 源图像
OutputArray dst, // 输出图像
InputArray M, // 旋转矩阵(来自上面)
Size dsize, // 输出图像尺寸
int flags = InterpolationFlags.Linear, // 插值方式
InterpolationFlags borderMode = InterpolationFlags.Constant,
Scalar borderValue = new Scalar()
);
逐参数详解
表格
| 参数名 | 含义 & 必记要点 |
|---|---|
| src | 输入图像(要旋转的图) |
| dst | 输出图像(旋转后的结果) |
| M | 旋转矩阵 → 直接传 GetRotationMatrix2D 的结果 |
| dsize | 输出图像的宽和高⚠️ 格式:new Size(宽度, 高度)⚠️ 和原图相反:OpenCV 永远是 (宽,高) |
| flags | 插值算法(决定旋转画质)推荐:- Cubic(清晰)- Linear(默认、快)- Area(缩小用) |
| borderMode | 边缘填充模式(旋转后空白区域怎么填) |
| borderValue | 填充颜色(默认黑色) |
三、最关键:旋转后不被裁剪的公式
直接用原图大小旋转,四个角会被切掉。
要让旋转后的图像完整显示、不裁剪,必须计算新画布大小:
新宽度、新高度公式
// 角度转弧度
double rad = angle * Math.PI / 180.0;
// 计算新画布宽高
int newWidth = (int)(src.Width * Math.Abs(Math.Cos(rad)) + src.Height * Math.Abs(Math.Sin(rad)));
int newHeight = (int)(src.Width * Math.Abs(Math.Sin(rad)) + src.Height * Math.Abs(Math.Cos(rad)));
还要修正旋转中心
Point2f oldCenter = new Point2f(src.Cols / 2f, src.Rows / 2f);
Mat rotMat = Cv2.GetRotationMatrix2D(oldCenter, angle, scale);
// 平移矩阵,让图像居中不裁剪
double cos = Math.Abs(rotMat.At<double>(0, 0));
double sin = Math.Abs(rotMat.At<double>(0, 1));
rotMat.At<double>(0, 2) = (newWidth / 2f) - oldCenter.X;
rotMat.At<double>(1, 2) = (newHeight / 2f) - oldCenter.Y;
四、完整可运行旋转代码(C#)
// 1. 读取图像
Mat src = Cv2.ImRead("test.jpg");
// 2. 旋转参数
double angle = 30; // 逆时针30度(负数=顺时针)
double scale = 1.0; // 不缩放
Point2f center = new Point2f(src.Cols / 2f, src.Rows / 2f);
// 3. 获取旋转矩阵
Mat rotMat = Cv2.GetRotationMatrix2D(center, angle, scale);
// 4. 计算新画布(防止被裁剪) // 用三角函数公式计算新画布宽高
double cos = Math.Abs(rotMat.At<double>(0, 0));
double sin = Math.Abs(rotMat.At<double>(0, 1));
int newW = (int)(src.Cols * cos + src.Rows * sin);
int newH = (int)(src.Cols * sin + src.Rows * cos);
// 5. 修正中心偏移
rotMat.At<double>(0, 2) += (newW / 2f) - center.X;
rotMat.At<double>(1, 2) += (newH / 2f) - center.Y;
// 6. 执行旋转(仿射变换)
Mat dst = new Mat();
Cv2.WarpAffine(
src,
dst,
rotMat,
new Size(newW, newH),
InterpolationFlags.Cubic, // 高质量插值
InterpolationFlags.Constant,
new Scalar(255, 255, 255) // 空白填充白色
);
// 7. 显示保存
Cv2.ImShow("rotated", dst);
Cv2.WaitKey(0);
五、快速总结(必记)
- GetRotationMatrix2D:生成旋转规则(中心点、角度、缩放)
- WarpAffine:执行旋转(矩阵、输出尺寸、插值、填充)
- 角度规则:正数逆时针,负数顺时针
- 不裁剪关键:必须计算新画布大小 + 修正中心点
- 推荐插值:旋转用
Cubic(清晰),默认Linear(快)
WarpAffine:执行仿射旋转变换
使用场景
倾斜文本矫正、不规则倾斜工件摆正。
public override Mat Execute(Mat src)
{
Mat dst = new Mat();
Point2f center = new Point2f(src.Cols / 2f, src.Rows / 2f);
// 1. 获取旋转矩阵
Mat rotationMat = Cv2.GetRotationMatrix2D(center, Angle, Scale);
Size outputSize = src.Size();
if (AutoExpandCanvas)
{ // 取四个角点 → 旋转 → 计算外接矩形
Point2f[] pts = new Point2f[]
{
new Point2f(0, 0),
new Point2f(src.Width, 0),
new Point2f(0, src.Height),
new Point2f(src.Width, src.Height)
};
Rect rect = Cv2.BoundingRect(pts);
outputSize = new Size(rect.Width, rect.Height);
// 修正中心点
rotationMat.Set(0, 2, rotationMat.Get<double>(0, 2) + (rect.Width / 2f - center.X));
rotationMat.Set(1, 2, rotationMat.Get<double>(1, 2) + (rect.Height / 2f - center.Y));
}
// 2. 执行仿射变换
Cv2.WarpAffine(src, dst, rotationMat, outputSize, InterpolationFlag);
rotationMat.Dispose();
return dst;
}
若文章对您有帮助,可以激励一下我哦,祝您平安幸福!
| 微信 | 支付宝 |
|---|---|
![]() |
![]() |

