计算机视觉进阶教学之图像投影(透视)变换
目录简介一、了解图像投影(透视)变换一、定义与原理二、应用场景三、实现方法二、案例分析1. 辅助函数定义1.1.cv_show 函数1.2.order_points 函数1.3.four_point_transform 函数1.4.resize 函数2. 主程序执行流程2.1.图像缩放处理2.2.轮廓检测2.3.获取最大轮廓文档边缘2.4.透视变换并保存结果3.总结简介在计算机视觉的进阶学习旅程中图像投影透视变换是一座连接理论与实战的关键桥梁。无论是实现证件照的智能矫正、自动驾驶中道路场景的视角转换还是无人机航拍图像的地理坐标映射这一技术都扮演着不可或缺的核心角色。如果你曾困惑于 “为何倾斜拍摄的文档会出现边缘变形”“如何让二维图像呈现出三维空间的立体感”或是在项目开发中急需解决图像视角转换的技术难题那么本系列博客将为你提供系统性的解决方案。一、了解图像投影(透视)变换图像的透视变换Perspective Transformation是一种在图像处理中广泛使用的技术它通过模拟人眼或相机镜头观看三维空间物体时的透视效果来改变图像的视角和形状。以下是对图像透视变换的详细解释一、定义与原理透视变换是一种非线性变换它可以将一个二维坐标系中的点映射到三维坐标系中的点然后再将其投影到另一个二维坐标系中的点。这种变换基于几何学中的透视原理通过一个3x3的变换矩阵来实现该矩阵作用于图像的每个像素坐标从而进行坐标的映射转换。透视变换能够模拟真实世界中的透视效果使物体看起来更接近、更远或者从不同角度观看。二、应用场景透视变换在图像处理和计算机视觉领域有着广泛的应用包括但不限于以下几个方面图像校正通过透视变换可以修正由于视角引起的图像扭曲如将拍摄的倾斜书本或建筑物照片校正为正视图。图像合成将两个图像中的物体或场景合成在一起仿佛它们是从同一视角拍摄的。虚拟现实VR和增强现实AR在VR和AR应用中透视变换用于模拟真实世界的视角和深度感提升用户体验。目标检测与跟踪在目标检测和跟踪任务中透视变换可以用于调整图像视角以便更准确地识别和跟踪目标。三维重建在三维重建过程中透视变换是连接二维图像与三维空间的关键技术之一。三、实现方法在OpenCV等图像处理库中透视变换通常通过以下步骤实现选择对应点在原始图像和目标图像上分别选择四个非共线的对应点。这些点通常是图像中的显著特征点如纸上的角落、建筑物的边缘等。计算变换矩阵使用OpenCV中的cv2.getPerspectiveTransform函数根据这些对应点计算透视变换矩阵。应用变换矩阵使用cv2.warpPerspective函数将计算得到的透视变换矩阵应用于原始图像从而得到变换后的图像。二、案例分析了解了枯燥的理论我们用下面这个案例来分析实现对一个小票进行图像投影变换1. 辅助函数定义1.1.cv_show 函数def cv_show(name, img): cv2.imshow(name, img) # 显示图像name是窗口名称img是要显示的图像 cv2.waitKey(0) # 等待用户按键0表示无限等待这是一个简化图像显示操作的函数封装了 OpenCV 的imshow和waitKey方法方便在多个地方调用。1.2.order_points 函数def order_points(pts): # 初始化一个4x2的矩阵存储排序后的坐标 rect np.zeros(shape(4, 2), dtypefloat32) # 按顺序找到对应坐标左上右上右下左下 s pts.sum(axis1) # 对每个点的x和y坐标求和 rect[0] pts[np.argmin(s)] # 最小的和对应左上角(xy最小) rect[2] pts[np.argmax(s)] # 最大的和对应右下角(xy最大) diff np.diff(pts, axis1) # 计算每个点的y-x差值 rect[1] pts[np.argmin(diff)] # 最小的差值对应右上角(y-x最小) rect[3] pts[np.argmax(diff)] # 最大的差值对应左下角(y-x最大) return rect这个函数用于对四边形的四个顶点进行排序确保它们按 左上→右上→右下→左下 的顺序排列为后续的透视变换做准备。1.3.four_point_transform 函数def four_point_transform(image, pts): # 获取排序后的坐标点 rect order_points(pts) (tl, tr, br, bl) rect # 分别赋值给左上、右上、右下、左下 # 计算宽度取底部和顶部宽度的最大值 widthA np.sqrt(((br[0] - bl[0]) **2) ((br[1] - bl[1])** 2)) widthB np.sqrt(((tr[0] - tl[0]) **2) ((tr[1] - tl[1])** 2)) maxWidth max(int(widthA), int(widthB)) # 计算高度取右侧和左侧高度的最大值 heightA np.sqrt(((tr[0] - br[0]) **2) ((tr[1] - br[1])** 2)) heightB np.sqrt(((tl[0] - bl[0]) **2) ((tl[1] - bl[1])** 2)) maxHeight max(int(heightA), int(heightB)) # 定义变换后的目标坐标 dst np.array([ [0, 0], # 左上 [maxWidth - 1, 0], # 右上 [maxWidth - 1, maxHeight - 1], # 右下 [0, maxHeight - 1] # 左下 ], dtypefloat32) # 计算透视变换矩阵 M cv2.getPerspectiveTransform(rect, dst) # 应用透视变换 warped cv2.warpPerspective(image, M, (maxWidth, maxHeight)) return warped这是核心函数实现了图像的透视变换将倾斜的四边形区域转换为正面矩形视图模拟了从不同角度拍摄的文档转换为正视图的效果。1.4.resize 函数def resize(image, widthNone, heightNone, intercv2.INTER_AREA): dim None # 存储调整后的尺寸 (h, w) image.shape[:2] # 获取原始图像的高度和宽度 # 如果宽高都未指定直接返回原图 if width is None and height is None: return image # 如果宽度未指定按高度比例缩放 if width is None: r height / float(h) # 计算缩放比例 dim (int(w * r), height) # 计算新的宽度 # 否则按宽度比例缩放 else: r width / float(w) # 计算缩放比例 dim (width, int(h * r)) # 计算新的高度 # 执行缩放操作 resized cv2.resize(image, dim, interpolationinter) return resized这个函数用于按比例调整图像大小避免图像过大处理困难或过小影响精度。2. 主程序执行流程import cv2 import numpy as np # 读取输入图像 image cv2.imread(fapiao.jpg) cv_show(image, image) # 显示原始图像2.1.图像缩放处理# 计算缩小比率以高度为基准缩放到500像素 ratio image.shape[0] / 500.0 orig image.copy() # 保存原始图像副本 image resize(orig, height500) # 按比例缩小图像 cv_show(1, image) # 显示缩小后的图像将图像按比例缩小到高度为 500 像素便于后续处理同时记录缩放比例以便后期恢复原始尺寸。2.2.轮廓检测print(STEP 1: 轮廓检测) gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转换为灰度图 # 自动阈值二值化处理OTSU算法 edged cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 查找轮廓 cnts cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2] # 绘制所有轮廓并显示 image_contours cv2.drawContours(image.copy(), cnts, -1, color(0, 0, 255), thickness1) cv_show(image_contours, image_contours)这一步将图像转为灰度图再通过二值化处理突出边缘最后检测出图像中的所有轮廓。2.3.获取最大轮廓文档边缘print(STEP 2: 获取最大轮廓) # 按轮廓面积排序取最大的那个通常是文档的边缘 screenCnt sorted(cnts, keycv2.contourArea, reverseTrue)[0] print(screenCnt.shape) # 输出轮廓形状 # 轮廓近似将不规则轮廓近似为多边形 peri cv2.arcLength(screenCnt, closedTrue) # 计算轮廓周长 # 用Douglas-Peucker算法近似轮廓0.05*peri是近似精度 screenCnt cv2.approxPolyDP(screenCnt, 0.05 * peri, closedTrue) print(screenCnt.shape) # 输出近似后的轮廓形状 # 绘制最大轮廓并显示 image_contour cv2.drawContours(image.copy(), [screenCnt], -1, color(0, 255, 0), thickness2) cv2.imshow(image_contour, image_contour) cv2.waitKey(0)文档通常是图像中面积最大的矩形物体所以这里通过面积排序找到最大轮廓并通过轮廓近似算法将其转换为四边形。2.4.透视变换并保存结果# 应用四点透视变换注意要将坐标还原到原始图像尺寸 warped four_point_transform(orig, screenCnt.reshape(4, 2) * ratio) # 保存变换后的图像 cv2.imwrite(filenameinvoice_new.jpg, imgwarped) # 显示变换后的图像 cv2.namedWindow(xx, cv2.WINDOW_NORMAL) # 创建可调整大小的窗口 cv2.imshow(xx, matwarped) cv2.waitKey(0)3.总结整个程序的核心思想是读取图像并适当缩放通过图像处理技术找到文档的边缘轮廓利用透视变换将倾斜的文档转换为正视图保存和显示处理结果最后我们还可以通过之前学习的旋转、阈值处理和图像形态学等让图片中的文字更加突出import cv2 import numpy as np imgcv2.imread(invoice_new.jpg) imgcv2.resize(img,dsizeNone,fx0.4,fy0.4) rotated_image1 cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE) cv2.imshow(ni90,rotated_image1) cv2.waitKey(0) ret, binary cv2.threshold(rotated_image1, 125, 255, cv2.THRESH_BINARY) cv2.imshow( binary, binary) # 偏白的变纯白偏黑的变纯黑 cv2.waitKey(0) kernel np.ones((2,2),np.uint8) # 这里kernel大小修改为5*5试试 erosion_1 cv2.erode(binary,kernel,iterations1) #iterations改为5试试 cv2.imshow(erosion_1,erosion_1) cv2.waitKey(0)

