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

试运行,结果如下:

相关推荐
AI_yangxi1 小时前
短视频矩阵系统选哪家
大数据·人工智能·矩阵
Shockang7 小时前
AI Slop 治理实战
人工智能
Mr数据杨8 小时前
医学影像分类实战复盘 从 Kaggle 竞赛到可落地建模流程
人工智能·数据分析·kaggle竞赛
AI情绪识别开源9 小时前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
ZGIAI9 小时前
ZGI 迭代节点:批量资料的逐项处理
人工智能·架构
ZGIAI9 小时前
ZGI 知识检索:让业务回答有据可查
人工智能·架构
Asize9 小时前
框架的说明书是写给 AI 看的:我用 Next.js 搭了个博客
人工智能·代码规范·next.js
2601_955662469 小时前
AI 配音工具 7 款实测:短视频、影视解说、小说推文音质横向对比
人工智能·音视频·语音识别·视频
AI创界者10 小时前
PinkCherry-MiniMax-H3 全能AI视频整合包:8G显存开箱即用,支持首尾帧/超分补帧/自动提示词
人工智能·aigc