像素重映射(cv::remap)

1、像素重映射概念;
2、API介绍;
3、代码演示;

像素重映射

1、像素重映射:把输入图像中各个像素按照一定的规则映射到另外一张图像的对应位置上去,形成一张新的图像; 映射的称为功能函数,数学原理如下:

2、demo: 对称映射

相关API

1、API : cv::remap();
参数说明:
src–输入图像,可以是3通道或单通道
dst–输出图像
map1–x映射表,要求位数必须是CV_32FC1/CV_32FC2;
map2–y映射表,
interpolation : 插值,常见的有线性插值或双线性,立方插值等等;一般选INTER_LINEAR(线性插值);
borderMode: 设置图像边缘处理方式;
borderValue : 设置使用什么颜色填充;(一般用不上)

Code

1、一种与键盘交互模板:

	int  index = 0;
	int c =0;
	while(true)
	{
			c = waitkey(500);  //500ms获取一次键盘输入
			index = c %4;
			if((char)c == 27)
			{
				break;
			}	
	}
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;

Mat src, dst, map_x, map_y;

int index = 0;

void update_map(void);

int main(int argc, char** argv)
{
   
   //原先写的Mat src = ....;导致全局变量被隐藏!!!!
	src = imread("C:\\Users\\hello\\Desktop\\18.jpg");
	if (!src.data)
	{
   
		cout << "could not load the image..." << endl;
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);

	//首先建立两个映射表
	map_x.create(src.size(), CV_32FC1);  //创建和原图一样大,数据类型为CV_32FC1(32位单通道)的图像
	map_y.create(src.size(), CV_32FC1);

	int c = 0;
	while (true)
	{
   
		c = waitKey(500);  //500ms检测一次键值
		
		if ((char)c == 27)
		{
   
			break;
		}
		index = c % 4;
		update_map();
		remap(src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 255, 255));
		imshow("remap image", dst);
	}
	
	return 0;
}

void update_map(void)
{
   
	for (int row = 0; row < src.rows; row++)
	{
   
		for (int col = 0; col < src.cols; col++)
		{
   
			switch (index)
			{
   
			case 0:
				//只有在规定范围内的像素有效(缩小一半)
				if ((col > src.cols * 0.25) && (col <= src.cols * 0.75) && (row > src.rows * 0.25) && (row <= src.rows * 0.75))
				{
   
					map_x.at<float>(row, col) = 2 * (col - (src.cols*0.25)); //x方向的映射
					map_y.at<float>(row, col) = 2 * (row - (src.rows*0.25));
				}
				else
				{
   
					map_x.at<float>(row, col) = 0;
					map_y.at<float>(row, col) = 0;
				}
				break;
			case 1:
				map_x.at<float>(row, col) = (src.cols - col - 1); //列映射 
				map_y.at<float>(row, col) = row;
				break;
			case 2:
				map_x.at<float>(row, col) = col; //行映射 
				map_y.at<float>(row, col) = (src.rows - row - 1);
				break;
			case 3:
				map_x.at<float>(row, col) = (src.cols - col - 1); //列映射 
				map_y.at<float>(row, col) = (src.rows - row - 1);
				break;

			default:
				break;
			}
		}
	}
}

效果

1、缩小一半:

2、X方向映射(列映射)

3、Y方向映射(行映射)

4、XY方向均映射: