opencv-26 图像几何变换04- 重映射-函数 cv2.remap()

news2024/11/23 8:30:44

什么是重映射?

重映射(Remapping)是图像处理中的一种操作,用于将图像中的像素从一个位置映射到另一个位置。重映射可以实现图像的平移、旋转、缩放和透视变换等效果。它是一种基于像素级的图像变换技术,可以通过定义映射关系来改变图像的几何形状和外观。

在重映射中,我们需要定义一个映射表(Map),这个映射表指定了源图像中每个像素点在目标图像中的位置。对于每个像素点 (x, y),映射表告诉我们在目标图像中的新位置 (x’, y’)。通过对所有像素点进行映射,我们就可以得到经过重映射变换后的新图像。

在OpenCV中,可以使用 cv2.remap() 函数来执行重映射操作。cv2.remap() 接受输入图像和一个表示映射关系的两个浮点型数组(map_x 和 map_y)。数组 map_x 和 map_y 的大小必须与输入图像的大小相同,并且每个元素 (x, y) 表示源图像中的像素点 (x, y) 在目标图像中的新位置 (x’, y’)。

重映射应用场景?

重映射在图像处理和计算机视觉领域有许多应用场景。以下是一些常见的重映射应用场景:

图像畸变校正:相机镜头引起的畸变(如透视畸变、鱼眼畸变等)会导致图像中的直线弯曲或形状失真。通过重映射技术,可以校正这些畸变,使图像看起来更加自然和真实。

图像配准:在多幅图像中找到对应点,并将它们对齐,使得它们在相同视角或坐标系下表现一致。这在图像拼接、全景图像合成和多视角图像处理中非常有用。

图像稳定:在视频处理中,当相机存在抖动或运动时,可以使用重映射技术来稳定视频,保持图像内容相对稳定,减少抖动效应。

视角变换:通过重映射,可以改变图像的视角,实现缩放、旋转、平移和透视等效果,从而得到不同角度或大小的图像。

增强现实 (AR) 应用:在AR应用中,通过对现实世界图像进行重映射,将虚拟物体或信息叠加到真实世界中,实现真实与虚拟的交互效果。

图像处理与滤波:重映射技术可以应用于图像处理中的滤波、图像增强和特效处理,从而实现各种图像变换和处理效果。

视频流处理:在实时视频流处理中,可以使用重映射技术对图像进行实时变换和校正,以满足特定的需求。

这些只是重映射在图像处理和计算机视觉中的一些常见应用场景。实际上,重映射技术非常灵活和强大,可以在许多不同的领域中发挥重要作用,帮助我们处理和改善图像数据。

映射参数的理解

OpenCV 内的重映射函数 cv2.remap()提供了更方便、更自由的映射方式,其语法格式如下:

dst = cv2.remap( src, map1, map2, interpolation[, borderMode[, borderValue]] )

式中:
 dst 代表目标图像,它和 src 具有相同的大小和类型。
 src 代表原始图像。
 map1 参数有两种可能的值:
 表示(x,y)点的一个映射。
 表示 CV_16SC2 , CV_32FC1, CV_32FC2 类型(x,y)点的 x 值。
 map2 参数同样有两种可能的值:
 当 map1 表示(x,y)时,该值为空。
 当 map1 表示(x,y)点的 x 值时,该值是 CV_16UC1,
CV_32FC1 类型(x,y)点的 y 值。
 Interpolation 代表插值方式
 borderMode 代表边界模式。当该值为 BORDER_TRANSPARENT 时,表示目标图像内
的对应源图像内奇异点(outliers)的像素不会被修改。
 borderValue 代表边界值,该值默认为 0。

重映射通过修改像素点的位置得到一幅新图像。在构建新图像时,需要确定新图像中每个像素点在原始图像中的位置。因此,映射函数的作用是查找新图像像素在原始图像内的位置。该过程是将新图像像素映射到原始图像的过程,因此被称为反向映射。在函数 cv2.remap()中,参数 map1 和参数 map2 用来说明反向映射,map1 针对的是坐标 x,map2 针对的是坐标 y。

