1.重映射是把图像中某位置的像素放置到另一图片指定位置的过程,通过重映射表达像素位置:
g(x,y)=f(h(x,y))
g()是目标图像,f()是原图像,h(x,y)是作用于(x,y)的映射方法函数
2.函数:remap()函数,根据指定的映射形式,将源图像进行重映射几何变换,基于以下公式:
3.函数原型:
void remap(InputArray src, OuptutArray dst, InputArray map1, InputArray map2, int interpolation, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
4.参数说明:
(1)输入图像,单通道8位或浮点型图像
(2)输出图像,与原图像有一样尺寸和类型
(3)两种可能表示:1)表示点(x,y)的第一个映射 2)表示CV_16SC2、CV_32FC1或CV_32FC2类型的x值
(4)两种可能表示:1)map1表示点(x,y)时,参数不代表任何值 2)表示CV_16UC1、CV_32FC1类型的y值
(5)插值方式,可选插值方式:
1)INTER_NEAREST–最近邻插值
2)INTER_LINEAR–双线性插值(默认值)
3)INTER_CUBIC–双三次样条插值(超过44像素邻域内的双三次插值)
4)INTER_LANCZOS4–Lanczos插值(超过88像素领域的Lanczos插值)
(6)边界模式,默认值BORDER_CONSTANT,表示目标图像中“离群点”像素值不会被此函数修改
(7)当有常数边界时使用的值,默认Scalar()
5.调用示例:
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
//变量定义
Mat srcImage, dstImage;
Mat map_x, map_y;
//载入原图
srcImage = imread("love.jpg");
if (!srcImage.data)
{
printf("载入原图失败~!\n");
return false;
}
//显示原图
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 i = 0; i < srcImage.rows; i++)
{
for (int j = 0; j < srcImage.cols; j++)
{
map_x.at<float>(i, j) = static_cast<float>(j);
map_y.at<float>(i, j) = static_cast<float>(srcImage.rows - i);
}
}
//重映射操作
remap(srcImage, dstImage, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
//显示效果图
imshow("【效果图】", dstImage);
waitKey(0);
return 0;
}
/*
效果:
按键控制实现4种不同重映射模式
*/
#include
#include
#include
using namespace cv;
using namespace std;
#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()
{
//改变console字体颜色
system("color 2F");
//显示帮助文字
ShowHelpText();
//【1】载入原图
g_srcImage = imread("3.jpg");
if (!g_srcImage.data)
{
printf("载入原图失败~!\n");
return false;
}
//【2】创建和原图一样的效果图,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);
//【3】创建窗口并显示
namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
imshow(WINDOW_NAME, g_srcImage);
//【4】轮询按键,更新map_x和map_y的值,进行重映射操作并显示效果图
while (1)
{
//获取键盘按键
int key = waitKey(0);
//判断ESC是否按下,若按下便退出
if ((key & 255) == 27)
{
cout << "程序退出...........\n";
break;
}
//根据按下的键盘按键来更新 map_x & map_y的值. 然后调用remap( )进行重映射
update_map(key);
remap(g_srcImage, g_dstImage, g_map_x, g_map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
//显示效果图
imshow(WINDOW_NAME, g_dstImage);
}
return 0;
}
//update_map( )函数:根据按键来更新map_x与map_x的值
int update_map(int key)
{
//双层循环,遍历每一个像素点
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) = static_cast<float>(2 * (i - g_srcImage.cols*0.25) + 0.5);
g_map_y.at<float>(j, i) = static_cast<float>(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': // 键盘【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': // 键盘【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 0;
}
static void ShowHelpText()
{
printf("\n\n\n\t欢迎来到重映射示例程序~\n\n");
printf("\n\n\t按键操作说明: \n\n");
printf("\t\t键盘按键【ESC】- 退出程序\n");
printf("\t\t键盘按键【1】- 第一种映射方式\n");
printf("\t\t键盘按键【2】- 第二种映射方式\n");
printf("\t\t键盘按键【3】- 第三种映射方式\n");
printf("\t\t键盘按键【4】- 第四种映射方式\n");
}
映射模式3 映射模式4