重映射

把一个图像中一个位置的像素放置到另一个图片指定位置的过程.

为了完成映射过程, 有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标不是一一对应的.

简单的说就是改变图片的位置(左,右,上,下,颠倒)


 
void remap(InputArray src, OutputArraydst, InputArray map1, InputArray map2, int interpolation, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

    • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
    • 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型。
    • 第三个参数,InputArray类型的map1,它有两种可能的表示对象。
  • 表示点(x,y)的第一个映射。
  • 表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
  • 第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
  • 若map1表示点(x,y)时。这个参数不代表任何值。
  • 表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。

 

  • 第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
  • INTER_NEAREST - 最近邻插值
  • INTER_LINEAR – 双线性插值(默认值)
  • INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)
  • INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)

 

  • 第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。
  • 第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。

其中要变换的模式如下

 

代码展示

#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
using namespace std;
using namespace cv;
Mat src, dst, mat_x, mat_y;
int index = 0;
void updateMap();
int main()
{
	src = imread("C:\\Users\\马迎伟\\Desktop\\heibao.jpg", 1);
	if (src.empty())
	{
		printf("cannot load!!\n");
		system("pause");
		return -1;
	}
	namedWindow("原图");
	imshow("原图", src);
	//生成x,y映射表
	mat_x.create(src.size(), CV_32FC1);//映射表只能是32FC1或者32FC2类型
	mat_y.create(src.size(), CV_32FC1);
	//重映射
	int c;
	while (true)
	{
		c = waitKey(500);
		updateMap();
		remap(src, dst, mat_x, mat_y, INTER_LINEAR);
		namedWindow("效果");
		imshow("效果", dst);
		if ((char)c == 27)
		{
			break;
		}
		index = (index + 1) % 4;
	}
	return 0;
}
void updateMap()//更新映射表
{
	int height = src.rows, width = src.cols;
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			switch (index)
			{
			case 0://缩小一半
				if (col > width*0.25&&col<width*0.75&&row>height*0.25&&row < height*0.75)
				{
					//mat_x每个点存的值代表生成图像的(row,col)位置对应于原图的哪一列
					mat_x.at<float>(row, col) = 2 * col - width * 0.5;
					//mat_y每个点存的值代表生成图像的(row,col)位置对应于原图的哪一行
					mat_y.at<float>(row, col) = 2 * row - height * 0.5;
				}
				else
				{
					mat_x.at<float>(row, col) = 0;
					mat_y.at<float>(row, col) = 0;
				}
				break;
			case 1://左右互换
				mat_x.at<float>(row, col) = width - col;
				mat_y.at<float>(row, col) = row;
				break;
			case 2://上下互换
				mat_x.at<float>(row, col) = col;
				mat_y.at<float>(row, col) = height - row;
				break;
			case 3://对角线互换
				mat_x.at<float>(row, col) = width - col;
				mat_y.at<float>(row, col) = height - row;
				break;
			}
		}
	}
}