OpenCv--像素重映射
重映射
把一个图像中一个位置的像素放置到另一个图片指定位置的过程.
为了完成映射过程, 有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标不是一一对应的.
简单的说就是改变图片的位置(左,右,上,下,颠倒)
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;
}
}
}
}