当前位置: 首页 > news >正文

旋转变换原理


旋转变换原理

旋转是仿射变换的一种,通过变换矩阵实现图像绕指定中心旋转,保持直线和平行性不变。其数学表示为:
在这里插入图片描述
其中:

  • ( c x , c y ) (c_x, c_y) (cx,cy) 是旋转中心。
  • θ \theta θ 是旋转角度(逆时针为正)。

旋转矩阵的平移项用于补偿旋转中心的偏移。推导过程如下:

  1. 将旋转中心移到原点
    在这里插入图片描述

  2. 旋转
    [
\begin{bmatrix}
\cos\theta & -\sin\theta & 0 \
\sin\theta & \cos\theta & 0 \
0 & 0 & 1
\end{bmatrix}
]

  3. 移回原位置
    [
\begin{bmatrix}
1 & 0 & c_x \
0 & 1 & c_y \
0 & 0 & 1
\end{bmatrix}
]

  4. 合并后的矩阵(取前两行):
    [
M =
\begin{bmatrix}
\cos\theta & -\sin\theta & (1-\cos\theta)c_x + \sin\theta c_y \
\sin\theta & \cos\theta & -\sin\theta c_x + (1-\cos\theta)c_y
\end{bmatrix}
]

import numpy as np
import cv2
import matplotlib.pyplot as plt

def get_rotation_matrix(angle, center=None, scale=1.0):
    """
    生成正确的2x3旋转仿射矩阵
    参数:
        angle: 旋转角度(度数,逆时针为正)
        center: (cx, cy)旋转中心坐标
        scale: 缩放比例
    返回:
        2x3仿射变换矩阵
    """
    angle_rad = np.deg2rad(angle)
    cos = np.cos(angle_rad) * scale
    sin = np.sin(angle_rad) * scale
    
    if center is None:
        raise ValueError("必须指定旋转中心")
    
    cx, cy = center
    
    # 计算平移分量
    tx = cx * (1 - cos) + cy * sin
    ty = cy * (1 - cos) - cx * sin
    
    return np.array([
        [cos, -sin, tx],
        [sin,  cos, ty]
    ])

def warp_affine(image, M, dsize):
    """
    手动实现仿射变换(支持多通道图像)
    参数:
        image: 输入图像(H,W,C)
        M: 2x3仿射变换矩阵
        dsize: 输出图像大小(width, height)
    返回:
        变换后的图像
    """
    h, w = dsize[1], dsize[0]
    output = np.zeros((h, w, image.shape[2]), dtype=image.dtype)
    
    # 构造逆变换矩阵
    M_inv = np.vstack([M, [0, 0, 1]])
    M_inv = np.linalg.inv(M_inv)[:2]
    
    # 生成目标图像网格坐标
    y, x = np.indices((h, w))
    coords = np.stack([x, y, np.ones_like(x)], axis=-1)  # (H,W,3)
    
    # 计算原图坐标
    src_coords = np.dot(coords, M_inv.T)  # (H,W,2)
    
    # 双线性插值
    x_src = src_coords[:, :, 0]
    y_src = src_coords[:, :, 1]
    
    # 计算四个邻近点坐标
    x0 = np.floor(x_src).astype(int)
    y0 = np.floor(y_src).astype(int)
    x1 = x0 + 1
    y1 = y0 + 1
    
    # 处理边界
    x0 = np.clip(x0, 0, image.shape[1]-1)
    y0 = np.clip(y0, 0, image.shape[0]-1)
    x1 = np.clip(x1, 0, image.shape[1]-1)
    y1 = np.clip(y1, 0, image.shape[0]-1)
    
    # 计算权重
    wa = (x1 - x_src) * (y1 - y_src)
    wb = (x_src - x0) * (y1 - y_src)
    wc = (x1 - x_src) * (y_src - y0)
    wd = (x_src - x0) * (y_src - y0)
    
    # 对每个通道进行插值
    for c in range(image.shape[2]):
        output[:, :, c] = (
            wa * image[y0, x0, c] + 
            wb * image[y0, x1, c] + 
            wc * image[y1, x0, c] + 
            wd * image[y1, x1, c]
        )
    
    return output.astype(np.uint8)

# 测试代码
if __name__ == "__main__":
    # 读取图像
    img = cv2.imread('example.jpg')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
    # 设置旋转参数
    angle = 45  # 旋转45度
    h, w = img.shape[:2]
    center = (w//2, h//2)  # 图像中心
    
    # 生成旋转矩阵
    M = get_rotation_matrix(angle, center)
    
    # 手动实现变换
    rotated_manual = warp_affine(img, M, (w, h))
    
    # 使用OpenCV实现对比
    rotated_cv = cv2.warpAffine(img, M, (w, h))
    
    # 显示结果
    plt.figure(figsize=(12, 6))
    plt.subplot(131), plt.imshow(img), plt.title('Original')
    plt.subplot(132), plt.imshow(rotated_manual), plt.title('Manual Rotation')
    plt.subplot(133), plt.imshow(rotated_cv), plt.title('OpenCV Rotation')
    plt.show()

相关文章:

  • 养老更安心!智绅科技“智慧”养老系统,智在何处?
  • A SAM-guided Two-stream Lightweight Model for AnomalyDetection
  • springBoot统一响应类型3.3版本
  • 4、网工软考—VLAN配置—hybird配置
  • 以科技赋能,炫我云渲染受邀参加中关村文化科技融合影视精品创作研讨会!
  • 《白帽子讲 Web 安全》之跨站请求伪造
  • 剑指Offer44 -- 思维
  • Java Synchronized底层原理:Monitor机制、锁膨胀、自旋优化与偏向锁细节解密
  • vcpkg安装指定版本的库
  • 重磅推出稳联技术Profinet转CANopen网关智能工厂解决方案!
  • 磷酸铁锂电池自动分选机:新能源产业的智能新宠
  • 深入理解机器学习之TF-IDF:文本特征提取的核心技术
  • STM32 时钟树配置(debug)
  • Citus源码(1)分布式表行为测试
  • 自动化测试与 CAPTCHA 识别指南
  • notepad++ 正则表达式
  • Python第六章16:字典(dict)的常用操作
  • 如何为 Debian 和 Kali 系统更换软件源并更新系统
  • transform 3d学习简单示例
  • Mysql-DML
  • 4年间职务侵占、受贿逾亿元,北京高院:严惩民企内部腐败
  • 以色列在加沙发起新一轮强攻,同步与哈马斯展开“无条件谈判”
  • 世界高血压日|专家:高血压患者控制血压同时应注重心率管理
  • 菲律宾选举委员会公布中期选举结果,马科斯阵营选情未达预期
  • 女排奥运冠军宋妮娜:青少年保持身心健康才能走得更远
  • 降水较常年同期少五成,安徽四大水利工程调水超11亿方应对旱情