【图像处理入门】3. 几何变换基础:从平移旋转到插值魔法

在这里插入图片描述

摘要

掌握图像的几何变换相当于学会「图像的空间魔法」。本文将带你理解平移/旋转/缩放的数学原理,掌握OpenCV中warpAffinegetAffineTransform的核心用法,对比最近邻、双线性等插值算法的优劣。通过图像翻转、镜像、透视变换实战,学会用变换矩阵控制图像的空间形态,为图像配准、目标检测等高级应用铺路。

一、几何变换的数学本质:变换矩阵

所有几何变换均可表示为矩阵运算:
通用变换公式
[ x ′ y ′ 1 ] = [ a b c d e f 0 0 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} a & b & c \\ d & e & f \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} xy1 = ad0be0cf1 xy1

  • 线性变换:左上角2x2矩阵(缩放、旋转、剪切)
  • 平移变换:第三列(c,d)决定平移量

OpenCV通过warpAffine函数实现仿射变换,需先计算变换矩阵M

二、基础变换实战:平移、旋转、缩放

1. 平移变换:图像的「空间位移」

import cv2
import numpy as np# 定义平移矩阵:向右平移100像素,向下平移50像素
M = np.float32([[1, 0, 100], [0, 1, 50]])  
translated = cv2.warpAffine(color, M, (width+100, height+50))  # 可视化对比
plt.subplot(121), plt.imshow(rgb), plt.title('Original')
plt.subplot(122), plt.imshow(cv2.cvtColor(translated, cv2.COLOR_BGR2RGB)), plt.title('Translated')

2. 旋转变换:绕原点的「顺时针舞蹈」

# 获取旋转矩阵:绕中心旋转30°,缩放因子1.0
height, width = color.shape[:2]
center = (width//2, height//2)
M = cv2.getRotationMatrix2D(center, 30, 1.0)  
rotated = cv2.warpAffine(color, M, (width, height))  # 注意:旋转后图像可能超出边界,需扩大输出尺寸避免裁剪

3. 缩放变换:放大缩小的「像素重组」

# 方法1:直接指定尺寸(最近邻插值)
zoomed_nearest = cv2.resize(color, (width*2, height*2), interpolation=cv2.INTER_NEAREST)  # 方法2:按比例缩放(双线性插值,更平滑)
zoomed_bilinear = cv2.resize(color, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)  

三、插值算法:变换时的像素「重建魔法」

不同插值算法在速度和质量间权衡:

算法速度图像质量适用场景
最近邻(NEAREST)最快锯齿明显缩小图像、实时处理
双线性(LINEAR)中等边缘平滑放大/缩小/旋转
双三次(CUBIC)最慢细节保留最佳高质量图像重建
区域插值(AREA)中等边缘清晰缩小图像(优于NEAREST)
# 对比不同插值的缩放效果
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(zoomed_nearest[:200, :200]), plt.title('Nearest')
plt.subplot(132), plt.imshow(zoomed_bilinear[:200, :200]), plt.title('Bilinear')
plt.subplot(133), plt.imshow(zoomed_cubic[:200, :200]), plt.title('Bicubic')

四、进阶变换:翻转、镜像与透视

1. 翻转与镜像:图像的「左右互搏」

# 水平翻转(左右镜像)
flipped_horizontal = cv2.flip(color, 1)  
# 垂直翻转(上下颠倒)
flipped_vertical = cv2.flip(color, 0)  
# 同时水平+垂直翻转
flipped_both = cv2.flip(color, -1)  

2. 透视变换:从平面到3D的「视觉欺骗」

# 定义原始四边形顶点和目标顶点(均为顺时针顺序)
src_points = np.float32([[50, 50], [450, 50], [450, 450], [50, 450]])  
dst_points = np.float32([[100, 200], [400, 200], [400, 300], [100, 300]])  # 获取透视变换矩阵并应用
M_perspective = cv2.getPerspectiveTransform(src_points, dst_points)  
perspective_img = cv2.warpPerspective(color, M_perspective, (width, height))  

五、实战:证件照尺寸标准化

假设需要将200x300像素的证件照缩放为标准1寸(295x413像素),并保持头像区域不变:

# 1. 计算缩放比例(保持宽高比)
src_h, src_w = img.shape[:2]
dst_w, dst_h = 295, 413
scale_w = dst_w / src_w
scale_h = dst_h / src_h
scale = min(scale_w, scale_h)# 2. 计算缩放后尺寸和填充区域
new_w = int(src_w * scale)
new_h = int(src_h * scale)
dx = (dst_w - new_w) // 2
dy = (dst_h - new_h) // 2# 3. 缩放+边缘填充(黑色背景)
resized = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_AREA)
standardized = cv2.copyMakeBorder(resized, dy, dst_h-new_h-dy, dx, dst_w-new_w-dx, cv2.BORDER_CONSTANT, value=(0,0,0))

