opencv之几何变换

文章目录

  • 1 前言
  • 2 线性几何变换的主要类型
    • 2.1 平移 (Translation):
      • 2.1.1 定义
      • 2.1.2代码
    • 2.2 缩放 (Scaling):
      • 2.2.1 定义
      • 2.2.2 代码
    • 2.3 旋转 (Rotation):
      • 2.3.1 定义
      • 2.3.2 代码
    • 2.4 仿射变换 (Affine Transformation):
      • 2.4.1 定义
      • 2.4.2 代码
    • 2.5 透视变换 (Perspective Transformation):
      • 2.5.1定义
      • 2.5.2 代码
    • 2.6线性几何变换的应用
  • 3.重映射
    • 3.1定义
    • 代码
      • cv2.remap()函数
      • 应用场景
      • 注意事项
  • 彩蛋
      • 重映射的独特性
      • 为什么没有将重映射与其他几何变换一起介绍
      • 重映射与其他几何变换的关系

1 前言

几何变换是计算机图像处理中的一种操作,用于对图像的几何结构进行修改。通过几何变换,可以实现图像的旋转、缩放、平移、扭曲等效果,从而改变图像的形状、位置和方向。这些变换可以是线性的或非线性的,通常使用数学矩阵来表示和计算。

一般公式

d s t ( x , y ) = s r c ( M 11 ⋅ x + M 12 ⋅ y + M 13 , M 21 ⋅ x + M 22 ⋅ y + M 23 ) dst(x, y)=src(M_{11}⋅x+M_{12}⋅y+M_{13}, M_{21}⋅x+M_{22}⋅y+M_{23}) dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)

x , y x,y x,y表示原图像素的位置坐标, M M M表示进行变换操作的矩阵。

几何变换的实现步骤

  1. 定义变换矩阵:根据所需的几何变换类型(如平移、旋转、缩放等),创建对应的变换矩阵。
  2. 应用变换矩阵:使用变换矩阵将输入图像的每个像素位置重新计算,以生成输出图像。
  3. 插值计算:由于变换后像素的新位置可能是非整数坐标,需使用插值方法(如最近邻、双线性插值等)计算新像素位置的像素值。
  4. 生成输出图像:根据重新计算后的像素位置和插值结果,生成经过几何变换的输出图像。

2 线性几何变换的主要类型

2.1 平移 (Translation):

2.1.1 定义

  • 将图像中的所有像素点按固定距离移动。
  • 数学表达式: T ( x , y ) = ( x + t x , y + t y ) T(x,y)=(x+tx,y+ty) T(x,y)=(x+tx,y+ty)
  • 其中 t x tx tx t y ty ty 是在 x 轴和 y 轴上的平移量。

平移操作将图像的每个像素点按指定的距离移动。在 OpenCV 中,可以使用 cv2.warpAffine() 来实现平移。

2.1.2代码

