opencv获取模板旋转角度_经验 | OpenCV图像旋转的原理与技巧

本文介绍了图像旋转的基本原理,包括图像尺寸变化、背景填充和像素插值。详细讲解了OpenCV中图像旋转函数`rotate()`和`warpAffine()`的使用,特别是如何生成旋转矩阵M,并提供了代码示例展示无Crop版本的图像旋转。同时,文章还通过动态演示展示了不同背景下的图像旋转效果。

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

635701211ff2aa5f0e1381cff677830a.gif

点击上方蓝字关注我们

微信公众号:OpenCV学堂

关注获取更多计算机视觉与深度学习知识

01

引言

初学图像处理,很多人遇到的第一关就是图像旋转,图像旋转是图像几何变换中最具代表性的操作,包含了插值、背景处理、三角函数等相关知识,一个变换矩阵跟计算图像旋转之后的大小公式就让很多开发者最后直接调用函数了事,但是其实这个东西并没有这么难懂,可以说主要是之前别人写的公式太吓人,小编很久以前第一次接触的也是被吓晕了!所以决定从程序员可以接受的角度从新介绍一下图像旋转基本原理与OpenCV中图像旋转函数操作的基本技巧。

图像旋转基本原理

旋转涉及到两个问题,一个是图像旋转之后的大小会发生改变,会产生背景,通过背景填充方式都是填充黑色,此外旋转还是产生像素的位置迁移,新的位置像素需要通过插值计算获得,常见的插值方式有最近邻、线性插值、立方插值等。

首先看旋转之后的图像宽高变化,如下图所示:

a9c18bbf6d56f985c16bdb3cad46aa63.png

5d85d754f32f6e92813fbce0679dc81d.png

这个是正常的平面坐标系中的旋转矩阵,可以简写为:

ce5d6a5c8c157e276c361bbca0a5b298.png

是一个2x3的矩阵,但是在图像中左上角是原点,要实现围绕图像的中心位置旋转,M就要重新计算,所以OpenCV中的图像旋转矩阵为:

a18f6f83685e8dfb43889d249fd88fb3.png

其中scale是表示矩阵支持旋转+放缩,这里可以把Scale=1。第三列是图像旋转之后中心位置平移量。

函数支持

OpenCV中支持图像旋转的函数有两个,一个是直接支持旋转的函数,但是它支持的是90,180,270这样的特殊角度旋转。

void cv::rotate   (    InputArray    src,    OutputArray dst,    int rotateCode)

其中rotateCode参数必须为:

ROTATE_180,ROTATE_90_CLOCKWISEROTATE_90_COUNTERCLOCKWISE 

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

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

但是M如何生成与获取,OpenCV中提供了一个函数根据输入的参数自动生成旋转矩阵M,该函数为:

Mat cv::getRotationMatrix2D(         Point2f   center,         double    angle,         double    scale)

代码演示

原图

105d348572669610a375c98cf5bcfdc9.png

使用自定义的M矩阵实现图像旋转

h, w, c = src.shape
# 定义矩阵
M = np.zeros((2, 3), dtype=np.float32)
# 定义角度
alpha = np.cos(np.pi / 4.0)
beta = np.sin(np.pi / 4.0)
print("alpha : ", alpha)
# 初始化矩阵
M[0, 0] = alpha
M[1, 1] = alpha
M[0, 1] = beta
M[1, 0] = -beta
cx = w / 2
cy = h / 2
tx = (1-alpha)*cx - beta*cy
ty = beta*cx + (1-alpha)*cy
M[0,2] = tx
M[1,2] = ty
# 执行旋转
dst = cv.warpAffine(src, M, (w, h))
cv.imshow("rotate-center-demo", dst)

c71ed54d7948dffce7477b4ab40da483.png

重新计算旋转之后的图像大小,实现无Crop版本的图像旋转

h, w, c = src.shape
M = np.zeros((2, 3), dtype=np.float32)
alpha = np.cos(np.pi / 4.0)
beta = np.sin(np.pi / 4.0)
print("alpha : ", alpha)

# 初始旋转矩阵
M[0, 0] = alpha
M[1, 1] = alpha
M[0, 1] = beta
M[1, 0] = -beta
cx = w / 2
cy = h / 2
tx = (1-alpha)*cx - beta*cy
ty = beta*cx + (1-alpha)*cy
M[0,2] = tx
M[1,2] = ty

# change with full size
bound_w = int(h * np.abs(beta) + w * np.abs(alpha))
bound_h = int(h * np.abs(alpha) + w * np.abs(beta))

# 添加中心位置迁移
M[0, 2] += bound_w / 2 - cx
M[1, 2] += bound_h / 2 - cy
dst = cv.warpAffine(src, M, (bound_w, bound_h))
cv.imshow("rotate without cropping", dst)

9fa88e89cdd04d7e4106fff8edca2612.png

背景随便变化+无Crop版本的图像旋转动态演示

degree = 1.0
d1 = np.pi / 180.0
while True:
    alpha = np.cos(d1*degree)
    beta = np.sin(d1*degree)
    M[0, 0] = alpha
    M[1, 1] = alpha
    M[0, 1] = beta
    M[1, 0] = -beta
    cx = w / 2
    cy = h / 2
    tx = (1 - alpha) * cx - beta * cy
    ty = beta * cx + (1 - alpha) * cy
    M[0, 2] = tx
    M[1, 2] = ty

    # change with full size
    bound_w = int(h * np.abs(beta) + w * np.abs(alpha))
    bound_h = int(h * np.abs(alpha) + w * np.abs(beta))
    M[0, 2] += bound_w / 2 - cx
    M[1, 2] += bound_h / 2 - cy
    red = np.random.randint(0, 255)
    green = np.random.randint(0, 255)
    blue = np.random.randint(0, 255)
    dst = cv.warpAffine(src, M, (bound_w, bound_h), borderMode=cv.BORDER_CONSTANT, borderValue=(blue, green, red))
    cv.imshow("rotate+background", dst)
    c = cv.waitKey(1000)
    if c == 27:
        break
    degree += 1
    print("degree", degree)
    if degree > 360:
        degree = degree % 360

af9d70eccd77caeb4375a04e8b2180c3.png

6f29030ee9a58276a567821920ffa6ab.png

君子藏器于身,待时而动

 推荐阅读 

OpenCV4系统化学习路线图-视频版本!

Tensorflow + OpenCV4 安全帽检测模型训练与推理

汇总 | OpenCV DNN模块中支持的分类网络

OpenCV中支持的人脸检测方法整理与汇总

从3D人脸到自动驾驶,CVPR2020十个顶级开源数据集

轻松学Pytorch – 构建UNet实现道路裂纹检测

详解ENet | CPU可以实时的道路分割网络

从Pytorch 的ONNX到OpenVINO中IR中间层

OpenVINO中的FCOS人脸检测模型代码演示

详解OpenVINO 模型库中的人脸检测模型

效果特好 | OpenVINO手写数字识别

OpenVINO+OpenCV 文本检测与识别

OpenVINO + OpenCV实现点头与摇头识别验证

OpenVINO + OpenCV实现车辆检测与道路分割

OpenCV二值图像分析之寻找缺失与靶心

OpenCV 基于Inception模型图像分类

OpenCV4.4 + YOLOv4 真的可以运行了…..

告别对象检测图像数据手动标注的坑,用Anno-Mage半自动图像标注工具

4bb5c5d3dca22b6492984ad4f9a89c4d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值