六、避坑指南:变换中的尺寸计算

  1. 旋转后的尺寸溢出
    旋转后图像可能超出原尺寸,需提前计算最小包围矩形:

    rows, cols = img.shape[:2]
    M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
    # 计算旋转后的新尺寸
    cos = np.abs(M[0,0]); sin = np.abs(M[0,1])
    new_cols = int(rows*sin + cols*cos)
    new_rows = int(rows*cos + cols*sin)
    M[0,2] += (new_cols - cols)/2; M[1,2] += (new_rows - rows)/2
    
  2. 透视变换的顶点顺序
    顶点必须按顺时针/逆时针顺序排列,否则会出现扭曲

总结

几何变换是图像处理的空间操作基石:

  • 平移/旋转/缩放通过仿射变换矩阵实现,本质是像素的坐标映射
  • 插值算法的选择直接影响变换后的图像质量,双线性插值是平衡之选
  • warpAffinewarpPerspective是处理2D/3D变换的核心函数

下一篇我们将进入图像增强领域,学习如何通过直方图均衡化、伽马校正等技术提升图像视觉效果。现在请打开一张倾斜的文档照片,尝试用透视变换将其矫正为正视角度吧!

思考:为什么旋转后的图像边缘会出现黑边?如何用边界填充解决这个问题?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序学习目录

个人简介 👨‍💻‍个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言&…

QT 5.15.2 程序中文乱码

1. 在.pro文件中添加: msvc { QMAKE_CXXFLAGS /source-charset:utf-8 /execution-charset:utf-8 }备注:.pro文件只有在选择 qmake 方式才会生成。 [Cmake 只会生成 CMakeLists.txt 文件] 2. 在文件首部增加以下程序行 #pragma execution_character_s…

Unity UI设计优化与模式原则

前言 在 Unity 中设计高效且可维护的 UI 系统时,需要结合性能优化和设计模式两大核心方向。以下是关键原则及实践方法: 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀! 一、UI 性能…

CppCon 2014 学习: The Implementation of Value Types

“The Implementation of Value Types” 在C里,通常指的是如何设计和实现**值类型(value types)**的类,确保它们符合值语义(value semantics),也就是说: 对象的赋值和拷贝操作应该是…

每日算法刷题Day19 5.31:leetcode二分答案3道题,用时1h

6. 475.供暖器(中等,学习check函数双指针思想) 475. 供暖器 - 力扣(LeetCode) 思想 1.冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。在加热器的加热半径范围内的每个房屋都可以获得供暖。现在,给出…

【计算机网络】第2章:应用层—应用层协议原理

目录 1. 网络应用的体系结构 2. 客户-服务器(C/S)体系结构 3. 对等体(P2P)体系结构 4. C/S 和 P2P 体系结构的混合体 Napster 即时通信 5. 进程通信 6. 分布式进程通信需要解决的问题 7. 问题1:对进程进行编址…

PHP+MySQL开发语言 在线下单订水送水小程序源码及搭建指南

随着互联网技术的不断发展,在线下单订水送水服务为人们所需要。分享一款 PHP 和 MySQL 搭建一个功能完善的在线订水送水小程序源码及搭建教程。这个系统将包含用户端和管理端两部分,用户可以在线下单、查询订单状态,管理员可以处理订单、管理…

vBulletin未认证API方法调用漏洞(CVE-2025-48827)

免责声明 本文档所述漏洞详情及复现方法仅限用于合法授权的安全研究和学术教育用途。任何个人或组织不得利用本文内容从事未经许可的渗透测试、网络攻击或其他违法行为。使用者应确保其行为符合相关法律法规,并取得目标系统的明确授权。 对于因不当使用本文信息而造成的任何直…

计算机模拟分子合成有哪些应用软件?

