【OpenCV】-重映射

news/2024/7/21 4:41:15 标签: opencv, 计算机视觉, 图像处理

文章目录

        • 1、重映射的概念
        • 2、实现重映射:remap()函数
        • 3、基本重映射
        • 4、实现多重映射

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方向反转

在这里插入图片描述


http://www.niftyadmin.cn/n/1815463.html

相关文章

SQL 语句的执行效率

1、操作符号&#xff1a; NOT IN操作符此操作是强列推荐不使用的&#xff0c;因为它不能应用表的索引。推荐方案&#xff1a;用NOT EXISTS 或&#xff08;外连接判断为空&#xff09;方案代替 "IS NULL", "<>", "!", "!>", &…

关闭ie8的欢迎界面

开始->运行->gpedit.msc->计算机配置->管理模板->Windows Compoents->Internet Explorer->阻止执行首次运行自定义设置”&#xff0c;选择“已启用”项&#xff0c;在“选择您的选择”下拉列表中选择“直接转到主页”。重新启动IE8转载于:https://www.cnb…

【Python21天学习挑战赛】-列表 元组 range

​ 活动地址&#xff1a;CSDN21天学习挑战赛 ​开头一叙&#xff1a; 无论是以后学习需要或者是三年后的工作需要&#xff0c;都需要用到python的工具&#xff0c;也接着这次活动的机会&#xff0c;把python系统的学一遍。跟着大佬&#xff0c;让python知识从入门到精通。 文章…

blog开张,发文庆祝

blog开张&#xff0c; 花费了好大力气才搞了这块地皮&#xff0c;得好好利用&#xff0c; 学而时习之&#xff0c;温故而知新&#xff0c;记录下学习的历程&#xff0c;便于以后查阅&#xff0c;方便交流&#xff0c;希望在此遇到共同爱好者&#xff0c;交换心得&#xff0c;共…

mysql索引ab和ba_MySQL 索引总结

1、索引是做什么的?索引用于快速找出在某个列中有一特定值的行。不使用索引&#xff0c;MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大&#xff0c;花费的时间越多。如果表中查询的列有一个索引&#xff0c;MySQL能快速到达一个位置去搜寻到数据文件的中间…

webstrom如何配置babel来转换es6

网上有很多关于如何设置babel的。我学习着设置&#xff0c;但总差那么几步&#xff0c;没能满足我的需求。 我使用的是webStorm2017.1版本。 babel安装准备 使用webStorm自带的filewatcher中的babel自动编译前&#xff0c;需要安装一些babel库 全局安装babel-cli npm insta…

【OpenCV】-仿射变换

1、认识仿射变换 仿射变换&#xff08;Affine Map)又称仿射映射&#xff0c;是指在几何中&#xff0c;一个向量空间进行一次线性变换并接上一个平移&#xff0c;变换为另一个向量空间的过程。保持二维图形之间的相对位置保持不变&#xff0c;平行线依然是平行线&#xff0c;且…

【Python21天学习挑战赛】字典 小数据池

​ ​ 活动地址&#xff1a;CSDN21天学习挑战赛 ​ 开头一叙&#xff1a; 无论是以后学习需要或者是三年后的工作需要&#xff0c;都需要用到python的工具&#xff0c;也接着这次活动的机会&#xff0c;把python系统的学一遍。跟着大佬&#xff0c;让python知识从入门到精通。 …