需要说明的是,map1 和 map2 的值都是浮点数。因此,目标图像可以映射回一个非整数的值,这意味着目标图像可以“反向映射”到原始图像中两个像素点之间的位置(当然,该位置是不存在像素值的)。这时,可以采用不同的方法实现插值,函数中的 interpolation 参数可以控制插值方式。正是由于参数 map1 和参数 map2 的值是浮点数,所以通过函数 cv2.remamp()所能实现的映射关系变得更加随意,可以通过自定义映射参数实现不同形式的映射。

需要注意的是,函数 cv2.remap()中参数 map1 指代的是像素点所在位置的列号,
参数 map2 指代的是像素点所在位置的行号。例如,我们想将目标图像(映射结果图像)中某个点 A 映射
为原始图像内处于第 0 行第 3 列上的像素点 B,那么需要将 A 点所对应的参数 map1 对应位置上的值设为 3,参数 map2 对应位置上的值设为 0。

所以,通常情况下,我们将 map1 写为 mapx,并且将 map2 写成 mapy,以方便理解。

同样,如果想将目标图像(映射结果图像)中所有像素点都映射为原始图像内处于第 0 行
第 3 列上的像素点 B,那么需要将参数 map1 内的值均设为 3,将参数 map2 内的值均设为 0。

实验:

使用 cv2.remap()完成数组映射,将目标数组内的所有像素点都映射为原始图像内第 0 行第 3 列上的像素点,以此来了解函数 cv2.remap()内参数 map1 和 map2 的使
用情况。
根据题目要求,可以确定:

 用来指定列的参数 map1(mapx)内的值均为 3。
 用来指定行的参数 map2(mapy)内的值均为 0。

import cv2
import numpy as np
img=np.random.randint(0,256,size=[4,5],dtype=np.uint8)
rows,cols=img.shape
mapx = np.ones(img.shape,np.float32)*3
mapy = np.ones(img.shape,np.float32)*0
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
print("img=\n",img)
print("mapx=\n",mapx)
print("mapy=\n",mapy)
print("rst=\n",rst)

运行结果:

img=
 [[253  90  32  65 181]
 [187 184 148  12 212]
 [157 229 255 138 115]
 [156  38  62  89 241]]
mapx=
 [[3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]]