参阅:Top 创新大奖 以下是用于计算机模拟分子合成(包括逆合成设计、分子对接、分子动力学模拟及综合设计平台)的主流应用软件分类总结,结合其核心功能和应用场景进行整理: 🔬 一、逆合成设计与路线规划软件…

Excel 中的SUMIFS用法(基础版),重复项求和

1. 首先复制筛选条件所在的列,去除重复项目 数据 》重复项 》删除重复项 2. 输入函数公式 SUMIFS(C:C,A:A,E2) 3. 选中单元格,通过 ShiftF3 查看函数参数 第一个参数:求和区域,要累加的值所在的区域范围 第二个参数&#xff1a…

【xmb】内部文档148344597

基于小米CyberDog 2的自主导航与视觉感知系统设计报告 摘要: 本文针对2025年全国大学生计算机系统能力大赛智能系统创新设计赛(小米杯)初赛要求,设计并实现了基于小米仿生四足机器人CyberDog 2的平台系统方案。参赛作品利用Cyber…

从零开始理解机器学习:知识体系 + 核心术语详解

你可能听说过“机器学习”,觉得它很神秘,像是让电脑自己学会做事。其实,机器学习的本质很简单:通过数据来自动建立规则,从而完成预测或决策任务。 这篇文章将带你系统梳理机器学习的知识体系,并用贴近生活…

springboot集成websocket给前端推送消息

一般通常情况下,我们都是前端主动朝后端发送请求,那么有没有可能,后端主动给前端推送消息呢?这时候就可以借助websocket来实现。下面给出一个简单的实现样例。 首先创建一个websocketDemo工程,该工程的整体结构如下&a…

【清晰教程】查看和修改Git配置情况

目录 查看安装版本 查看特定配置 查看全局配置 查看本地仓库配置 设置或修改配置 查看安装版本 打开命令行工具,通过version命令检查Git版本号。 git --version 如果显示出 Git 的版本号,说明 Git 已经成功安装。 查看特定配置 如果想要查看特定…

【Github/Gitee Webhook触发自动部署-Jenkins】

Github/Gitee Webhook触发自动部署-Jenkins #mermaid-svg-hRyAcESlyk5R2rDn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hRyAcESlyk5R2rDn .error-icon{fill:#552222;}#mermaid-svg-hRyAcESlyk5R2rDn .error-tex…

C语言数据结构-链式栈

头文件&#xff1a;stack.h #ifndef __STACK_H__ #define __STACK_H__ #include <stdio.h> #include <stdlib.h> typedef int DataType; /* 链式栈节点类型 */ typedef struct staNode { DataType data; struct staNode *pNext; }StackNode; /* 链式栈…

M4Pro安装ELK(ElasticSearch+LogStash+Kibana)踩坑记录

ElasticSearch安装&#xff0c;启动端口9200&#xff1a; docker pull elasticsearch:8.13.0 新增配置文件elasticsearch.yml&#xff1a; cd /opt/homebrew/etc/ mkdir elasticsearch_config cd elasticsearch_config vi elasticsearch.yml cluster.name: "nfturbo…

uni-app学习笔记十六-vue3页面生命周期(三)

uni-app官方文档页面生命周期部分位于页面 | uni-app官网。 本篇再介绍2个生命周期 1.onUnload&#xff1a;用于监听页面卸载。 当页面被关闭时&#xff0c;即页面的缓存被清掉时触发加载onUnload函数。 例如:在demo6页面点击跳转到demo4&#xff0c;在demo4页面回退不了到d…

Java互联网大厂面试:从Spring Boot到Kafka的技术深度探索

Java互联网大厂面试&#xff1a;从Spring Boot到Kafka的技术深度探索 在某家互联网大厂的面试中&#xff0c;面试官A是一位技术老兵&#xff0c;而被面试者谢飞机&#xff0c;号称有丰富的Java开发经验。以下是他们的面试情景&#xff1a; 场景&#xff1a;电商平台的后端开发…

机器学习算法——KNN

一、KNN算法简介 1.KNN思想 &#xff08;1&#xff09;K-近邻算法 根据你的“邻居”来推断你是什么类别 KNN算法思想&#xff1a;如果一个样本在特征空间&#xff08;训练集&#xff09;中的k个最相似的样本中的大多数属于某一个类别。则该样本也属于这个类别 &#xff08…