当前位置:网站首页>【OpenCV】-重映射
【OpenCV】-重映射
2022-08-04 00:55:00 【我菜就爱学】
1、重映射的概念
重映射是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。为了完成重映射过程,需要获得一些插值为非整数像素的坐标,因为源图像与目标图像像素坐标不是一一对应的。如下:
g ( x , y ) = f ( h ( x , y ) ) g(x,y)=f(h(x,y)) g(x,y)=f(h(x,y))
g()是目标图像,f()是源图像,而h(x,y)是作用于(x,y)的映射方法函数。
2、实现重映射:remap()函数
remap()函数会根据指定的映射形式,将源图像进行重映射几何变换:
d s t ( x , y ) = s r c ( m a p x ( x , y ) , m a p y ( x , y ) ) dst(x,y)=src(mapx(x,y),mapy(x,y)) dst(x,y)=src(mapx(x,y),mapy(x,y))
void remap(InputArray src,OutputArray dst,InputArray map1,InputArray map2,int interpolation,intborderMode=BORDER_CONSTANT,const Scalar& borderValue=Scalar())
- 第一个参数:输出图像
- 第二个参数:函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型
- 第三个参数:InputArray类型的 map1,有两种可能的表示对象
- 表示点(x,y)的第一映射
- 表示CV_16SC2,CV_32FC1,CV_32FC2类型的X值
- 第四个参数:InputArray类型的 map2,有两种可能的表示对象
- 若map1表示点(x,y)时,这个参数不代表任何值
- 表示CV_16UC1,CV_32FC1类型的Y值
- 第五个参数:int 类型的interpolation,插值方式,所选的插值方式如下:
- INTER_NEAREST——最近邻插值
- INTER_LINEAR——双线性插值(默认值)
- INTER_CUBIC——双三次样条插值
- INTER_LANCZOS4——Lanczos插值
- 第六个参数:边界模式
- 第七个参数:const Scalar&类型的borderValue,当有常数边界使用的值,其默认值Scalar(),即默认值为0
3、基本重映射
说明:下面是精简后的以remap函数为核心的示例程序
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage, dstImage;
Mat map_x, map_y;
//载入原始图像
srcImage = imread("E:\\Pec\\car.jpg", 1);
imshow("【原始图】", srcImage);
//创建和原始图一样的效果图,x重映射图,y重映射图
dstImage.create(srcImage.size(), srcImage.type());
map_x.create(srcImage.size(), CV_32FC1);
map_y.create(srcImage.size(), CV_32FC1);
//双层循环,遍历每一个像素点,改变map_x和Map_y
for (int j = 0; j < srcImage.rows; j++)
{
for (int i = 0; i < srcImage.cols; i++)
{
//通过at获取像素值
map_x.at<float>(j, i) = static_cast<float>(i);
map_y.at<float>(j, i) = static_cast<float>(srcImage.rows-j);
}
}
//进行重映射
remap(srcImage, dstImage, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
imshow("【效果图】", dstImage);
waitKey(0);
}
4、实现多重映射
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
#define WINDOW_NAME "【程序窗口】"
Mat g_srcImage, g_dstImage;
Mat g_map_x, g_map_y;
int update_map(int key);
static void ShowHelpText();
int main()
{
system("color 2F");
ShowHelpText();
//载入原始图像
g_srcImage = imread("E:\\Pec\\car.jpg", 1);
imshow("【原始图】", g_srcImage);
//创建和原始图一样的效果图,x重映射图,y重映射图
g_dstImage.create(g_srcImage.size(), g_srcImage.type());
g_map_x.create(g_srcImage.size(), CV_32FC1);
g_map_y.create(g_srcImage.size(), CV_32FC1);
namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME, g_srcImage);
while (1)
{
int key = waitKey(0);
if ((key & 255) == 27)
{
cout << "程序退出......" << endl;
break;
}
update_map(key);
//根据按下键盘按键来更新map_x & map_y的值,然后调用remap()进行重映射
remap(g_srcImage, g_dstImage, g_map_x, g_map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
imshow(WINDOW_NAME, g_dstImage);
}
return 0;
}
int update_map(int key)
{
//双层循环,遍历每一个像素点,改变map_x和Map_y
for (int j = 0; j < g_srcImage.rows; j++)
{
for (int i = 0; i < g_srcImage.cols; i++)
{
switch (key)
{
case '1'://按键1按下,进行第一重映射操作
if (i > g_srcImage.cols*0.25&&i<g_srcImage.cols*0.75&&j>g_srcImage.rows*0.25&&j < g_srcImage.rows*0.75)
{
g_map_x.at<float>(j, i) = 2 * (i - g_srcImage.cols*0.25) + 0.5;
g_map_y.at<float>(j, i) = 2 * (j - g_srcImage.rows*0.25) + 0.5;
}
else
{
g_map_x.at<float>(j, i) = 0;
g_map_y.at<float>(j, i) = 0;
}
break;
case '2': //按键2按下,进行第二重映射操作
g_map_x.at<float>(j, i) = static_cast<float>(i);
g_map_y.at<float>(j, i) = static_cast<float>(g_srcImage.rows - j);
break;
case '3':
g_map_x.at<float>(j, i) = static_cast<float>(g_srcImage.cols-i);
g_map_y.at<float>(j, i) = static_cast<float>(j);
break;
case '4':
g_map_x.at<float>(j, i) = static_cast<float>(g_srcImage.cols - i);
g_map_y.at<float>(j, i) = static_cast<float>(g_srcImage.rows - j);
break;
}
}
}
return 1;
}
static void ShowHelpText()
{
cout << "\n\n\n\t欢迎来到重映射示例程序\n";
cout << "\n\n\n\t按键操作如下:" ;
cout << "\n\n\n\t键盘按下【ESC】-退出程序" ;
cout << "\n\n\n\t键盘按下【1】-第一种映射方式,缩小2倍" ;
cout << "\n\n\n\t键盘按下【2】-第二种映射方式,y方向翻转" ;
cout << "\n\n\n\t键盘按下【3】-第三种映射方式,x方向反转" ;
cout << "\n\n\n\t键盘按下【4】-第四种映射方式,x,y方向反转" ;
}
第一种映射方式,缩小2倍
第二种映射方式,y方向翻转
第三种映射方式,x方向反转
第四种映射方式,x,y方向反转
边栏推荐
- 网络带宽监控,带宽监控工具哪个好
- 咱们500万条数据测试一下,如何合理使用索引加速?
- 越来越火的图数据库到底能做什么?
- 因为一次bug的教训,我决定手撕Nacos源码(先撕客户端源码)
- 扩展卡尔曼滤波EKF
- MATLAB三维绘图命令plot3入门
- MPLS Comprehensive Experiment
- LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三:两次优化
- Justin Sun: Web3.0 and the Metaverse will assist mankind to enter the online world more comprehensively
- Tanabata festival coming, VR panoramic look god assists for you
猜你喜欢
fsdbDump用法
如何通过单步调试的方式找到引起 Fiori Launchpad 路由错误的原因试读版
Salesforce's China business may see new changes, rumors may be closing
Electronics manufacturing enterprise deployment WMS what are the benefits of warehouse management system
BGP实验(含MPLS)
MySQL回表指的是什么
共享新能源充电桩充电站建设需要些什么流程及资料?
It will invest about 200 billion US dollars in the United States in 20 years, and Samsung Electronics looks so handsome
View the version number of CUDA, pytorch, etc.
越来越火的图数据库到底能做什么?
随机推荐
nodeJs--async/await
教你如何定位不合理的SQL?并优化之
A Preliminary Study of RSS Subscription to WeChat Official Account-feed43
Using matlab to solve the linear optimization problem based on matlab dynamic model of learning notes _11 】 【
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三:两次优化
XSS - Bypass for loop filtering
It will invest about 200 billion US dollars in the United States in 20 years, and Samsung Electronics looks so handsome
NLP resources that must be used for projects [Classified Edition]
C # WPF equipment monitoring software (classic) - the next
即席查询——Presto
VR全景拍摄线上展馆,3D全景带你沉浸体验
jmeter distributed stress test
Nanoprobes Mono- Sulfo -NHS-Nanogold的使用和应用
Analysis: What makes the Nomad Bridge hack unique
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三:两次优化
身为程序员的我们如何卷死别人?破局重生。
typescript58 - generic classes
【性能优化】MySQL常用慢查询分析工具
jmeter分布式压测
扩展卡尔曼滤波EKF