2026/6/11 0:19:49
网站建设
项目流程
来雁新城建设投资公司官方网站,太原电子商务网站的建设与服务,做外包胡it网站,在线切图网站仿射变换#xff08;Affine Transformation#xff09;是一种保持图像平行性和共线性的几何变换#xff0c;核心是通过线性变换#xff08;缩放、旋转、剪切#xff09;与平移变换的组合#xff0c;改变图像的位置、姿态和尺寸#xff0c;但不改变图形的平行关系#x…仿射变换Affine Transformation是一种保持图像平行性和共线性的几何变换核心是通过线性变换缩放、旋转、剪切与平移变换的组合改变图像的位置、姿态和尺寸但不改变图形的平行关系如平行线变换后仍平行。OpenCV 中通过cv2.warpAffine()函数实现仿射变换需先构造仿射变换矩阵广泛用于图像校正、姿态调整、视角变换等场景。一、核心原理1. 仿射变换的数学表达对于图像中任意像素点(x, y)仿射变换后映射到新坐标(x, y)其数学公式为用矩阵形式表示为其中2×3 矩阵[[a,b,c],[d,e,f]]为仿射变换矩阵OpenCV 中需用numpy.ndarray表示 dtype 为np.float32前 2×2 子矩阵[[a,b],[d,e]]负责线性变换缩放、旋转、剪切最后一列[c,f]负责平移变换x 方向平移cy 方向平移f。2. 仿射变换的三大基础操作仿射变换可分解为三种基础变换的组合也可直接通过这三种变换构造矩阵基础变换作用变换矩阵特点平移Translation图像沿 x/y 轴移动前 2×2 为单位矩阵[[1,0],[0,1]]平移量[c,f]旋转Rotation图像绕原点 / 特定点旋转前 2×2 为旋转矩阵[[cosθ, -sinθ],[sinθ, cosθ]]可结合平移实现绕任意点旋转缩放Scaling图像沿 x/y 轴缩放前 2×2 为对角矩阵[[sx,0],[0,sy]]sx/sy为宽 / 高缩放比例3. 仿射变换矩阵的构造方式OpenCV 提供两种核心构造方法无需手动计算矩阵通过三点映射构造已知原图中 3 个非共线点及其变换后的对应点用cv2.getAffineTransform(src_pts, dst_pts)自动计算变换矩阵最常用手动构造直接根据平移、旋转、缩放的数学公式创建 2×3 矩阵适合简单变换。二、核心函数详解1.cv2.getAffineTransform()通过三点映射生成变换矩阵函数原型cv2.getAffineTransform(src_pts, dst_pts)参数说明参数含义要求src_pts原图中 3 个非共线点的坐标格式为np.float32([[x1,y1], [x2,y2], [x3,y3]])dst_pts变换后对应 3 个点的坐标格式与src_pts一致数量必须为 3返回值2×3 仿射变换矩阵np.float32类型。2.cv2.warpAffine()应用仿射变换函数原型cv2.warpAffine(src, M, dsize, dstNone, flagsNone, borderModeNone, borderValueNone)参数说明参数含义注意事项src输入图像单通道 / 多通道均可灰度图 / 彩色图M仿射变换矩阵必须是 2×3 的np.float32矩阵dsize输出图像尺寸格式为(width, height)与 OpenCV 图像shape相反flags插值算法可选默认cv2.INTER_LINEAR缩小用INTER_AREA高质量放大用INTER_CUBICborderMode边界填充模式可选默认cv2.BORDER_CONSTANT常数填充也可设为BORDER_REPLICATE复制边界borderValue边界填充值可选仅borderModeBORDER_CONSTANT有效默认黑色0彩色图用(b,g,r)格式返回值变换后的输出图像numpy.ndarray类型。三、完整实现代码多种场景1. 基础场景通过三点映射实现任意仿射变换已知原图 3 个点和目标点自动计算矩阵实现变换如校正倾斜图像import cv2 import numpy as np import matplotlib.pyplot as plt # 1. 读取图像 img cv2.imread(lena.jpg) if img is None: print(无法读取图像请检查路径) exit() h, w img.shape[:2] img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转为RGB用于matplotlib显示 # 2. 定义原图3个点和变换后对应3个点非共线 # 原图中选择3个特征点如左上角、右上角、左下角 src_pts np.float32([[50, 50], [200, 50], [50, 200]]) # 变换后目标点示例向右倾斜、向下平移 dst_pts np.float32([[50, 50], [250, 80], [30, 220]]) # 3. 计算仿射变换矩阵 M cv2.getAffineTransform(src_pts, dst_pts) # 4. 应用仿射变换输出尺寸与原图一致 img_affine cv2.warpAffine(img, M, (w, h), flagscv2.INTER_LINEAR, borderValue(255,255,255)) img_affine_rgb cv2.cvtColor(img_affine, cv2.COLOR_BGR2RGB) # 5. 绘制特征点可视化对应关系 for (x, y) in src_pts.astype(int): cv2.circle(img_rgb, (x, y), 5, (255, 0, 0), -1) # 原图点蓝色 for (x, y) in dst_pts.astype(int): cv2.circle(img_affine_rgb, (x, y), 5, (0, 255, 0), -1) # 目标点绿色 # 6. 显示结果 plt.figure(figsize(12, 6)) plt.subplot(1, 2, 1) plt.imshow(img_rgb) plt.title(Original Image (Blue Points)) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(img_affine_rgb) plt.title(Affine Transformation (Green Points)) plt.axis(off) plt.tight_layout() plt.show()2. 常用场景手动构造矩阵实现平移、旋转、缩放1平移变换沿 x 轴右移 100 像素y 轴下移 50 像素import cv2 import numpy as np import matplotlib.pyplot as plt img cv2.imread(lena.jpg) h, w img.shape[:2] img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 构造平移矩阵[[1,0,c],[0,1,f]]cx平移量fy平移量 tx, ty 100, 50 # x右移100y下移50 M_translate np.float32([[1, 0, tx], [0, 1, ty]]) # 应用变换输出尺寸可适当放大避免图像被截断 img_translate cv2.warpAffine(img, M_translate, (w tx, h ty), borderValue(255,255,255)) img_translate_rgb cv2.cvtColor(img_translate, cv2.COLOR_BGR2RGB) # 显示 plt.figure(figsize(12, 6)) plt.subplot(1, 2, 1) plt.imshow(img_rgb) plt.title(fOriginal ({h}×{w})) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(img_translate_rgb) plt.title(fTranslated (x100, y50) ({img_translate.shape[0]}×{img_translate.shape[1]})) plt.axis(off) plt.show()2旋转变换绕图像中心旋转 45°缩放比例 0.8旋转矩阵需结合平移先将旋转中心移至原点旋转后再移回原位置公式如下其中θ为旋转角度弧度sx/sy为缩放比例(cx, cy)为旋转中心。import cv2 import numpy as np import matplotlib.pyplot as plt img cv2.imread(lena.jpg) h, w img.shape[:2] img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 旋转参数 angle 45 # 旋转角度度 scale 0.8 # 旋转时的缩放比例 cx, cy w // 2, h // 2 # 旋转中心图像中心 # 计算旋转矩阵OpenCV内置函数无需手动计算 M_rotate cv2.getRotationMatrix2D((cx, cy), angle, scale) # 应用旋转输出尺寸可按旋转后的边界调整避免截断 img_rotate cv2.warpAffine(img, M_rotate, (w, h), flagscv2.INTER_CUBIC, borderValue(255,255,255)) img_rotate_rgb cv2.cvtColor(img_rotate, cv2.COLOR_BGR2RGB) # 显示 plt.figure(figsize(12, 6)) plt.subplot(1, 2, 1) plt.imshow(img_rgb) plt.title(fOriginal ({h}×{w})) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(img_rotate_rgb) plt.title(fRotated {angle}° (scale{scale})) plt.axis(off) plt.show()3缩放变换宽度缩放 1.5 倍高度缩放 0.8 倍import cv2 import numpy as np import matplotlib.pyplot as plt img cv2.imread(lena.jpg) h, w img.shape[:2] img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 构造缩放矩阵[[sx,0,0],[0,sy,0]]sx宽度缩放比sy高度缩放比 sx, sy 1.5, 0.8 M_scale np.float32([[sx, 0, 0], [0, sy, 0]]) # 应用缩放输出尺寸原图尺寸×缩放比 new_w, new_h int(w * sx), int(h * sy) img_scale cv2.warpAffine(img, M_scale, (new_w, new_h), flagscv2.INTER_CUBIC) img_scale_rgb cv2.cvtColor(img_scale, cv2.COLOR_BGR2RGB) # 显示 plt.figure(figsize(12, 6)) plt.subplot(1, 2, 1) plt.imshow(img_rgb) plt.title(fOriginal ({h}×{w})) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(img_scale_rgb) plt.title(fScaled (sx{sx}, sy{sy}) ({new_h}×{new_w})) plt.axis(off) plt.show()3. 实用场景图像校正倾斜文档校正通过选择文档的四个角点先取 3 个计算仿射矩阵校正倾斜的文档图像import cv2 import numpy as np import matplotlib.pyplot as plt def correct_skew_image(img, src_pts, target_size): 校正倾斜图像仿射变换 :param img: 输入倾斜图像 :param src_pts: 原图中文档的3个角点np.float32 :param target_size: 校正后目标尺寸 (width, height) :return: 校正后的图像 # 定义校正后目标点文档的三个角点左上角、右上角、左下角 dst_pts np.float32([[0, 0], [target_size[0]-1, 0], [0, target_size[1]-1]]) # 计算仿射矩阵 M cv2.getAffineTransform(src_pts, dst_pts) # 应用变换 corrected_img cv2.warpAffine(img, M, target_size, flagscv2.INTER_CUBIC, borderValue(255,255,255)) return corrected_img # 1. 读取倾斜文档图像 img_skew cv2.imread(skew_document.jpg) if img_skew is None: print(无法读取倾斜图像请检查路径) exit() h, w img_skew.shape[:2] img_skew_rgb cv2.cvtColor(img_skew, cv2.COLOR_BGR2RGB) # 2. 手动选择原图中3个角点可通过图像查看工具获取坐标 src_pts np.float32([[60, 80], [420, 70], [50, 500]]) # 示例坐标需根据实际图像调整 # 3. 校正图像目标尺寸宽400高550 target_size (400, 550) img_corrected correct_skew_image(img_skew, src_pts, target_size) img_corrected_rgb cv2.cvtColor(img_corrected, cv2.COLOR_BGR2RGB) # 4. 绘制角点可视化 for (x, y) in src_pts.astype(int): cv2.circle(img_skew_rgb, (x, y), 6, (0, 255, 0), -1) # 5. 显示结果 plt.figure(figsize(15, 8)) plt.subplot(1, 2, 1) plt.imshow(img_skew_rgb) plt.title(Skewed Image (Green Corners)) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(img_corrected_rgb) plt.title(fCorrected Image ({target_size[1]}×{target_size[0]})) plt.axis(off) plt.tight_layout() plt.show()四、关键说明与应用场景1. 仿射变换的核心特点保持平行性原图中平行线变换后仍为平行线保持共线性原图中共线点变换后仍共线灵活性可组合平移、旋转、缩放、剪切等多种变换仅需 3 个点通过 3 个非共线点的映射关系即可唯一确定变换矩阵。2. 典型应用场景图像校正倾斜文档、车牌、身份证等图像的水平 / 垂直校正姿态调整调整图像的旋转角度、位置适配特定显示区域视角变换模拟不同视角下的图像如将倾斜的物体转为正面视角数据增强深度学习中通过仿射变换旋转、平移、缩放扩充样本集提升模型泛化能力。3. 与透视变换的区别仿射变换 vs 透视变换Perspective Transformation特性仿射变换透视变换变换矩阵2×3 矩阵3×3 矩阵核心特点保持平行性不保持平行性可将平行线变为相交线点映射需求3 个非共线点4 个非共线点适用场景简单姿态调整、校正复杂视角变换如拍摄的文档转为正射投影五、注意事项坐标格式src_pts和dst_pts必须是np.float32类型否则会报错输出尺寸dsize格式为(width, height)需与图像shapeheight, width区分避免尺寸错乱边界填充变换后图像可能超出原尺寸需通过borderMode和borderValue设置边界填充如白色填充避免黑边插值算法选择缩小图像用cv2.INTER_AREA避免锯齿放大图像 / 保持细节用cv2.INTER_CUBIC或cv2.INTER_LINEAR旋转中心绕非原点旋转时需先平移到原点、旋转、再平移回原位置推荐用cv2.getRotationMatrix2D()自动计算矩阵避免手动计算错误。通过cv2.getAffineTransform()构造矩阵、cv2.warpAffine()应用变换可轻松实现各类仿射变换需求掌握三点映射和矩阵构造逻辑是核心。