OpenCV图像处理——重映射 remap函数

article/2025/8/27 9:59:14

在《学习OpenCV3,O'Reilly系列丛书》中的第11章常见的图像变换中讲到的“任意映射”,Remap函数。函数cv::remap通常用来纠正校准的立体图像,包括图像变形和图像扭曲。其实这个函数在无人机拍摄延时摄影(使用电子防抖算法)合成视频时也是常用到的函数。主要是处理无人机悬停或者行进中拍摄的照片出现比较大的形变。

remap( )函数解析

remap( )函数会根据我们指定的映射形式,将源图像进行重映射几何变换,基于的式子如下:

 

需要注意,此函数不支持就地(in-place)操作。看看其原型和参数。

void cv::remap(InputArraysrc,
OutputArraydst,
InputArraymap1,
InputArraymap2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar() 
)

 Parameters

srcSource image.
dstDestination image. It has the same size as map1 and the same type as src .
map1The first map of either (x,y) points or just x values having the type CV_16SC2 , CV_32FC1, or CV_32FC2. See convertMaps for details on converting a floating point representation to fixed-point for speed.
map2The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map if map1 is (x,y) points), respectively.
interpolation

插值方式,

Interpolation method (see InterpolationFlags). The method INTER_AREA is not supported by this function.

borderMode

图像边界处理方式

Pixel extrapolation method (see BorderTypes). When borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image that corresponds to the "outliers" in the source image are not modified by the function.

borderValueValue used in case of a constant border. By default, it is 0.

使用OpenCV-3.4中的samples/cpp/tutorial_code/ImgTrans/Remap_Demo.cpp进行演示。

update_map函数中的参数ind意义:

ind=0表示提取源图像的25%~75%显示,1%~24%和76%~100%填充。

 

ind=1表示关于沿着x轴翻转(上下翻转)

ind=2表示关于沿着Y轴翻转(左右翻转)

 

ind=3表是上下和左右同时翻转。

