Opencv的getRotationMatrix2D函数底层解析

源码

cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale )
{
    angle *= CV_PI/180;
    double alpha = cos(angle)*scale;
    double beta = sin(angle)*scale;
 
    Mat M(2, 3, CV_64F);
    double* m = M.ptr<double>();
 
    m[0] = alpha;
    m[1] = beta;
    m[2] = (1-alpha)*center.x - beta*center.y;
    m[3] = -beta;
    m[4] = alpha;
    m[5] = beta*center.x + (1-alpha)*center.y;
 
    return M;
}

推导

1、有图有真相

为什么这样画图,值得注意的是,计算机中图像的横坐标是向右增加,纵坐标是向下增加!!!

2、任务描述

其中角DAB=α,角CAB=θ

AD与横坐标轴平行,AE与纵坐标轴平行,现在需要沿着A点(centerX,centerY)==>>简写(cx,cy)作为旋转中心

将B点旋转θ角度后到达C点,假设C点坐标为(x',y'),求解x',y'和x,y,θ,cx,cy的数学关系

3、开始计算

AC由AB旋转得到,故其长度相等,令AC=AB=L

于是由三角函数知识

x'=cx+L*cos(α-θ)=cx+L*(cos(α)*cos(θ)+sin(α)*sin(θ))     1式

y'=cy+L*sin(α-θ)=cy+L*(sin(a)*cos(θ)-sin(θ)*cos(a))       2式

cos(α)=(x-cx)/L                                                                 3式

sin(a)=(y-cy)/L                                                                  4式

把3式,4式分别代入1式和2式,可以消去α和L。得到

x'=cx+(x-cx)*cos(θ)+(y-cy)*sin(θ)=x*cos(θ)+y*sin(θ)+cx*(1-cos(θ))-cy*sin(θ)

y'=cy+(y-cy)*cos(θ)-(x-cx)*sin(θ)=x*(-sin(θ))+y*cos(θ)+cy*(1-cos(θ))+cx*sin(θ)

提取出矩阵就是

[

        [cos(θ),sin(θ),cx*(1-cos(θ))-cy*sin(θ)],

        [-sin(θ),cos(θ),cy*(1-cos(θ))+cx*sin(θ)]

]

验证

实践是检验真理的唯一标准

上Python代码

import numpy as np
import cv2 as cv
import math

cx = 250
cy = 250
angle = 45
scale = 1.0

opencv_M = cv.getRotationMatrix2D((cx, cy), angle, scale)
print(f"opencv_M=\n{opencv_M}")

print("=================================")

cos_angle = math.cos(angle / 180.0 * math.pi)
sin_angle = math.sin(angle / 180.0 * math.pi)
self_M = np.array([
    [cos_angle, sin_angle, cx * (1 - cos_angle) - cy * sin_angle],
    [-sin_angle, cos_angle, cy * (1 - cos_angle) + cx * sin_angle]
])
print(f"self_M=\n{self_M}")

旋转中心(cx,cy)=(250,250)

旋转角度θ=45°

不进行缩放操作scale=1.0

运行结果

可以看出,运算结果是一模一样的,此函数的运算过程确实如上述公式所示

注意

python中math函数库的三角函数输入参数,是转换成多少pi,而不是直接输入一个角度,(准确地说,它接受的是弧度)

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值