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

《OpenCV》——图像透视转换

图像透视转换简介

  • 在 OpenCV 里,图像透视转换属于重要的几何变换,也被叫做投影变换。下面从原理、实现步骤、相关函数和应用场景几个方面为你详细介绍。

原理

在这里插入图片描述

实现步骤

  • 选取对应点:要在源图像和目标图像上分别找出至少四个对应的点。这些对应点不能共线,因为它们是计算透视变换矩阵的关键依据。
  • 计算透视变换矩阵:利用 OpenCV 的 cv2.getPerspectiveTransform 函数,依据前面选取的对应点来计算透视变换矩阵。
  • 应用透视变换:使用 cv2.warpPerspective 函数,将计算得到的透视变换矩阵应用到源图像上,从而得到透视变换后的图像。

相关函数

  • cv2.getPerspectiveTransform
    • 功能:计算透视变换矩阵。
    • 语法:cv2.getPerspectiveTransform(src, dst)
    • 参数:
      • src:源图像中四个点的坐标,数据类型为 np.float32。
      • dst:目标图像中对应的四个点的坐标,数据类型为 np.float32。
  • 返回值:返回一个 3×3 的透视变换矩阵。
  • cv2.warpPerspective
    • 功能:对图像应用透视变换。
    • 语法:cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
    • 参数:
      • src:源图像。
      • M:透视变换矩阵。
      • dsize:输出图像的大小,格式为 (width, height)。
      • dst(可选):输出图像。
      • flags(可选):插值方法,如 cv2.INTER_LINEAR 等。
      • borderMode(可选):边界填充模式。
      • borderValue(可选):边界填充值。
  • 返回值:返回透视变换后的图像。

应用场景

  • 图像校正:校正因拍摄角度倾斜而产生畸变的图像,例如校正拍摄的文档图像,使其呈现为标准的矩形。
  • 虚拟现实:在虚拟现实场景中,将二维图像转换为具有透视效果的三维场景,增强沉浸感。
  • 自动驾驶:对车载摄像头拍摄的图像进行透视变换,以获取道路的鸟瞰图,辅助车辆进行路径规划和障碍物检测。

图像透视转换实例

对以下图片进行图像透视转换:
在这里插入图片描述

实例步骤

导入所需库

import numpy as np
import cv2

写入所需函数

def resize(image, width=None, height=None, inter=cv2.INTER_AREA):# 初始化 dim 为 None,用于存储调整后的图像尺寸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))# 使用 cv2.resize 函数根据 dim 和指定的插值方法对图像进行缩放resized = cv2.resize(image, dim, interpolation=inter)# 返回缩放后的图像return resized# 定义一个函数用于显示图像
# name: 显示窗口的名称
# img: 要显示的图像
def cv_show(name,img):# 使用cv2.imshow函数显示图像,第一个参数是窗口名称,第二个参数是要显示的图像cv2.imshow(name,img)# 使用cv2.waitKey(0)等待用户按键,参数为0表示无限等待cv2.waitKey(0)# 定义一个函数用于对输入的四个点进行排序
# pts: 输入的四个点的坐标,是一个形状为(4, 2)的numpy数组
def order_points(pts):# 创建一个形状为(4, 2)的全零数组,数据类型为float32,用于存储排序后的点rect = np.zeros((4,2),dtype="float32")# 计算每个点的x和y坐标之和s = pts.sum(axis=1)# 找到坐标和最小的点,这个点通常是左上角的点rect[0]=pts[np.argmin(s)]# 找到坐标和最大的点,这个点通常是右下角的点rect[2]=pts[np.argmax(s)]# 计算每个点的x和y坐标之差diff = np.diff(pts,axis=1)# 找到坐标差最小的点,这个点通常是右上角的点rect[1]=pts[np.argmin(diff)]# 找到坐标差最大的点,这个点通常是左下角的点rect[3]=pts[np.argmax(diff)]# 返回排序后的四个点return rect# 定义一个函数用于进行四点透视变换
# image: 输入的原始图像
# pts: 输入的四个点的坐标,是一个形状为(4, 2)的numpy数组
def four_point_transform(image,pts):# 调用order_points函数对输入的四个点进行排序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))# 创建一个形状为(4, 2)的numpy数组,用于存储变换后的四个点的坐标dst = np.array([[0,0],[maxWidth-1,0],[maxWidth-1,maxHeight-1],[0,maxHeight-1]],dtype="float32")# 使用cv2.getPerspectiveTransform函数计算透视变换矩阵M = cv2.getPerspectiveTransform(rect,dst)# 使用cv2.warpPerspective函数进行透视变换,得到变换后的图像warped = cv2.warpPerspective(image,M,(maxWidth,maxHeight))# 返回变换后的图像return warped