/*** @function Remap_Demo.cpp* @brief Demo code for Remap* @author Ana Huaman*/#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>using namespace cv;/// Function Headers
void update_map( int &ind, Mat &map_x, Mat &map_y );/*** @function main*/
int main(int argc, const char** argv)
{CommandLineParser parser(argc, argv, "{@image |chicky_512.png|input image name}");std::string filename = parser.get<std::string>(0);//! [Load]/// Load the imageMat src = imread( samples::findFile( filename ), IMREAD_COLOR );if (src.empty()){std::cout << "Cannot read image: " << filename << std::endl;return -1;}//! [Load]//! [Create]/// Create dst, map_x and map_y with the same size as src:Mat dst(src.size(), src.type());Mat map_x(src.size(), CV_32FC1);Mat map_y(src.size(), CV_32FC1);//! [Create]//! [Window]/// Create windowconst char* remap_window = "Remap demo";namedWindow( remap_window, WINDOW_AUTOSIZE );//! [Window]//! [Loop]/// Index to switch between the remap modesint ind = 0;for(;;){/// Update map_x & map_y. Then apply remapupdate_map(ind, map_x, map_y);remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );/// Display resultsimshow( remap_window, dst );/// Each 1 sec. Press ESC to exit the programchar c = (char)waitKey( 1000 );if( c == 27 ){break;}}//! [Loop]return 0;
}/*** @function update_map* @brief Fill the map_x and map_y matrices with 4 types of mappings*/
//! [Update]void update_map( int &ind, Mat &map_x, Mat &map_y )
{for( int i = 0; i < map_x.rows; i++ ){for( int j = 0; j < map_x.cols; j++ ){switch( ind ){case 0:if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 ){map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;}else{map_x.at<float>(i, j) = 0;map_y.at<float>(i, j) = 0;}break;case 1://行翻转map_x.at<float>(i, j) = (float)j;map_y.at<float>(i, j) = (float)(map_x.rows - i);break;case 2: //列翻转map_x.at<float>(i, j) = (float)(map_x.cols - j);map_y.at<float>(i, j) = (float)i;break;case 3: //上下左右均翻转map_x.at<float>(i, j) = (float)(map_x.cols - j);map_y.at<float>(i, j) = (float)(map_x.rows - i);break;default:break;} // end of switch}}ind = (ind+1) % 4;
}


http://chatgpt.dhexx.cn/article/4kOZK0jY.shtml

相关文章

重映射:remap()函数

remap()函数会根据指定的映射形式&#xff0c;将原图像进行重映射几何变换&#xff0c;基于公式如下&#xff1a; dst(x, y) src( mapx(x, y), mapy(x, y) )函数原型C&#xff08;程序 / 20&#xff09;: void remap( InputArray src, OutputArray dst, InputArray map1, In…

OpenCV:remap()简单重映射

学习自&#xff1a;【OpenCV入门教程之十七】OpenCV重映射 重映射&#xff0c;就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。为了完成映射过程, 我们需要获得一些插值为非整数像素的坐标,因为源图像与目标图像的像素坐标不是一一对应的。一般情况下&#xff…

JS获取对象键值对中key值的方法

使用Object.keys Object.keys( ) 会返回一个数组&#xff0c;数组中是这个对象的key值列表 所以只要Object.keys(a)[0]&#xff0c; 就可以得只包含一个键值对的key值 下面是MDN中对Object.keys的描述 Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组&…

C# 键值对

1.初始化一个键值对 1 //初始化定义一个键值对&#xff0c;注意最后的括号 2 Dictionary<int, string> dic new Dictionary<int, string>(); 2.为键值对添加元素 1 //键值对的Add函数 2 dic.Add(2, "zhao"); 3 dic.Add(4, "qian"); 4 dic…

js中往数组对象中添加键值对的方法有哪些?

❤️❤️❤️Topology-le5le智慧光伏能源可视化方案❤️❤️❤️ &#x1f31f;&#x1f31f;&#x1f31f;Topology可视化绘图引擎&#x1f31f;&#x1f31f;&#x1f31f; 1.Object.assign() 用法&#xff1a;Object.assign(源对象, {要添加的键值对}) 2.拓展运算符&…

键值对操作

键值对 RDD 通常用来进行聚合计算。我们一般要先通过一些初始 ETL(抽取、转化、装载)操作来将数据转化为键值对形式。键值对 RDD 提供了一些新的操作接口(比如统计每个产品的评论,将数据中键相同的分为一组,将两个不同的 RDD 进行分组合并等)。 1. 动机 Spark 为包含键值对类…

java键值对的使用

Map集合没有继承Collection接口&#xff0c;但是其提供了key到value的映射。每一个key不能有相同&#xff0c;每个key只能映射一个value值。 Map接口常用方法&#xff1a; 方法功能描述put(K key, V value)向集合中添加指定的key与value的映射关系containsKey(Object key)如果…

C++ map容器(键值对)

文章目录 1&#xff0c;map简介2&#xff0c;map的功能3&#xff0c;使用map4&#xff0c;map的构造函数5&#xff0c;插入元素6&#xff0c; 查找元素7&#xff0c; 刪除与清空元素8&#xff0c;map的大小9&#xff0c;map的基本操作函数&#xff1a; 使用示例示例1 20221027 …

java 键值对详解及java键值对代码

在 Java中&#xff0c;对象可以理解为一个列表。这个列表里面的每个元素都是一个“键”&#xff0c;而每个“键”都是一个值。 键值对的概念&#xff0c;并不是在 Java中第一次出现&#xff0c;在 java 1.x中就已经有了。那时候它的意思是在一个命名空间中建立两个名字相同的对…

node(map对象/键值对,作用域,函数作用域,全局作用域)

map键值对 什么是键值对? 键值对(key value) 顾名思义,每一个键会对应一个值。 比如&#xff1a; 身份证号和你本人是绑定的关系。每一个身份证号(键)都会对应一个小可爱(值)。 我们在登录微信或者游戏时,需要输入手机号验证身份。系统会向该手机号发送一条验证短信。 这里的…

键值对是什么?

一、键值对问题&#xff1a; 键值对&#xff08;“key value”&#xff09;&#xff0c;顾名思义&#xff0c;每一个键会对应一个值。 二、举个例子 身份证号和你本人的绑定关系&#xff0c;在系统中输入身份证号(键)都会对应一个小可爱(值)。咱在登陆微信、游戏或外卖账号…

键值对

感谢传智播客C语言视频教程对作者的帮助。 一、键值对问题 1、什么是键值对 举个简单的例子&#xff0c;电话簿中&#xff0c;键&#xff1a;小马、值&#xff1a;18753137777。是一种简单的对应关系。 2、代码举例 键值对&#xff08;“key value”&#xff09;字符串&a…

MBR、EBR、OBR的区别和联系

先看图&#xff1a; 一块硬盘&#xff0c;最开始只能实现4个分区&#xff0c;也就是4个主分区。 后来的发展&#xff0c;4个分区不够用了&#xff0c;可以有一个分区作为扩展分区&#xff0c;用它来作为总扩展分区&#xff0c;里面可以分成很多个子扩展分区&#xff0c;每个子…

MBR分区结构、DPT分区表、EBR扩展引导

本文链接&#xff1a;http://www.blogfshare.com/mbr-dpt-ebr.html 主引导记录&#xff08;Master Boot Record&#xff0c;缩写&#xff1a;MBR&#xff09;&#xff0c;又叫做主引导扇区&#xff0c;是计算机开机后访问硬盘时所必须要读取的首个扇区&#xff0c;它在硬盘上的…

C语言读取磁盘分区信息(MBR、DPT、EBR)

文章目录 简介使用的函数1.CreateFile()函数打开设备2.DeviceIoControl()函数返回磁盘设备信息3.SetFilePointer()函数设置读取磁盘信息位置4.ReadFile()函数读取磁盘内容 源代码结果分析MBR部分&#xff1a;第一个EBR的DPT内容为&#xff1a;第2个EBR内容 总结 简介 在win8以后…

使用Epoch-Based Reclamation(EBR,特定域回收的一种方法)修改 lazy-list

如前文所说&#xff0c;lazy-list最大的隐患莫过于逻辑删除&#xff0c;而没有物理删除问题&#xff0c;因此EBR首先就把这个问题给他solve了。 一.EBR修改部分 int parse_delete(intset_l_t *set, val_t val) {node_l_t *pred, *curr;int result, validated, isVal;while(1)…

淘宝电商搜索EBR算法笔记

淘宝电商搜索EBR算法笔记 - 知乎《Embedding-based Product Retrieval in Taobao Search》介绍了淘宝目前最新的EBR算法。仍然是一个双塔的结构&#xff0c;query/user一个塔&#xff0c;item一个塔&#xff0c;各自得到向量表示&#xff0c;然后计算内积。 网络结构如上图所示…

解决西门子ebr设备模块更新报错,EQP_STATEVALUE more than one row

问题排查报告 原文来至 问题跟踪 首先定位到EQP_STATEVALUE表&#xff0c;发现数据出现重复&#xff1a; 执行语句取出所有非重复数据&#xff1a; select t.stateid,t.fk_statelistcst,t.code,t.label,t.functionid,t.pk_id,t.dlu,t.dluunit,t.cpt,t.haseqpimpact from EQP…

机械臂关节模组制动相关(零差云控eBr)

目录 前言一、电磁插销式抱闸1.原理2.特点 二、电磁摩擦片式制动器1.原理2.特点 三、零差云控电磁摩擦片式制动器&#xff08;eBreaker&#xff09;1.简介2.使用说明需要注意的事情3.接线 总结参考文献 前言 现阶段机械臂的制动方法主要有两种&#xff0c;一种是电磁插销式抱闸…

西门子EBR与BATCH通讯方法,mes与batch交互

最新更新请访问&#xff1a;mesebr.com 链接 1 前期准备 1.1 网络检查 两台服务器防火墙全部关闭&#xff1b;两台服务器之间可以相互ping同&#xff0c;若batch服务器连接oracle数据库的连接名称写的机器名&#xff0c;则batch服务器ping机器名也要可以ping通&#xff1b; 1…