OpenCV 实现重新映射(53)

返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV 实现霍夫圆变换(52)
下一篇 :OpenCV实现仿射变换(54)

目标

在本教程中,您将学习如何:

一个。使用 OpenCV 函数 cv::remap 实现简单的重新映射例程。

理论

什么是重映射?

  • 它是从图像中的一个位置获取像素并将它们定位在新图像中的另一个位置的过程。
  • 为了完成映射过程,可能需要对非整数像素位置进行一些插值,因为源图像和目标图像之间并不总是存在一对一的像素对应关系。
  • 我们可以表示每个像素位置的重新映射(x,y)如:

      

    哪里g()是重新映射的图像,f()源图像和ℎ(x,y)是操作的映射函数(x,y).

  • 让我们举个简单的例子。想象一下,我们有一个图像我而且,比如说,我们想做一个重新映射,以便:

      

    会发生什么?很容易看出,图像会在x方向。例如,考虑输入图像:

观察红色圆圈相对于 x 如何改变位置(考虑到x水平方向):

  • 在 OpenCV 中,函数 cv::remap 提供了一个简单的重新映射实现。

C++代码
 

  • 这个程序是做什么的?
    • 加载图像
    • 每秒将 4 个不同的重新映射过程中的 1 个应用于图像,并在窗口中无限期地显示它们。
    • 等待用户退出程序
    • 教程代码如下所示。您也可以从这里下载
     
     
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/highgui.hpp"
    #include "opencv2/imgproc.hpp"
    #include <iostream>using namespace cv;void update_map( int &ind, Mat &map_x, Mat &map_y );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);Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );if (src.empty()){std::cout << "Cannot read image: " << filename << std::endl;return -1;}Mat dst(src.size(), src.type());Mat map_x(src.size(), CV_32FC1);Mat map_y(src.size(), CV_32FC1);const char* remap_window = "Remap demo";namedWindow( remap_window, WINDOW_AUTOSIZE );int ind = 0;for(;;){update_map(ind, map_x, map_y);remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );imshow( remap_window, dst );char c = (char)waitKey( 1000 );if( c == 27 ){break;}}return 0;
    }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;
    }

解释

  • 加载图像

     Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );if (src.empty()){std::cout << "Cannot read image: " << filename << std::endl;return -1;}

  • 创建目标映像和两个映射矩阵(对于 x 和 y )

    Mat dst(src.size(), src.type());Mat map_x(src.size(), CV_32FC1);Mat map_y(src.size(), CV_32FC1);

  • 创建一个窗口以显示结果

     const char* remap_window = "Remap demo";namedWindow( remap_window, WINDOW_AUTOSIZE );

  • 建立循环。每隔 1000 毫秒,我们就会更新映射矩阵(mat_x 和 mat_y),并将它们应用于我们的源图像:

     int ind = 0;for(;;){update_map(ind, map_x, map_y);remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );imshow( remap_window, dst );char c = (char)waitKey( 1000 );if( c == 27 ){break;}}

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;
}

结果

  1. 编译上面的代码后,您可以执行它,并给出一个图像路径作为参数。例如,使用下图:

  1. 这是将其减小到一半大小并居中的结果:

  1. 把它颠倒过来:

  1. 在 x 方向上反映它

  1. 在两个方向上反映它:


参考文献:

1、《Remapping》------Ana Huamán

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

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

相关文章

React和antd如何封装权限按钮

在React和Ant Design(antd)中封装一个权限按钮涉及到两个主要步骤: 权限判断:首先,你需要有一个权限管理系统来存储和检查用户的权限。这通常是通过API从服务器获取用户权限,然后将其保存在应用的状态中。 封装按钮组件:基于用户的权限,你可以封装一个React组件,这个…

STM32——点亮第一个LED灯

代码示例&#xff1a; #include "stm32f10x.h" // Device headerint main() {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启时钟GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitSt…

c# winform快速建websocket服务器源码 wpf快速搭建websocket服务 c#简单建立websocket服务 websocket快速搭建

完整源码下载----->点击 随着互联网技术的飞速发展&#xff0c;实时交互和数据推送已成为众多应用的核心需求。传统的HTTP协议&#xff0c;基于请求-响应模型&#xff0c;无法满足现代Web应用对低延迟、双向通信的高标准要求。在此背景下&#xff0c;WebSocket协议应运而生…

【51单片机普中板子74LS138+245+573可调时钟整点蜂鸣中级应用】2022-12-7

缘由用51单片机普中开发板实现数字时钟-嵌入式-CSDN问答 #include "reg52.h" //定义按键 sbit key0P3^0; sbit key1P3^1; sbit key2P3^2; sbit key3P3^3; //定义数码管位驱运位 sbit L1P2^2; sbit L2P2^3; sbit L3P2^4; sbit beepP2^5; unsigned char code ShuMaGua…

用Springboot(java程序)访问Salesforce RestAPI之二(Update和Create)

在上一篇博文中&#xff0c;介绍了Springboot连接Salesforce的步骤和环境构建。 其中&#xff0c;只给出了对Salesforce数据进行查询的例子&#xff0c;这篇文章针对Salsforce数据的Update和Create&#xff0c;再展开一下。 对于Create和Update的操作&#xff0c;请求的方式和…

一周零碎时间练习微服务(nacos,rq,springcloud,es等)内容

目录 1 总览1.1 技术架构1.2 其他1.2.1 数据库1.2.2 后端部分1.2.2.1 复习feign1.2.2.2 复习下网关网关的核心功能特性&#xff1a;网关路由的流程断言工厂过滤器工厂全局过滤器 过滤器执行顺序解决跨域问题 1.2.2.3 es部分复习 1.2.3 前端部分 2 day1 配置网关2.1 任务2.2 网关…

