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

试运行,结果如下:

相关推荐
CoovallyAIHub4 分钟前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
深度学习·算法·计算机视觉
孤烟34 分钟前
【RAG 实战系列 02】检索精度翻倍!混合检索(稀疏 + 稠密)实战教程
人工智能·llm
明明如月学长1 小时前
OpenClaw 帮我睡后全自动完成了老板交代的任务
人工智能
uuware1 小时前
Lupine.Press + AI 助您分分钟搞定技术项目的文档网站
人工智能·前端框架
海上日出1 小时前
使用 QuantStats 进行投资组合绩效分析:Python 量化实战指南
人工智能
Qinana1 小时前
150行代码搞定私有知识库!Node.js + LangChain 打造最小化 RAG 系统全流程
人工智能·程序员·node.js
猿猿长成记1 小时前
AI专栏 | AI大法则之思维链、自洽性、思维树
人工智能
用户5191495848451 小时前
CrushFTP 条件竞争认证绕过漏洞利用工具 (CVE-2025-54309)
人工智能·aigc
一拳不是超人1 小时前
AI时代,35岁程序员焦虑终结:经验从负债变资产
人工智能·程序员
IT_陈寒2 小时前
Vite快得离谱?揭秘它比Webpack快10倍的5个核心原理
前端·人工智能·后端