相关新闻

Claude与GLM-4-9B-Chat-1M对比:长上下文处理能力评测

Claude与GLM-4-9B-Chat-1M对比:长上下文处理能力评测

Claude与GLM-4-9B-Chat-1M对比:长上下文处理能力评测 1. 评测背景与意义 长上下文处理能力是当前大语言模型发展的重要方向,它直接决定了模型在实际应用中的表现。今天我们来对比两个在长文本处理方面表现突出的模型:Anthropic的Claude和智…

2026/7/5 16:10:47 阅读更多 →
Asian Beauty Z-Image Turbo 低代码集成:在Dify平台上快速构建AI图像生成应用

Asian Beauty Z-Image Turbo 低代码集成:在Dify平台上快速构建AI图像生成应用

Asian Beauty Z-Image Turbo 低代码集成:在Dify平台上快速构建AI图像生成应用 最近在帮一个做文创产品的朋友解决一个头疼的问题:他们想为每款新产品生成一些风格独特的宣传图,但团队里没有专业的设计师,外包又贵又慢。他们试过一…

2026/7/5 22:54:16 阅读更多 →
GARbro视觉小说资源处理全攻略:从入门到精通

GARbro视觉小说资源处理全攻略:从入门到精通

GARbro视觉小说资源处理全攻略:从入门到精通 【免费下载链接】GARbro Visual Novels resource browser 项目地址: https://gitcode.com/gh_mirrors/ga/GARbro 一、认知层:理解GARbro的核心价值 1.1 视觉小说资源处理的技术挑战 作为视觉小说爱好…