ThreeJS:项目搭建

介绍如何基于Vite、Vue、React构建ThreeJS项目。 Vite项目 1. 初始化项目&#xff0c;命令&#xff1a;npm init vitelatest&#xff0c; 2. 安装依赖&#xff0c;命令&#xff1a;npm install&#xff0c; 3. 启动项目&#xff0c;命令&#xff1a;npm run dev。 4. 样式初始…

【LeetCode刷题记录】简单篇-94-二叉树的中序遍历

【题目描述】 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 【测试用例】 示例1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例2&#xff1a; 输入&#xff1a;root [ ] 输出&#xff1a;[ ] 示例3&#xff1a; 输入…

Rust 动态数组Vector

导航 一、动态数组是什么&#xff0c;怎么用1、动态数组Vector是什么2、动态数组怎么用&#xff08;1&#xff09;创建动态数组&#xff08;2&#xff09;尾部追加元素&#xff08;3&#xff09;尾部删除元素&#xff08;4&#xff09;删除指定位置元素&#xff08;5&#xff0…

ThreeJS:本地部署官网文档与案例

部署方式 部署之前请确保已经配置好node.js环境。 1. 下载ThreeJS源码 ThreeJS的GitHub地址&#xff1a;GitHub - mrdoob/three.js: JavaScript 3D Library.&#xff0c;可以简单查看ThreeJS当前版本&#xff1a;r164&#xff0c; 我们可以选择对应的版本&#xff08;此处为r1…

win11 Terminal 部分窗口美化

需求及分析&#xff1a;因为在 cmd、anaconda prompt 窗口中输入命令较多&#xff0c;而命令输入行和输出结果都是同一个颜色&#xff0c;不易阅读&#xff0c;故将需求定性为「美化窗口」。 美化结束后&#xff0c;我在想是否能不安装任何软件&#xff0c;简单地通过调整主题颜…

boost::asio::ip::tcp::socket set_option

Boost asio 官方教程简介_asio::write-CSDN博客 boost::asio::ip::tcp::socket 是一个用于异步I/O操作的类&#xff0c;它是Boost.Asio库的一部分&#xff0c;专门用于处理TCP套接字。 以下是一个简单的使用 boost::asio::ip::tcp::socket 的例子&#xff0c;这个例子展示了如…

备考2024年上海初中生古诗文大会:单选题真题示例和独家解析

现在距离2024年初中生古诗文大会还有四个多月时间&#xff0c;备考要趁早&#xff0c;因为知识点还是相对比较多的。这些知识点对于初中语文的学习也是很有帮助的。 我们继续来看10道历年真题&#xff0c;这些真题来自于过去历年真题的去重、汇总&#xff0c;每道题都有参考答…

2-手工sql注入(进阶篇) sqlilabs靶场1-4题

1. 阅读&#xff0c;学习本章前&#xff0c;可以先去看看基础篇&#xff1a;1-手工sql注入(基础篇)-CSDN博客 2. 本章通过对sqlilabs靶场的实战&#xff0c;关于sqlilabs靶场的搭建&#xff1a;Linux搭建靶场-CSDN博客 3. 本章会使用到sqlmap&#xff0c;关于sqlmap的命令&…

机器翻译常用指标BLEU

诸神缄默不语-个人CSDN博文目录 文章目录 什么是BLEU指标&#xff1f;BLEU指标的原理BLEU的计算公式BLEU指标的Python实现 什么是BLEU指标&#xff1f; BLEU&#xff08;Bilingual Evaluation Understudy&#xff09;指标是一种评估机器翻译质量的方法&#xff0c;广泛用于自然…

salesforce vscode 获取profile metadata所有配置内容

1.更新cli&#xff1a;sfdx update 2.安装read插件&#xff1a;sfdx plugins:install sfdx-plugin-source-read 3.通过vscode☁️&#xff08;org browser&#xff09;或者package.xml拉取profile&#xff0c;此时获取的简档没有所有配置内容 <?xml version"1.0&qu…

PostgreSQL自带的命令行工具02- createdb

PostgreSQL自带的命令行工具02- createdb 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;5777createdb 是 Postgr…

2024五一数学建模C题煤矿深部开采冲击地压危险预测原创论文分享

大家好&#xff0c;从昨天肝到现在&#xff0c;终于完成了2024五一数学建模竞赛C题的完整论文啦。 实在精力有限&#xff0c;具体的讲解大家可以去讲解视频&#xff1a; 2024五一数学建模C题完整原创论文讲解&#xff0c;手把手保姆级教学&#xff01;_哔哩哔哩_bilibili 202…

003 redis分布式锁 jedis分布式锁 Redisson分布式锁 分段锁

文章目录 Redis分布式锁原理1.使用set的命令时&#xff0c;同时设置过期时间2.使用lua脚本&#xff0c;将加锁的命令放在lua脚本中原子性的执行 Jedis分布式锁实现pom.xmlRedisCommandLock.javaRedisCommandLockTest.java 锁过期问题1乐观锁方式&#xff0c;增加版本号(增加版本…

自动控制工程技术人员的工作内容有哪些

自动控制工程技术人员主要负责开发和维护自动化系统和控制仪器&#xff0c;他们的工作内容涵盖了从系统设计、实施到测试和优化各个方面。以LabVIEW&#xff08;一种广泛使用的图形编程语言&#xff0c;用于数据采集、仪器控制和工业自动化&#xff09;为例&#xff0c;自动控制…