import cv2
import numpy as np# 读取图像
image = cv2.imread('image.jpg')# 创建平移矩阵
tx, ty = 100, 50  # x轴和y轴的平移量
translation_matrix = np.float32([[1, 0, tx], [0, 1, ty]])# 应用平移变换
translated_image = cv2.warpAffine(image, translation_matrix, (image.shape[1], image.shape[0]))# 显示结果
cv2.imshow('Translated Image', translated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.2 缩放 (Scaling):

2.2.1 定义

  • 改变图像的尺寸(放大或缩小)。
  • 数学表达式: S ( x , y ) = ( α ⋅ x , β ⋅ y ) S(x,y)=(\alpha⋅x,\beta⋅y) S(x,y)=(αx,βy)
  • 其中 α \alpha α β \beta β是在 x x x 轴和$ y$ 轴上的缩放因子。

缩放操作改变图像的尺寸。缩放因子决定了图像的放大或缩小程度。

2.2.2 代码

import cv2# 读取图像
image = cv2.imread('image.jpg')# 缩放因子
scale_x, scale_y = 1.5, 1.5  # x轴和y轴的缩放因子
scaled_image = cv2.resize(image, None, fx=scale_x, fy=scale_y, interpolation=cv2.INTER_LINEAR)# 显示结果
cv2.imshow('Scaled Image', scaled_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.3 旋转 (Rotation):

2.3.1 定义

  • 将图像绕其中心点旋转指定的角度。
  • 数学表达式: R ( x , y ) = ( x ⋅ c o s ⁡ ( θ ) − y ⋅ s i n ⁡ ( θ ) , x ⋅ s i n ⁡ ( θ ) + y ⋅ c o s ⁡ ( θ ) ) R(x,y)=(x⋅cos⁡(θ)−y⋅sin⁡(θ),x⋅sin⁡(θ)+y⋅cos⁡(θ)) R(x,y)=(xcos(θ)ysin(θ),xsin(θ)+ycos(θ))
  • 其中 θ \theta θ 是旋转角度。

旋转操作将图像绕其中心旋转一定的角度。需要定义旋转矩阵并使用 cv2.warpAffine() 来应用旋转。

2.3.2 代码

import cv2
import numpy as np# 读取图像
image = cv2.imread('image.jpg')# 获取图像的中心
center = (image.shape[1] // 2, image.shape[0] // 2)# 创建旋转矩阵
angle = 45  # 旋转角度
scale = 1.0  # 缩放因子
rotation_matrix = cv2.getRotationMatrix2D(center, angle, scale)# 应用旋转变换
rotated_image = cv2.warpAffine(image, rotation_matrix, (image.shape[1], image.shape[0]))# 显示结果
cv2.imshow('Rotated Image', rotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.4 仿射变换 (Affine Transformation):

仿射变换是一种更复杂的变换,可以同时包括平移、缩放和旋转。仿射变换的矩阵是一个2x3的矩阵。

在这里插入图片描述

2.4.1 定义

  • 一种保平行的变换,允许进行平移、旋转、缩放和剪切。
  • 数学表达式: A ( x , y ) = ( a ⋅ x + b ⋅ y + t x , c ⋅ x + d ⋅ y + t y ) A(x,y)=(a⋅x+b⋅y+tx,c⋅x+d⋅y+ty) A(x,y)=(ax+by+tx,cx+dy+ty)
  • 其中 a a a, b b b, c c c, d d d , t x tx tx t y ty ty 是变换矩阵的参数。

2.4.2 代码

import cv2
import numpy as np# 读取图像
image = cv2.imread('image.jpg')# 定义原始图像中的三点和目标图像中的三点
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])# 计算仿射矩阵
affine_matrix = cv2.getAffineTransform(pts1, pts2)# 应用仿射变换
affine_transformed_image = cv2.warpAffine(image, affine_matrix, (image.shape[1], image.shape[0]))# 显示结果
cv2.imshow('Affine Transformed Image', affine_transformed_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.5 透视变换 (Perspective Transformation):

2.5.1定义

  • 处理图像的透视效果,通常用于校正图像中的透视扭曲。
  • 数学表达式: P ( x , y ) = ( a ⋅ x + b ⋅ y + c d ⋅ x + e ⋅ y + f , g ⋅ x + h ⋅ y + i d ⋅ x + e ⋅ y + f ) P(x,y)=(\frac{a⋅x+b⋅y+c}{d⋅x+e⋅y+f},\frac{g⋅x+h⋅y+i}{d⋅x+e⋅y+f}) P(x,y)=(dx+ey+fax+by+c,dx+ey+fgx+hy+i)
  • 其中 a , b , c , d , e , f , g , h , 和 i a, b, c, d, e, f, g, h, 和 i a,b,c,d,e,f,g,h,i 是透视矩阵的参数。

透视变换允许你将图像从一个视角转换到另一个视角。需要定义四个点来创建透视矩阵。

2.5.2 代码

import cv2
import numpy as np# 读取图像
image = cv2.imread('image.jpg')# 定义原始图像中的四点和目标图像中的四点
pts1 = np.float32([[50, 50], [200, 50], [50, 200], [200, 200]])
pts2 = np.float32([[10, 100], [220, 30], [30, 220], [210, 210]])# 计算透视矩阵
perspective_matrix = cv2.getPerspectiveTransform(pts1, pts2)# 应用透视变换
perspective_transformed_image = cv2.warpPerspective(image, perspective_matrix, (image.shape[1], image.shape[0]))# 显示结果
cv2.imshow('Perspective Transformed Image', perspective_transformed_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.6线性几何变换的应用

  • 图像校正:修正图像中的畸变和透视问题。
  • 图像增强:通过缩放、旋转等方法提高图像的可视效果。
  • 特效生成:创建视觉效果,如模拟相机拍摄角度等。
  • 目标检测与识别:对图像中的目标进行标准化处理,提高算法的准确性。

线性几何变换在计算机视觉和图像处理领域中扮演了重要角色,帮助实现各种图像操作和分析。

3.重映射

3.1定义

  • 重映射是指根据特定的映射函数,将输入图像的像素位置重新映射到输出图像的新位置。这种映射可以是线性的或非线性的,具体取决于所需的变换效果。
  • 数学表达式: g ( x , y ) = f ( h ( x , y ) ) g(x,y)=f(h(x,y)) g(x,y)=f(h(x,y)),假设 h ( x , y ) = x 2 + y h(x,y)=x^{2}+y h(x,y)=x2+y, 则有 g ( x , y ) = f ( x 2 , y ) g(x,y)=f(x^{2},y) g(x,y)=f(x2,y)
  • 其中 f ( x , y ) f(x,y) f(x,y)是原图像函数, g ( x , y ) g(x,y) g(x,y)是目标图像函数, h ( x , y ) h(x,y) h(x,y)是映射函数

重映射的过程

  1. 映射函数的定义:通过函数或映射矩阵定义图像中每个像素的位置变化。映射函数通常根据图像处理需求确定,例如几何变换、去畸变等。
  2. 重新计算像素位置:对于每个像素 (x, y),使用映射函数计算其在输出图像中的新位置 (x', y')
  3. 像素值的插值:由于新位置 (x', y') 可能不是整数,因此需要通过插值方法(如最近邻、双线性插值等)计算出该位置的像素值。
  4. 生成输出图像:将所有像素的新位置和对应的像素值合成,生成变换后的输出图像。

代码

重映射(Remapping)是通过函数 cv2.remap() 来实现的。这个函数可以将图像的每个像素点根据提供的映射规则重新定位。重映射在图像校正、图像扭曲、去畸变等操作中非常有用。

cv2.remap()函数

cv2.remap() 的基本语法如下:

dst = cv2.remap(src, map_x, map_y, interpolation)

src:输入图像。

map_xmap_y:指定图像中每个像素在输出图像中的新位置。map_xmap_y 是浮点数矩阵,大小与输入图像相同。map_x 存储每个像素新的 x 坐标,map_y 存储新的 y 坐标。

interpolation:插值方法,用于插值像素值。常见的方法有:

  • cv2.INTER_NEAREST:最近邻插值。
  • cv2.INTER_LINEAR:双线性插值(默认)。
  • cv2.INTER_CUBIC:双三次插值。
  • cv2.INTER_LANCZOS4:Lanczos 插值。

以下是一个使用 cv2.remap() 实现图像水平翻转的例子:

import cv2
import numpy as np# 读取图像
src = cv2.imread('input_image.jpg')# 获取图像尺寸
height, width = src.shape[:2]# 创建映射矩阵
map_x = np.zeros((height, width), dtype=np.float32)
map_y = np.zeros((height, width), dtype=np.float32)# 填充映射矩阵,使图像水平翻转
for i in range(height):for j in range(width):map_x[i, j] = width - 1 - jmap_y[i, j] = i# 应用重映射
dst = cv2.remap(src, map_x, map_y, cv2.INTER_LINEAR)# 显示结果
cv2.imshow('Original Image', src)
cv2.imshow('Remapped Image', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

应用场景

  1. 去畸变:通过校正镜头的畸变,得到更加真实的图像。
  2. 图像校正:将图像从一种投影坐标系变换到另一种坐标系,例如鱼眼图像的校正。
  3. 图像扭曲:根据需求对图像进行各种扭曲和变形处理。

注意事项

  • map_xmap_y 通常是通过某种函数生成的,基于目标效果。
  • 如果需要实现一些常见的几何变换(如平移、旋转、缩放),通常仿射变换或透视变换更为高效和方便。

cv2.remap() 是一个非常强大的函数,可以实现许多复杂的图像处理任务。

彩蛋

与前面提到的平移、旋转、缩放等标准的几何变换不同,重映射更为灵活和通用。它允许对图像的每个像素位置进行任意的重新映射,而不仅仅是线性变换。因此,虽然它属于广义上的几何变换,但其功能和应用场景与传统的几何变换有些不同。

重映射的独特性

  • 任意变换:与平移、旋转、缩放等仿射变换不同,重映射可以实现任意的变换。通过提供映射矩阵 map_xmap_y,可以自由地将图像的像素点重新分配到新的位置,这使得重映射比其他几何变换更加灵活和强大。
  • 广泛应用:重映射可以用于图像扭曲、鱼眼矫正、投影变换等复杂的图像处理任务。

为什么没有将重映射与其他几何变换一起介绍

  1. 操作方式不同:平移、旋转、缩放、仿射变换和透视变换都是基于矩阵运算的几何变换,通常可以通过定义一个变换矩阵直接应用到整个图像。而重映射则是基于像素级的映射,通过对每个像素的坐标进行独立计算来实现,操作上有所不同。
  2. 灵活度不同:其他几何变换的变换矩阵通常是线性的,遵循特定的规则,而重映射允许任意的非线性变换,这种高度的自由度使其更适合被单独讨论。
  3. 应用场景不同:重映射经常用于复杂的图像处理任务,而传统的几何变换更常用于图像的基本变换(如旋转、缩放)。

重映射与其他几何变换的关系

尽管重映射与平移、旋转、缩放等有操作上的差异,但它们都属于图像几何变换的范畴。在某些情况下,可以通过合适的重映射函数实现其他几何变换的效果,反之亦然。但由于重映射的灵活性,它更适合处理复杂的变换需求。

所以,重映射是一种广义的几何变换,其灵活性和功能性使得它在某些场景下更为适用,因此通常单独讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

全国地市未来产业水平数据集(2008-2023年)

未来产业,作为驱动经济社会高质量发展的核心引擎,是指依托科技创新和模式创新,引领全球新一轮科技革命和产业变革,具有前瞻性、先导性、战略性的新兴产业领域。也是实现生产力大解放,推动生产力质的跃迁并形成新质生产…

wacat - 一款开源随机测试工具

想象一下,你离开电脑一会儿去拿一杯咖啡。与此同时,你的猫走过键盘,引发了一些混乱。 wacat 应用程序: • 访问你的网页应用的根网址 • 随机访问应用中的每个链接 • 在表单中添加随机文本输入 • 从下拉菜单、复选框等中选择…

使用Redis如何实现集群会话同步?

使用Redis如何实现集群会话同步? 1、为什么选择Redis?2、如何实现?1. 环境准备2. 配置Web服务器3. 测试与验证4. 监控与优化 💖The Begin💖点点关注,收藏不迷路💖 在分布式Web应用中&#xff0c…

springboot高校实验室教学管理系统的设计和实现

基于springbootvue高校实验室教学管理系统的设计和实现(源码L文ppt)4-045 4 系统总体设计 此次高校实验室教学管理系统通过springboot框架。springboot适合快速构建Web应用。springboot将B/S设计模式中的视图分成了View模块和Template模块两部分,将动态的逻辑处理…

51单片机.之蜂鸣器振动播放歌曲

蜂鸣器发声是通过喇叭振动发声的&#xff0c;通电产生磁场&#xff0c;磁铁吸收&#xff0c;而振动。不断释放&#xff0c;吸收。 1、蜂鸣器发声&#xff0c;播放不同频率的声音逐渐变尖 #include<reg52.h>sbit BUZZ P1^6;unsigned char T0RH0; unsigned char T0RL0; v…

SpringCloud开发实战(二):通过RestTemplate实现远程调用

目录 SpringCloud开发实战&#xff08;一&#xff09;&#xff1a;搭建SpringCloud框架 RestTemplate介绍 RestTemplate 是 Spring 框架中的一个类&#xff0c;它用于促进 HTTP 请求的发送和接收&#xff0c;并且简化了与 RESTful 服务的交互。RestTemplate 提供了许多便利的方…

Redis Zset 类型:Score 属性在数据排序中的作用

Zset 有序集合 一 . zset 的引入二 . 常见命令2.1 zadd、zrange2.2 zcard2.3 zcount2.4 zrevrange、zrangebyscore2.5 zpopmax、zpopmin2.6 bzpopmax、bzpopmin2.7 zrank、zrevrank2.8 zscore2.9 zrem、zremrangebyrank、zremrangebyscore2.10 zincrby2.11 集合间操作交集 : zi…

【算法】PageRank

一、引言 PageRank是由谷歌创始人拉里佩奇和谢尔盖布林在斯坦福大学读研究生时发明的一种算法&#xff0c;用于衡量网页的重要性。它基于一个简单的假设&#xff1a;更重要的网页会有更多的链接指向它。 二、算法原理 PageRank算法的核心思想是&#xff0c;一个网页的重要性可以…

沸点 | LDBC 第18届 TUC 会议召开,专家孙宇熙受邀参加并发表演讲

图数据管理领域国际权威组织LDBC&#xff08;Linked Data Benchmark Council&#xff09;于8月30日至31日在广州举办了第18届LDBC TUC会议。作为图数据库领域的创新引领者&#xff0c;嬴图受邀参加此次盛会&#xff0c;国际高性能计算与存储系统专家、大数据专家、图专家及嬴图…

【从零开始学爬虫】采集58同城房源数据

本文以采集北京市58同城房源数据为例进行演示&#xff1a; l 采集网站 【场景描述】采集58同城房源数据。 【使用工具】前嗅ForeSpider数据采集系统 http://www.forenose.com/view/commodity/forespider.html 【入口网址】 https://bj.58.com/xiaoqu/?PGTID0d000000-000…

三、数组————相关概念详解

数组 前言一、数据理论基础二、数组常用操作2.1 初始化数组2.2 访问数组中的元素2.3 插入元素2.4 删除元素 三、数组扩展3.1 遍历数组3.2 数组扩容 总结1、数组的优点2、数组的不足 前言 在数据结构中&#xff0c;数组可以算得上最基本的数据结构。数组可以用于实现栈、队列、…

YoloV10改进策略:卷积篇|基于PConv的二次创新|附结构图|性能和精度得到大幅度提高(独家原创)

文章目录 摘要论文指导PConv在论文中的描述改进YoloV10的描述改进代码与结构图改进方法测试结果总结摘要 在PConv的基础上做了二次创新,创新后的模型不仅在精度和速度上有了质的提升,还可以支持Stride为2的降采样。 改进方法简单高效,需要发论文的同学不要错过! 论文指导…

机器学习实战篇——肿瘤良性/恶性分类器(二元逻辑回归)

机器学习之实战篇——肿瘤良性/恶性分类器&#xff08;二元逻辑回归&#xff09; 前言数据集和实验文件下载相关文章推荐实验过程导入相关模块数据预处理手写二元逻辑回归模型&#xff08;小批量梯度下降&#xff09;sklearn逻辑回归器 前言 实验中难免有许多缺陷和错误&#…

Mac M1安装Hive

一、下载解压Hive 1.官网地址 https://dlcdn.apache.org/hive/ 2.选择对应版本进行下载&#xff0c;这里我以3.1.3为例&#xff1b; 3.下载好后&#xff0c;进行解压&#xff0c;并重命名为hive-3.1.3&#xff0c;放到资源库目录下&#xff1b; 二、配置系统环境 1.打开~/…

Hack The Box-Infiltrator【更新中】

信息收集&端口利用 nmap -sSVC infiltrator.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-02 09:17 CST Nmap scan report for infiltrator.htb Host is up (0.61s latency). Not shown: 987 filtered tcp ports (no-response) PORT STATE SERVICE …

C++竞赛初阶L1-15-第六单元-多维数组(34~35课)551: T456501 计算矩阵边缘元素之和

题目内容 输入一个整数矩阵&#xff0c;计算位于矩阵边缘的元素之和。 所谓矩阵边缘的元素&#xff0c;就是第一行和最后一行的元素以及第一列和最后一列的元素。 输入格式 第 1 行包含两个整数&#xff0c;分别为行数 m 和列数 n&#xff0c;两个整数之间空格隔开。 第 2 …

【单调栈 】2289. 使数组按非递减顺序排列

本文涉及的基础知识点 单调栈分类、封装和总结 LeetCode2289. 使数组按非递减顺序排列 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&a…

Sobel算子,Scharr算子和Laplacian算子

图像边缘检测大幅度地减少了数据量&#xff0c;并且剔除了可以认为不相关的信息&#xff0c;保留了图像重要的结构属性。有许多方法用于边缘检测&#xff0c; 绝大部分可以划分为两类&#xff1a;基于搜索和基于零穿越。 基于搜索:通过寻找图像一阶导数中的最大值来检测边界&am…

4.1 数据分析-excel 基本操作

第四节&#xff1a;数据分析-excel 基本操作 课程目标 学会excel 基本操作 课程内容 数据伪造 产生一份招聘数据 import pandas as pd from faker import Faker import random import numpy as np# 创建一个Faker实例&#xff0c;用于生成假数据&#xff0c;指定中文本地…

c# 笔记 winform添加右键菜单,获取文件大小 ,多条件排序OrderBy、ThenBy,list<double>截取前5个

Winform右键菜单‌ 要在C# Winform应用程序中添加右键菜单&#xff0c;‌你可以按照以下步骤操作&#xff1a;‌ 1.‌创建菜单项‌ 在Form的构造函数或加载事件中&#xff0c;‌创建ContextMenuStrip控件的实例&#xff0c;‌并为其添加菜单项。‌ 2.‌绑定到控件‌ 将Con…