OpenCV 图像重映射函数remap()实例详解

OpenCV 图像重映射函数remap()对图像应用通用几何变换。其原型如下:

void remap(InputArray src,

OutputArray dst,

InputArray map1,

InputArray map2,

int interpolation,

int borderMode = BORDER_CONSTANT,

const Scalar & borderValue = Scalar()

参数:

src 源图像。

dst 输出目标图像。它的大小与 map1 相同,类型与 src 相同。

map1 (x,y) 点或仅 x 值的第一个映射具有 CV_16SC2 、 CV_32FC1 或 CV_32FC2 类型。

map2 y 值的第二个映射分别具有 CV_16UC1、CV_32FC1 类型或无类型(如果映射 1 是 (x,y) 点,则为空映射)。

interpolation 插值方法,可选: INTER_NEAREST, INTER_LINEAR , INTER_CUBIC, INTER_LANCZOS4, INTER_NEAREST_EXACT INTER_MAX WARP_FILL_OUTLIERS , WARP_INVERSE_MAP

borderMode 像素外推法。当 borderMode=BORDER_TRANSPARENT 时,意味 着目标图像中与源图像中的"异常值"相对应的像素不会被该函数修改。可为:BORDER_CONSTANT ,BORDER_REPLICATE,BORDER_REFLECT,BORDER_WRAP ,BORDER_REFLECT_101 ,BORDER_TRANSPARENT ,BORDER_REFLECT101 ,BORDER_DEFAULT,BORDER_ISOLATED

borderValue 在边界恒定的情况下使用的值。默认值为 0。

OpenCV的remap函数的主要用途是重新映射图像中像素的位置或值。用它可以实现图像镜像、形态改变、特效制作、图像分割等。下面以例演示 其用法。先写一个示例程序,读入一张图片然后,用remap函数分别获取水平镜像图片,示例程序代码如下:

// RemapTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include<opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat src = imread("1.png");
	if (src.empty())
	{
		cout << "Cann't load Image!";
		return -1;
	}
	imshow("原始图像:",src);
	Mat srcx(src.rows, src.cols, CV_32F); // x 方向
	Mat srcy(src.rows, src.cols, CV_32F); // y 方向

	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = src.cols - j - 1;
			srcy.at<float>(i, j) = i;
			
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("水平镜像:", src);

	waitKey(0);
	return 1;
}

试运行,结果如下:

获取垂直镜像,其代码如下:

// RemapTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include<opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat src = imread("1.png");
	if (src.empty())
	{
		cout << "Cann't load Image!";
		return -1;
	}
	imshow("原始图像:",src);
	Mat srcx(src.rows, src.cols, CV_32F); // x 方向
	Mat srcy(src.rows, src.cols, CV_32F); // y 方向

	//水平镜像
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = src.cols - j - 1;
			srcy.at<float>(i, j) = i;
			
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("水平镜像:", src);
	*/

	//垂直镜像
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j;
			srcy.at<float>(i, j) = src.rows -i -1;

		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("垂直镜像:", src);

	waitKey(0);
	return 1;
}

试运行结果如下:

再写一段改变图形形状的代码,代码如下:

// RemapTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include<opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat src = imread("1.png");
	if (src.empty())
	{
		cout << "Cann't load Image!";
		return -1;
	}
	imshow("原始图像:",src);
	Mat srcx(src.rows, src.cols, CV_32F); // x 方向
	Mat srcy(src.rows, src.cols, CV_32F); // y 方向

	//水平镜像
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = src.cols - j - 1;
			srcy.at<float>(i, j) = i;
			
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("水平镜像:", src);
	*/

	//垂直镜像
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j;
			srcy.at<float>(i, j) = src.rows -i -1;

		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("垂直镜像:", src);
	*/

	//改变图像形状
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j;
			srcy.at<float>(i, j) = i + 5.0 * cos(i / 5.0);
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("改变图形形状:", src);



	waitKey(0);
	return 1;
}

割裂效果呈现,实现的程序代码如下:

// RemapTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include<opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat src = imread("1.png");
	if (src.empty())
	{
		cout << "Cann't load Image!";
		return -1;
	}
	imshow("原始图像:",src);
	Mat srcx(src.rows, src.cols, CV_32F); // x 方向
	Mat srcy(src.rows, src.cols, CV_32F); // y 方向

	//水平镜像
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = src.cols - j - 1;
			srcy.at<float>(i, j) = i;
			
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("水平镜像:", src);
	*/

	//垂直镜像
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j;
			srcy.at<float>(i, j) = src.rows -i -1;

		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("垂直镜像:", src);
	*/

	//改变图像形状
	/*
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j;
			srcy.at<float>(i, j) = i + 5.0 * cos(i / 5.0);
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("改变图形形状:", src);
	*/

	//割裂效果呈现
	for (size_t i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			srcx.at<float>(i, j) = j + 10.0 * tan(j / 5.0);;
			srcy.at<float>(i, j) = i;
		}
	}
	remap(src, src, srcx, srcy, INTER_LINEAR);
	imshow("割裂效果:", src);


	waitKey(0);
	return 1;
}

试运行,结果如下:

相关推荐
YueiL4 分钟前
OpenCV 颜色空间:原理与操作指南
python·opencv
源码姑娘6 分钟前
基于OpenCV的车牌识别系统(源码+论文+部署教程)
人工智能·毕业设计
我码玄黄7 分钟前
大模型时代,为什么模型都是多少B?
人工智能·llm
Dmatteratall11 分钟前
目标检测热力图的生成代码(基于GridCam)生成的
人工智能·目标检测·计算机视觉
没学上了19 分钟前
逻辑回归机器学习
人工智能·深度学习·逻辑回归
CITY_OF_MO_GY37 分钟前
Spark-TTS:基于大模型的文本语音合成工具
人工智能·深度学习·语音识别
阿丢是丢心心43 分钟前
【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)
人工智能·深度学习·神经网络
新智元43 分钟前
10²⁶参数,AGI 还需 70 年!清华人大预测届时 GPU 总价达 4000 万倍苹果市值
人工智能·openai
何大春1 小时前
【对话推荐系统综述】Broadening the View: Demonstration-augmented Prompt Learning for CR
论文阅读·人工智能·深度学习·语言模型·prompt·论文笔记
WenGyyyL1 小时前
使用OpenCV和MediaPipe库——增强现实特效(在手腕添加虚拟手表)
人工智能·opencv·计算机视觉·ar·cv·mediapipe