获取图片信息并处理图片

import cv2# 读取指定路径的图片,返回一个表示图像的多维数组
image = cv2.imread('dan_zi.jpg')
# 调用自定义的cv_show函数展示原始图像,窗口名为'image'
cv_show('image', image)# 计算原始图像高度与500像素的比例,后续用于恢复尺寸
ration = image.shape[0] / 500.0
# 复制原始图像,避免后续操作修改原始数据
orig = image.copy()
# 调用resize函数将图像高度调整为500像素,保持宽高比
image = resize(orig, height=500)
# 调用cv_show函数展示调整大小后的图像,窗口名为'1'
cv_show('1', image)# 打印提示信息,表明进入轮廓检测步骤
print("STEP 1: 轮廓检测")
# 将调整大小后的图像从BGR颜色空间转换为灰度颜色空间
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 运用Otsu's算法进行二值化处理,得到二值化后的图像
edged = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 在二值化图像的副本上查找轮廓,使用RETR_LIST检索模式和CHAIN_APPROX_SIMPLE近似方法
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
# 在图像副本上绘制所有检测到的轮廓,颜色为红色,线条宽度为1像素
image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 1)
# 调用cv_show函数展示绘制了所有轮廓的图像,窗口名为'image_contours'
cv_show("image_contours", image_contours)# 打印提示信息,表明进入获取最大轮廓步骤
print("STEP 2:获取最大轮廓")
# 按轮廓面积从大到小对检测到的轮廓进行排序,选取面积最大的轮廓
screenCnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]# 计算最大轮廓的周长,参数True表示轮廓是封闭的
peri = cv2.arcLength(screenCnt, True)
# 对最大轮廓进行多边形逼近,以减少轮廓上的点数,第二个参数为逼近精度
screenCnt = cv2.approxPolyDP(screenCnt, 0.02 * peri, True)
# 打印逼近后轮廓的形状信息
print(screenCnt.shape)# 在图像副本上绘制逼近后的最大轮廓,颜色为绿色,线条宽度为2像素
image_contour = cv2.drawContours(image.copy(), [screenCnt], -1, (0, 255, 0), 2)# 展示绘制了最大逼近轮廓的图像,窗口名为'image_contour'
cv2.imshow("image_contour", image_contour)
# 等待用户按键,防止窗口立即关闭
cv2.waitKey(0)

进行透视转换

# 调用之前定义的 four_point_transform 函数对原始图像进行四点透视变换
# screenCnt.reshape(4, 2) * ration 是将之前获取的轮廓点恢复到原始图像的尺寸
warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ration)
# 将透视变换后的图像保存为 invoice_new.jpg
cv2.imwrite("invoice_new.jpg", warped)
# 创建一个名为 "xxxxx" 的窗口,并且该窗口大小可以调整
cv2.namedWindow("xxxxx", cv2.WINDOW_NORMAL)
# 在 "xxxxx" 窗口中显示透视变换后的图像
cv2.imshow("xxxxx", warped)
# 等待用户按键,防止窗口立即关闭
cv2.waitKey(0)# 将透视变换后的图像从 BGR 颜色空间转换为灰度颜色空间
warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
# 调用 resize 函数将灰度图像的宽度调整为 400 像素
warped = resize(warped, 400)
# 对调整大小后的灰度图像使用 Otsu's 算法进行二值化处理
warped = cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 调用自定义的 cv_show 函数显示二值化后的图像,窗口名为 "1111"
cv_show("1111", warped)# 创建一个 1x1 的矩形结构元素,用于形态学操作
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))
# 对二值化后的图像进行闭运算,填充小孔和连接相邻物体
closeX = cv2.morphologyEx(warped, cv2.MORPH_CLOSE, rectKernel)
# 调用自定义的 cv_show 函数显示闭运算后的图像,窗口名为 'gradX'
cv_show('gradX', closeX)

结果显示

在这里插入图片描述

invoice_new.jpg
在这里插入图片描述

在这里插入图片描述

如果不想使用这张照片,换其他图片也是可以的,处理步骤都是相同的

相关文章:

《OpenCV》——图像透视转换

图像透视转换简介 在 OpenCV 里,图像透视转换属于重要的几何变换,也被叫做投影变换。下面从原理、实现步骤、相关函数和应用场景几个方面为你详细介绍。 原理 实现步骤 选取对应点:要在源图像和目标图像上分别找出至少四个对应的点。这些对…...

9 点结构模块(point.rs)