mapy=
 [[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
rst=
 [[65 65 65 65 65]
 [65 65 65 65 65]
 [65 65 65 65 65]
 [65 65 65 65 65]]

通过观察上述结果可知,目标图像(数组)dst 内的所有值都来源于原始图像中第 0 行第 3
列上的像素值 65。

复制

为了更好地了解重映射函数 cv2.remap()的使用方法,本节介绍如何通过该函数实现图像的复制。在映射时,将参数进行如下处理:

 将 map1 的值设定为对应位置上的 x 轴坐标值。
 将 map2 的值设定为对应位置上的 y 轴坐标值。

通过上述处理后,可以让函数 cv2.remap()实现图像复制。下面通过一个例题来观察实现复
制时,如何设置函数 cv2.remap()内的 map1 和 map2 参数的值。

使用函数 cv2.remap()完成数组复制,了解函数 cv2.remap()内参数 map1和 map2 的使用情况。

这里为了方便理解,将参数 map1 定义为 mapx,将参数 map2 定义为 mapy。后续程序中都采用了这种定义方式,后面不再重复说明。

import cv2
import numpy as np
img=np.random.randint(0,256,size=[4,5],dtype=np.uint8)
rows,cols=img.shape
mapx = np.zeros(img.shape,np.float32)
mapy = np.zeros(img.shape,np.float32)
for i in range(rows):
 for j in range(cols):
 	mapx.itemset((i,j),j)
	mapy.itemset((i,j),i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
print("img=\n",img)
print("mapx=\n",mapx)
print("mapy=\n",mapy)
print("rst=\n",rst)

运行程序,出现如下结果:

img=
 [[151 137  24  88 216]
 [  8 112 205 130  44]
 [ 78 106   1 134  85]
 [190  55 135  56  64]]
mapx=
 [[0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]
 [0. 1. 2. 3. 4.]]
mapy=
 [[0. 0. 0. 0. 0.]
 [1. 1. 1. 1. 1.]
 [2. 2. 2. 2. 2.]
 [3. 3. 3. 3. 3.]]
rst=
 [[151 137  24  88 216]
 [  8 112 205 130  44]
 [ 78 106   1 134  85]
 [190  55 135  56  64]]

通过本例可以观察到,参数 mapx 和参数 mapy 分别设置了 x 轴方向的坐标和 y 轴方向的
坐标。函数 cv2.remap()利用参数 mapx、mapy 所组成的数组构造的映射关系实现了图像的复制。
例如,rst 中的像素点[3,4]在 src 内的 x、y 轴坐标如下:
 x 轴坐标取决于 mapx 中 mapx[3,4]的值,为 4。
 y 轴坐标取决于 mapy 中 mapy[3,4]的值,为 3。

这说明 rst[3,4]来源于原始图像 src 的第 4 列(x 轴方向,由 mapx[3,4]决定)、第 3 行(y
轴方向,由 mapy[3,4]决定),即 rst[3,4]=src[3,4]。原始对象 src[3,4]的值为 64,所以目标对象
rst[3,4]的值为 64。

像绕 x 轴的翻转

import cv2
import numpy as np
img=cv2.imread("lena.png")
rows,cols=img.shape[:2]
mapx = np.zeros(img.shape[:2],np.float32)
mapy = np.zeros(img.shape[:2],np.float32)
for i in range(rows):
 for j in range(cols):
    mapx.itemset((i,j),j)
    mapy.itemset((i,j),rows-1-i)
rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
cv2.imshow("original",img)
cv2.imshow("result",rst)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
,左图是原始图像,右图是翻转结果图像

还有绕Y 翻转,绕X,Y 轴翻转,更多操作多动作试试

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

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

相关文章

vue项目中对组件使用v-model绑定值,在vue3中如何更新数据

在el-form 中 el-form-item 绑定组件进行校验 想在表单下面爆红提示 可以对组件使用v-model绑定值 vue2 通过this.$emit(‘input’,value) 更新 v-model值 vue3 通过this.$emit(‘update:modelValue’ ,value) 更新 v-model值

管理类联考——写作——素材篇——论说文——人工智能

有人说,机器人的使命应该是帮助人类做那些人类做不了的事情,而不是替代人类。技术变革会夺取一些人低端繁琐的工作岗位,最终也会创造更高端更人性化的工作机会。例如,铁路的出现抢去了很多挑夫的工作,但也增加了千百万…

资源成本降低70%!华为MetaERP资产核算的Serverless架构实践

资产核算是指在一定的财务周期,对企业拥有的房屋建筑物、机器设备、商标权和专利权等资产的取得、折旧和处置的会计核算,反映企业固定资产、无形资产的增减变动和价值分摊活动。华为资产核算产品,支撑企业资产从获取到处置全生命周期的管理和…

synchronized关键字同步原理

1.同步方法 public class Test {synchronized public static void testMethod(){}public static void main(String[] args) {testMethod();} }// 实现class文件的反汇编 java -c -v *.class从字节码文件中可以看到同步方法根据flags标志中的ACC_SYNCHRONIZED来判别是否是同步方…

动态内存管理面试题

动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下&#xff08;示例&#xff09;&#xff1a; #include<stdio.h> #include<string.h> #incl…

快速学习Protobuf

目录 1. 什么是Protobuf&#xff1f; 2. 安装与设置 3. 定义消息 4. 编写.proto文件 5. 编译.proto文件 6. 序列化与反序列化 7. 使用Proto文件 8. Protobuf高级特性 1. 什么是Protobuf&#xff1f; 简介&#xff1a;Protobuf&#xff08;Protocol Buffers&#xff09;…

opencv python 训练自己的分类器

源码下载 一、分类器制作 1.样本准备 收集好你所需的正样本&#xff0c;和负样本&#xff0c;分别保存在不同文件夹 在pycharm新建项目&#xff0c;项目结构如下&#xff1a;has_mask文件夹放置正样本&#xff0c;no_mask文件夹放置负样本 安装opencv&#xff0c;把opencv包…

MySQL数据库面试题总结(2022最新版)

&#x1f436; 程序猿周周 ⌨️ 短视频小厂BUG攻城狮 &#x1f93a; 如果文章对你有帮助&#xff0c;记得关注、点赞、收藏&#xff0c;一键三连哦&#xff0c;你的支持将成为我最大的动力 本文是《后端面试小册子》系列的第 1️⃣ 篇文章&#xff0c;该系列将整理和梳理笔者作…

即时通讯im软件有哪些适合企业内部使用?

随着互联网的普及&#xff0c;即时通讯&#xff08;IM&#xff09;软件发挥着越来越重要的作用。它们为企业内部提供了高效的沟通方式&#xff0c;促进了团队沟通和工作效率的提升。以下是一些适合企业内部使用的即时通讯IM软件。 飞书 飞书是一款由字节跳动公司推出的企业级即…

python版本管理

安装anaconda3 conda conda search “^python$” conda创建新的 Python 环境&#xff0c;并指定你想要的 Python 版本&#xff1a; conda create -n myenv python<desired_python_version> 例如&#xff1a; conda create -n myenv python3.8.8 conda activate myen…

JS加载资源失败的解决办法

JS加载资源失败的解决办法 原文地址 JS加载失败导致问题 JS 也有可能加载失败&#xff0c;导致页面样式错乱&#xff0c;甚至白屏无法使用。这对用户体验是非常不利的&#xff0c;尤其是对于单页应用&#xff0c;如果 JS 加载不出来&#xff0c;用户就无法继续浏览页面了。 …

云计算迎来中场战役,MaaS或将成为弯道超车“新赛点”

科技云报道原创。 没有人能预见未来&#xff0c;但我们可以因循常识&#xff0c;去捕捉技术创新演进的节奏韵脚。 2023年最火的风口莫过于大模型。 2022年底&#xff0c;由美国初创企业OpenAI开发的聊天应用ChatGPT引爆市场&#xff0c;生成式AI成为科技市场热点&#xff0c…

(十六十七)时序数据库是怎么存储用户名和密码的从InfluxDB OSS迁移数据

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 16 章 时序数据库是怎么存储用户名和密码的 1、InfluxDB内部自带了一个用Go语言写的BlotDB&#xff0c;Blo…

大数据处理架构详解:Lambda架构、Kappa架构、流批一体、Dataflow模型、实时数仓

前言 本文隶属于专栏《大数据理论体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据理论体系 姊妹篇 《分布式数据模型详解&#xff1a;OldSQL &…

LDR6028DRP五V充电芯片OTG传数据充电高端方案

随着科学的进步&#xff0c;生产力的进步&#xff0c;时代的进步&#xff0c;电子产品的更新迭代&#xff0c;手机上面的接口越来越来少&#xff0c;甚至到后面手机没有任何接口。现在的手机只剩Type-c&#xff0c;那手机又要充电又要进行数据传输&#xff0c;那怎么办呢。那么…

Vue 常用指令 v-for 列表循环

v-for&#xff1a;根据数据生成列表结构&#xff0c;并且是响应式的&#xff0c;可以十分便捷的操作列表结构了。 至于是什么样的列表&#xff0c;就看你指令使用的位置了&#xff0c;列表的生成依赖于数据&#xff0c;所以先去定义数据。 它结合的类型挺多的&#xff0c;数组…

js实现框选截屏功能

实现的思路大概就是&#xff0c;先将dom转化为canvas画布&#xff0c;再对canvas进行裁切&#xff0c;然后通过canvas api生成图片&#xff0c;这里用到了一个库html2canvas 效果如图&#xff1a; 首先实现框选效果&#xff1a; const mousedownEvent (e) > {moveX 0;mo…

Java真的没出路了吗?

前言 并不是没有出路&#xff0c;Java当下确实是比较的内卷&#xff0c;但关键在于个人&#xff0c;可以看看不同地方&#xff08;这里主要举例北上广深一线城市&#xff09;对于Java开发工程师这个职位的具体要求&#xff1a; 在以下北上广深这些一线大城市的面试招聘当中不…

CAPL中有符号和无符号数据类型的若干问题

我们知道CAPL中的整数类型分为:无符号(unsigned)和有符号(signed)。 无符号类型有: byte (unsigned, 1 Byte)word (unsigned, 2 Byte)dword (unsigned, 4 Byte)qword(unsigned, 8 Byte)有符号类型有: int (signed, 2 Byte)long (signed, 4 Byte)int64(signed, 8 Byte)什…

Sharding-JDBC数据加密详解与实战

&#x1f680; ShardingSphere &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&…