[OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码
文章目录
- 前言
- 1.像素重映射理论基础
- 2.代码实现
- (1) remap()细节
- (2)水平翻转
- (2)垂直翻转
- (3)旋转 180 度
- (4)径向扭曲
- 3.完整代码
前言
像素重映射将图像中的每个像素映射到新位置,实现图像的扭曲、校正等操作。在 OpenCV 中,cv::remap()
函数就是用于实现这种功能的。本文将详细介绍像素重映射的基本原理以及在 OpenCV 中的实现方法,并给出完整代码。
1.像素重映射理论基础
像素重映射的原理是将图像的每个像素通过预定义的映射规则重新分配到新的位置。映射规则可以是任意的数学函数,比如旋转、缩放、扭曲等,甚至可以通过查表的方式进行非线性的映射。
像素重映射可以用以下公式表示:
dst ( x ′ , y ′ ) = src ( x , y ) \text{dst}(x', y') = \text{src}(x, y) dst(x′,y′)=src(x,y)
其中 (x, y)
是源图像中的像素位置,(x', y')
是目标图像中的像素位置。通过映射函数,可以将源图像的像素映射到目标图像的相应位置。
常见的重映射应用
图像扭曲:将图像以某种方式进行扭曲处理,使其变形。
镜头畸变校正:通过重映射可以校正图像中由于镜头引起的畸变,如鱼眼镜头畸变。
图像旋转与缩放:可以将图像按照指定的角度和比例进行旋转与缩放。
2.代码实现
实验用到图像,供学习使用sherlock.jpg
(1) remap()细节
cv::remap(
InputArray src,// 输入图像
OutputArray dst,// 输出图像
InputArray map1,// x 映射表 CV_32FC1/CV_32FC2
InputArray map2,// y 映射表
int interpolation,// 选择的插值方法,常见线性插值,可选择立方等
int borderMode,// 指定图像边界的处理方式,默认为 BORDER_CONSTANT。
const Scalar borderValue// 用于边界像素的值,默认是黑色。
)
(2)水平翻转
将 map1
中的列坐标从右向左映射,map2
保持原始的行坐标不变。
for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(src.cols - j - 1); // 水平翻转map2.at<float>(i, j) = static_cast<float>(i);}}Mat dst_hflip;remap(src, dst_hflip, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Horizontal Flip", WINDOW_AUTOSIZE);imshow("Horizontal Flip", dst_hflip);
结果:
(2)垂直翻转
将 map2
中的行坐标从下向上映射,而 map1
保持列坐标不变。
// 2. 垂直翻转for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(j);map2.at<float>(i, j) = static_cast<float>(src.rows - i - 1); // 垂直翻转}}Mat dst_vflip;remap(src, dst_vflip, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Vertical Flip", WINDOW_AUTOSIZE);imshow("Vertical Flip", dst_vflip);
结果:
(3)旋转 180 度
同时进行水平和垂直翻转
// 3. 旋转 180 度for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(src.cols - j - 1); // 水平翻转map2.at<float>(i, j) = static_cast<float>(src.rows - i - 1); // 垂直翻转}}Mat dst_rotate180;remap(src, dst_rotate180, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Rotate 180 degrees", WINDOW_AUTOSIZE);imshow("Rotate 180 degrees", dst_rotate180);
结果:
(4)径向扭曲
通过对极坐标中的半径进行二次变换,产生径向扭曲效果,图像向中心点扭曲,产生类似鱼眼镜头的效果。
// 4. 径向扭曲效果float cx = src.cols / 2.0;float cy = src.rows / 2.0;float radius = min(cx, cy);for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {float dx = j - cx;float dy = i - cy;float r = sqrt(dx * dx + dy * dy);float theta = atan2(dy, dx);float r_distorted = radius * (r / radius) * (r / radius); // 径向扭曲map1.at<float>(i, j) = cx + r_distorted * cos(theta);map2.at<float>(i, j) = cy + r_distorted * sin(theta);}}Mat dst_radial;remap(src, dst_radial, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Radial Distortion", WINDOW_AUTOSIZE);imshow("Radial Distortion", dst_radial);
结果:
3.完整代码
#include<opencv2/opencv.hpp>
#include<highgui.hpp>
#include<iostream>
#include<math.h>using namespace cv;
using namespace std;void remap_image()
{cv::Mat src;src = imread("sherlock.jpg");if (src.empty()) {printf("could not find the image...\n");return;}namedWindow("Source Image", WINDOW_AUTOSIZE);imshow("Source Image", src);//创建映射矩阵Mat map1(src.size(), CV_32FC1);Mat map2(src.size(), CV_32FC1);// 1. 水平翻转for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(src.cols - j - 1); // 水平翻转map2.at<float>(i, j) = static_cast<float>(i);}}Mat dst_hflip;remap(src, dst_hflip, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Horizontal Flip", WINDOW_AUTOSIZE);imshow("Horizontal Flip", dst_hflip);// 2. 垂直翻转for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(j);map2.at<float>(i, j) = static_cast<float>(src.rows - i - 1); // 垂直翻转}}Mat dst_vflip;remap(src, dst_vflip, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Vertical Flip", WINDOW_AUTOSIZE);imshow("Vertical Flip", dst_vflip);// 3. 旋转 180 度for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {map1.at<float>(i, j) = static_cast<float>(src.cols - j - 1); // 水平翻转map2.at<float>(i, j) = static_cast<float>(src.rows - i - 1); // 垂直翻转}}Mat dst_rotate180;remap(src, dst_rotate180, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Rotate 180 degrees", WINDOW_AUTOSIZE);imshow("Rotate 180 degrees", dst_rotate180);// 4. 径向扭曲效果float cx = src.cols / 2.0;float cy = src.rows / 2.0;float radius = min(cx, cy);for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {float dx = j - cx;float dy = i - cy;float r = sqrt(dx * dx + dy * dy);float theta = atan2(dy, dx);float r_distorted = radius * (r / radius) * (r / radius); // 径向扭曲map1.at<float>(i, j) = cx + r_distorted * cos(theta);map2.at<float>(i, j) = cy + r_distorted * sin(theta);}}Mat dst_radial;remap(src, dst_radial, map1, map2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));namedWindow("Radial Distortion", WINDOW_AUTOSIZE);imshow("Radial Distortion", dst_radial);waitKey(0);
}
int main()
{remap_image();return 0;
}
相关文章:

[OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码
文章目录 前言1.像素重映射理论基础2.代码实现(1) remap()细节(2)水平翻转(2)垂直翻转(3)旋转 180 度(4)径向扭曲 3.完整代码 前言 像素重映射将图像中的每个像素映射到新位置,实现图像的扭曲、校正等操作。在 OpenCV 中,cv::remap() 函数就是用于实现这…...
Oreace每日运维操作
一.Oreace每日运维操作 目录 一.Oreace每日运维操作 1.1、确认所有的INSTANCE状态正常 1.2、检查文件系统的使用(剩余空间) 1.3 lwh暗码,,、检查日志文件和trace文件记录 1.4 lwh、检查数据库当日备份…...

【XR】AR HUD
1. AR HUD(head up display)原理 目标: 产业链上的各大Tier1及PGU企业都在积极开发这一技术,许多厂家已推出LCOS样机,比如说水晶光电、华阳集团、瀚思通、疆程已在北京车展或去年的上海车展上展出了LCOS方案的AR-HUD样…...
C/C++内存管理——内存泄漏/内存碎片
一、什么是内存泄漏 内存泄漏指的是在程序运行过程中,已经分配给程序使用的内存没有得到及时和正确的释放,导致这部分内存无法被程序再次使用或者被操作系统回收。内存泄漏通常发生在动态分配的内存上,如果这部分内存没有被正确释放,随着时间的推移,越来越多的内存将被占…...

使用 GaLore 预训练LLaMA-7B
项目代码: https://github.com/jiaweizzhao/galorehttps://github.com/jiaweizzhao/galore 参考博客: https://zhuanlan.zhihu.com/p/686686751 创建环境 基础环境配置如下: 操作系统: CentOS 7CPUs: 单个节点具有 1TB 内存的 Intel CP…...
gitlab无法push(pre-receive hook declined)
如果是个人的项目,托管在官网,可以参考这位大佬的, GitLab新建项目后push reject提交失败的解决办法_push rejected-CSDN博客 如果是公司的项目,去项目成员里看自己的身份,如果只是developer,是无法push到…...

物品识别——基于python语言
目录 1.物品识别 2.模型介绍 3.文件框架 4.代码示例 4.1 camera.py 4.2 interaction.py 4.3 object_detection.py 4.4 main.py 4.5 运行结果 5.总结 1.物品识别 该项目使用Python,OpenCV进行图像捕捉,进行物品识别。我们将使用YOLO(…...

【PostgreSQL】安装及使用(Navicat/Arcgis),连接(C#)
简介 PostgreSQL 是一个功能强大的开源对象关系数据库系统 下载地址 PostgreSQL: Downloads 由于我电脑上安装的是arcgispro3.1所以需要下载对应的postgresql版本 PostgreSQL 12 对应的 PostGIS 版本主要是 3.5.0 或更高版本。 安装 一般设置为postgresql 安装扩展插件 此…...

第L6周:机器学习-随机森林(RF)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标: 1.什么是随机森林(RF) 随机森林(Random Forest, RF)是一种由 决策树 构成的 集成算法 &#…...

【电路笔记】-差分运算放大器
差分运算放大器 文章目录 差分运算放大器1、概述2、差分运算放大器表示2.1 差分模式2.2 减法器模式3、差分放大器示例3.1 相关电阻3.2 惠斯通桥3.3 光/温度检测4、仪表放大器5、总结1、概述 在之前的文章中,我们讨论了反相运算放大器和同相运算放大器,我们考虑了在运算放大器…...
git 命令---想要更改远程仓库
在 Git 中,origin 是默认的远程仓库名称。可以使用以下命令查看当前 Git 仓库的 origin 名称及其对应的 URL: git remote -v这个命令会列出所有配置的远程仓库及其名称,其中 origin 通常是克隆时自动设置的默认远程仓库名称。输出示例&#…...
LeetCode:2848. 与车的相交点 一次遍历,时间复杂度O(n)
2848. 与车的相交点 today 2848. 与车的相交点 题目描述 给你一个下标从 0开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i ,nums[i] [starti, endi] ,其中 s t a r t i start_i starti 是第 i 辆车的起点, e n …...

Xcode 16 RC (16A242) 发布下载,正式版下周公布
Xcode 16 RC (16A242) - Apple 平台 IDE IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 请访问原文链接:https://sysin.org/blog/apple-xcode-16/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org Xcode 16 的新功…...

git 更换远程地址的方法
需要将正在开发的代码远程地址改成新的地址,通过查询发现有三个方法可以实现,特此记录。具体方法如下: (1)通过命令直接修改远程仓库地址 git remote 查看所有远程仓库git remote xxx 查看指定远程仓库地址git remote…...

9. 什么是 Beam Search?深入理解模型生成策略
是不是总感觉很熟悉? 在之前第5,7,8篇文章中,我们都曾经用到过与它相关的参数,而对于早就有着实操经验的同学们,想必见到的更多。这篇文章将从示例到数学原理和代码带你进行理解。 Beam Search 对应的中文翻…...
Spring自定义注解
目录 一、interface 关键字 二、元注解 三、简单实现 四、使用切面执行自定义注解逻辑 1) 首先将刚才的注解修改成放在方法上的: 2) 定义一个切面类: 3)将注解放入到接口方法中测试: 五、切点表达式 一、interface 关键字 …...

微信小程序:wx.login或调用uni.login时报错the code is a mock one
微信小程序,调用wx.login或调用uni.login方法,返回the code is a mock one 原因与解决 原因:没有关联真实的 appid,解决办法:绑定真实的微信小程序的appid...
URL的执行流程
基本概念: URL(统一资源定位符,Uniform Resource Locator)的执行流程是指当你在浏览器中输入一个URL并按下回车键时,从输入URL到最终在浏览器中显示网页的完整过程。 1.解析协议 URL 以协议开头,如 http…...

双指针算法专题(2)
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: 优选算法专题 想要了解双指针算法的介绍,可以去看下面的博客:双指针算法的介绍 目录 611.有效三角形的个数 LCR 1…...

加密与安全_优雅存储用户密码的最佳实践
文章目录 Pre概述最佳实践避免使用MD5、SHA1等快速哈希算法加盐哈希 (不推荐)使用BCrypt、Argon2等慢哈希算法 (推荐)BCrypt Code1. 自动生成和嵌入盐2. 哈希结果的格式3. 代价因子 BCrypt特点 防止暴力破解1. 登录失败锁定2. 双因素认证(2FA…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...