2026/5/17 7:42:59 阅读更多 →

最新新闻

[实例] SPI接口的ADC芯片全通道纯硬件驱动——基于HAL库和TLA2518芯片

[实例] SPI接口的ADC芯片全通道纯硬件驱动——基于HAL库和TLA2518芯片

本次需要通过TI的TL2518芯片进行ADC采样。该芯片为SPI接口,具有八个通道,可以全部配置成AIN进行采样,本次需要探究如何该如何配置才能将芯片的采样率达到最大。1.TLA2158首先要陈列一下该芯片的一些特性,为节省篇幅,此…

2026/7/6 3:48:11 阅读更多 →
【全文系列目录】风控PM记

【全文系列目录】风控PM记

风控PM记 一:风险认知与识别(入门篇) ① 入门第一课:认识风险,了解风控 ② 入门第二课:业务催生风险,常见的业务风险有哪些? ③ 《电商风控入门:我们到底在“防”什…

2026/7/6 3:48:11 阅读更多 →
基于Databricks的企业级AI Agent生产实践:从架构设计到部署运维

基于Databricks的企业级AI Agent生产实践:从架构设计到部署运维

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 如果你正在考虑将AI Agent引入企业生产环境,可能会面临这样的困境:在本地开发环境中跑得飞快的Agent原型&…

2026/7/6 3:42:09 阅读更多 →
飞书卡片表格渲染踩坑记:从 Markdown 到原生 table 组件的迁移实战

飞书卡片表格渲染踩坑记:从 Markdown 到原生 table 组件的迁移实战

背景 团队每日通过飞书推送项目晨报和日报,内容从项目管理平台实时拉取,包含任务统计、进度列表、风险项等多维数据,天然需要表格来承载。 最初的实现方案是飞书消息推送 纯文本,格式简陋,阅读体验差。于是决定升级为…

2026/7/6 3:40:09 阅读更多 →
构建AI毒舌投资人:用Prompt工程验证副业想法的可行性

构建AI毒舌投资人:用Prompt工程验证副业想法的可行性

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在折腾各种 AI 工具时,我发现一个挺有意思的现象:很多人拿到一个强大的 AI 模型,比如 DeepSee…

2026/7/6 3:40:09 阅读更多 →
认识安企CMS-系统和模板文件结构

认识安企CMS-系统和模板文件结构

了解安企CMS安装后的完整目录结构,掌握主程序、配置文件、模板目录、附件目录、运行时数据等每个关键目录和文件的具体作用,方便后续日常维护和二次开发。安企CMS 安装后的完整目录结构概览,带你了解每个目录和文件的用途。一、顶层目录结构 …

2026/7/6 3:40:09 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