一、point.rs源码 use super::UnknownUnit; use crate::approxeq::ApproxEq; use crate::approxord::{max, min}; use crate::length::Length; use crate::num::*; use crate::scale::Scale; use crate::size::{Size2D, Size3D}; use crate::vector::{vec2, vec3, Vector2D, V…...

Java线程认识和Object的一些方法ObjectMonitor

专栏系列文章地址:https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标: 要对Java线程有整体了解,深入认识到里面的一些方法和Object对象方法的区别。认识到Java对象的ObjectMonitor,这有助于后面的Synchron…...

【高等数学】贝塞尔函数

贝塞尔函数(Bessel functions)是数学中一类重要的特殊函数,通常用于解决涉及圆对称或球对称的微分方程。它们在物理学、工程学、天文学等多个领域都有广泛的应用,例如在波动方程、热传导方程、电磁波传播等问题中。 贝塞尔函数的…...

99.20 金融难点通俗解释:中药配方比喻马科维茨资产组合模型(MPT)

目录 0. 承前1. 核心知识点拆解2. 中药搭配比喻方案分析2.1 比喻的合理性 3. 通俗易懂的解释3.1 以中药房为例3.2 配方原理 4. 实际应用举例4.1 基础配方示例4.2 效果说明 5. 注意事项5.1 个性化配置5.2 定期调整 6. 总结7. 代码实现 0. 承前 本文主旨: 本文通过中…...

实现使用K210单片机进行猫脸检测,并在检测到猫脸覆盖屏幕50%以上时执行特定操作

要实现使用K210单片机进行猫脸检测,并在检测到猫脸覆盖屏幕50%以上时执行特定操作,以及通过WiFi上传图片到微信小程序,并在微信小程序中上传图片到开发板进行训练,可以按照以下步骤进行: 1. 硬件连接 确保K210开发板…...

小程序设计和开发:如何研究同类型小程序的优点和不足。

一、确定研究目标和范围 明确研究目的 在开始研究同类型小程序之前,首先需要明确研究的目的。是为了改进自己的小程序设计和开发,还是为了了解市场趋势和用户需求?不同的研究目的会影响研究的方法和重点。例如,如果研究目的是为了…...

tiktok 国际版抖抖♬♬ X-Bogus参数算法逆向分析

加密请求参数得到乱码,最终得到X-Bogus...

Redis 基础命令

1. redis 命令官网 https://redis.io/docs/latest/commands/ 2. 在 redis-cli 中使用 help 命令 # 查看 help string 基础命令 keys * # * 代表通配符set key value # 设置键值对del key # 删除键expire key 时间 # 给键设置时间 # -2 代表时间到期了, -1 代表…...

深入解析Python机器学习库Scikit-Learn的应用实例

深入解析Python机器学习库Scikit-Learn的应用实例 随着人工智能和数据科学领域的迅速发展,机器学习成为了当下最炙手可热的技术之一。而在机器学习领域,Python作为一种功能强大且易于上手的编程语言,拥有庞大的生态系统和丰富的机器学习库。其…...

专业的定制版软件,一键操作,无限使用

今天给大家介绍一个专业的PDF转word的小软件,软件只有5.5M。非常小,而且没有文档大小的限制,可以随意使用。 PDFtu PDF转word 软件第一次使用需要安装一下。 安装好之后,我们就能在桌面找到对应的图标,打开就能直接使…...

小程序-基础加强

前言 这一节把基础加强讲完 1. 导入需要用到的小程序项目 2. 初步安装和使用vant组件库 这里还可以扫描二维码 其中步骤四没什么用 右键选择最后一个 在开始之前,我们的项目根目录得有package.json 没有的话,我们就初始化一个 但是我们没有npm这个…...

pytorch实现基于Word2Vec的词嵌入

PyTorch 实现 Word2Vec(Skip-gram 模型) 的完整代码,使用 中文语料 进行训练,包括数据预处理、模型定义、训练和测试。 1. 主要特点 支持中文数据,基于 jieba 进行分词 使用 Skip-gram 进行训练,适用于小数…...

流媒体娱乐服务平台在AWS上使用Presto作为大数据的交互式查询引擎的具体流程和代码

一家流媒体娱乐服务平台拥有庞大的用户群体和海量的数据。为了高效处理和分析这些数据,它选择了Presto作为其在AWS EMR上的大数据查询引擎。在AWS EMR上使用Presto取得了显著的成果和收获。这些成果不仅提升了数据查询效率,降低了运维成本,还…...

鸿蒙 循环控制 简单用法

效果 简单使用如下: class Item {id: numbername: stringprice: numberimg: stringdiscount: numberconstructor(id: number, name: string, price: number, img: string, discount: number) {this.id idthis.name namethis.price pricethis.img imgthis.discou…...

四、GPIO中断实现按键功能

4.1 GPIO简介 输入输出(I/O)是一个非常重要的概念。I/O泛指所有类型的输入输出端口,包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口。而GPIO(General-Purpose Input/Output)则是一个常见的术语&#xff0c…...

Linux安装zookeeper

1, 下载 Apache ZooKeeperhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apa…...

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:贪心算法篇–CSDN博客 文章目录 前言例题1.买卖股票的最佳时机2.买卖股票的最佳时机23.k次取…...

007 JSON Web Token

文章目录 https://doc.hutool.cn/pages/jwt/#jwt%E4%BB%8B%E7%BB%8D JWT是一种用于双方之间安全传输信息的简洁的、URL安全的令牌标准。这个标准由互联网工程任务组(IETF)发表,定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。…...

Windsurf cursor vscode+cline 与Python快速开发指南

Windsurf简介 Windsurf是由Codeium推出的全球首个基于AI Flow范式的智能IDE,它通过强大的AI助手功能,显著提升开发效率。Windsurf集成了先进的代码补全、智能重构、代码生成等功能,特别适合Python开发者使用。 Python环境配置 1. Conda安装…...

ant-design 1.x版本表格头部拖拽、可拖拽列实现

表格列宽拖拽调整 — 问题总结 版本 “vue”: “2.6.11”,“vue-draggable-resizable”: “^2.3.0”,"ant-design “:”1.7.0“ 问题 1:thDom 为 null 导致 getBoundingClientRect 报错 现象: TypeError: Cannot read properties of nul…...

维吾尔语AI语音最后一公里难题:ElevenLabs+Kaldi联合方案实现方言变体(伊犁/喀什/和田)动态适配(含开源声学适配器)

更多请点击: https://intelliparadigm.com 第一章:维吾尔语AI语音最后一公里难题的本质剖析 维吾尔语AI语音系统在实验室环境中已能实现较高识别准确率,但落地至真实场景时仍面临显著性能衰减——这一“最后一公里”并非技术迭代的自然延迟&…...

八千多条提示词,装成你的「随身工具箱」

做图、想创意的时候,最烦的不是「不会写」,而是找不到、和不好管,写过的好句子不知道丢哪了。群里转发的、自己试出来的、收藏夹里吃灰的链接——真要用时,往往只记得个大概,翻半天也找不回来。 BoltPrompt 提示词库想…...

Taotoken用量看板如何帮助团队管理大模型API成本

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken用量看板如何帮助团队管理大模型API成本 作为团队的技术负责人,在引入大模型能力支持多个项目时,一…...

终极文档下载神器:30+平台一键免费保存,告别繁琐下载流程

终极文档下载神器:30平台一键免费保存,告别繁琐下载流程 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该…...

Heightmapper完全指南:5步将全球地形数据变成3D模型

Heightmapper完全指南:5步将全球地形数据变成3D模型 【免费下载链接】heightmapper interactive heightmaps from terrain data 项目地址: https://gitcode.com/gh_mirrors/he/heightmapper 还在为3D地形建模发愁吗?Heightmapper让你的地形创作效…...

大语言模型记忆增强框架:LightMem原理、实现与工程实践

1. 项目概述:当大模型遇上“记忆”瓶颈最近在折腾大语言模型(LLM)应用开发的朋友,估计都遇到过同一个头疼的问题:模型记不住事儿。你精心设计了一个对话系统,希望它能记住用户的历史偏好,比如“…...

Claude与Codex双引擎协作:AI代码生成的新范式与实践

1. 项目概述:当Claude遇上Codex,双引擎驱动的代码生成新范式最近在GitHub上看到一个挺有意思的项目,叫claude-codex-duo。光看名字,你大概就能猜到它的核心玩法——把Anthropic的Claude和OpenAI的Codex这两个顶级的AI模型给“撮合…...

别再只当扫码枪用了!用Python+GM861S模块,DIY一个智能物料盘点小工具

用PythonGM861S模块打造智能物料盘点系统 在仓库管理和生产制造场景中,物料盘点是项耗时又容易出错的工作。传统扫码枪往往只作为简单数据采集工具,而结合Python编程能力,我们可以将GM861S这类高性能扫码模块升级为智能终端。这个项目将展示如…...

Node.js连接币安生态:MCP社区工具实战与架构解析

1. 项目概述:一个连接Node.js与币安生态的MCP社区工具最近在捣鼓一些加密货币数据分析和自动化策略的时候,发现了一个挺有意思的项目,叫node2flow-th/binance-th-mcp-community。光看这个名字,可能有点摸不着头脑,但拆…...