Opencv中文网

任意角度旋转(GetRotationMatrix2D + WarpAffine)

组合算法:GetRotationMatrix2D + WarpAffine

一、GetRotationMatrix2D 函数(获取旋转矩阵)

函数作用

生成一个 2×3 的仿射旋转矩阵,用于描述:

  • 绕哪个点旋转(中心点)
  • 旋转多少度
  • 旋转时是否缩放
Mat GetRotationMatrix2D(
    Point2f center,    // 旋转中心点
    double angle,      // 旋转角度(°)
    double scale       // 缩放系数
);

逐参数详解

表格

参数名类型含义 & 详细说明
centerPoint2f旋转中心点通常用 图像中心new Point2f(cols/2f, rows/2f)x = 宽度 / 2,y = 高度 / 2
angledouble旋转角度(度)正数 = 逆时针旋转负数 = 顺时针旋转例:90 → 逆时针转 90°;-45 → 顺时针转 45°
scaledouble缩放比例1.0 = 不缩放0.5 = 缩小一半2.0 = 放大一倍

关键常识

  • 返回的 Mat2 行 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);

五、快速总结(必记)

  1. GetRotationMatrix2D:生成旋转规则(中心点、角度、缩放)
  2. WarpAffine:执行旋转(矩阵、输出尺寸、插值、填充)
  3. 角度规则:正数逆时针,负数顺时针
  4. 不裁剪关键:必须计算新画布大小 + 修正中心点
  5. 推荐插值:旋转用 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;
}

copyright @重庆教主 WPF中文网 联系站长:(QQ)23611316 (微信)movieclip (QQ群).NET小白课堂:864486030 | 本文由WPF中文网原创发布,谢绝转载 渝ICP备2023009518号-1