重映射就是把一个图像中一个为之的像素放置到另一个图片指定位置过程。为了完成重映射过程有必要获得一些插值作为非整数像素坐标,因为原图像与目标图像的像素坐标不是一一对应的。我们通过重映射来表达每个像素的位置(x, y):
g(x, y)=f(h(x,y))
这里g()是目标图像,f()是原图像,h(x,y)是作用于(x,y)的映射方法函数。假设有一幅图像I,满足下面条件作重映射:
h(x,y)=(I.cols - x,y)
图像会按照x轴方向发生反转,如下:
看到红色圈关于x的位置改变(x轴水平翻转)
opencv提供函数reman()实现简单的重映射。remap函数原型如下:
void cv::remap ( InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode = BORDER_CONSTANT, const Scalar & borderValue = Scalar() )
参数解释
. src:输入图像
. dst:目标图像,与原图像类型相同,与map1图像尺寸大小相等
. map1: (x, y)的第一个映射或者是CV_16SC2、CV_32FC1或CV_32FC2的x值。查询convertMaps获得详细解释。
. map2: 第二个map,表示类型为CV_16UC1、CV_32FC1的y值或空值(如果map1是用(x,y)进行表示)
. interpolation: 插值方式,在此函数中不支持INTER_AREA插值方法。插值方法如下(可通过InterpolationFlags查看)
. borderMode: 边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点”的像素值不会被此函数修改
. borderValue: 当有常数边界时使用的值,有默认值Scalar()即0
示例代码
#include <iostream> #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> using namespace std; using namespace cv; //定义全局变量 Mat srcImage, dstImage; Mat map1_x, map2_y; String windowName = "图像重映射"; int ind; //重映射类型选择 void updateMap(void); int main() { //初始化参数 ind = 0; srcImage = imread("dog.jpg"); dstImage.create(srcImage.size(), srcImage.type()); map1_x.create(srcImage.size(), CV_32FC1); map2_y.create(srcImage.size(), CV_32FC1); //创建窗口 namedWindow(windowName, WINDOW_AUTOSIZE); while(true) { int c = waitKey(1000); //延迟1000ms if((char)c == 27) { break; //ESC退出 } updateMap(); //调用函数,更新重映射模式 remap(srcImage, dstImage, map1_x, map2_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); imshow(windowName, dstImage); } return 0; } void updateMap(void) { ind = ind%4; for(int j = 0; j < srcImage.rows; j++) { for(int i = 0; i < srcImage.cols; i++) { switch(ind) { //图像长宽缩小到原来的一半并居中显示 case 0: if(i > srcImage.cols*0.25 && i < srcImage.cols*0.75 && j > srcImage.rows*0.25 && j < srcImage.rows*0.75) { map1_x.at<float>(j, i) = 2*(i - srcImage.cols*0.25) + 0.5; map2_y.at<float>(j, i) = 2*(j - srcImage.rows*0.25) + 0.5; } else { map1_x.at<float>(j, i) = 0; map2_y.at<float>(j, i) = 0; } break; //图像左右翻转 case 1: map1_x.at<float>(j, i) = i; map2_y.at<float>(j, i) = srcImage.rows - j; break; //图像上下翻转 case 2: map1_x.at<float>(j, i) = srcImage.cols - i; map2_y.at<float>(j, i) = j; break; //图像上下左右均翻转 case 3: map1_x.at<float>(j, i) = srcImage.cols - i; map2_y.at<float>(j, i) = srcImage.rows - j; break; default: break; } } } ind++; }
————————————————
运行结果
图像缩小
左右翻转
上下翻转
版权声明:本文为CSDN博主「梧桐栖鸦」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:
https://blog.csdn.net/keith_bb/article/details/56295873
