opencv笔记(十九)——对图像进行remapping
何谓remapping呢?翻译过来就是重映射。因为每个图像本身就是f(x, y),是像素位置为自变量的像素值的函数。然后我们对这些位置上的像素的值再次进行变换,
g(x, y) = f(h(x, y)),h(x, y)就是重映射的函数,g(x, y)就是重映射的结果。
想象如果h(x, y) = f(I.cols-x, y),会怎么样?
明显地,新图像是原图像关于x轴的翻转。
先看看OpenCV中对remapping操作的定义
void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
src是输入的图像,无特殊要求
dst是输出的图像,和src的尺寸类型一致。文档里说remap不能就地操作,建议dst最好不要与src相同。
map1是x轴上的映射,map1和src尺寸一致,类型一般为CV_32FC1。例如map1.at<float>(i, j) = (src.cols - i);
map2是y轴上的映射
interpolation在这里一般为INTER_LINEAR,采用bilinear interpolation方法将一对浮点坐标(映射后)转化为整数坐标。见下图:
出自:http://en.wikipedia.org/wiki/Bilinear_interpolation
borderMode一般默认为BORDER_CONSTANT,这里的border我也不太清楚意义。
OpenCV给出的使用remap的例子很清晰易懂,注意map1和map2是如何设定的即可:
1 /** 2 * @function Remap_Demo.cpp 3 * @brief Demo code for Remap 4 * @author Ana Huaman 5 */ 6 7 #include "opencv2/highgui/highgui.hpp" 8 #include "opencv2/imgproc/imgproc.hpp" 9 #include <iostream> 10 #include <stdio.h> 11 12 using namespace cv; 13 14 /// Global variables 15 Mat src, dst; 16 Mat map_x, map_y; 17 const char* remap_window = "Remap demo"; 18 int ind = 0; 19 20 /// Function Headers 21 void update_map( void ); 22 23 /** 24 * @function main 25 */ 26 int main( int, char** argv ) 27 { 28 /// Load the image 29 src = imread( argv[1], 1 ); 30 31 /// Create dst, map_x and map_y with the same size as src: 32 dst.create( src.size(), src.type() ); 33 map_x.create( src.size(), CV_32FC1 ); 34 map_y.create( src.size(), CV_32FC1 ); 35 36 /// Create window 37 namedWindow( remap_window, WINDOW_AUTOSIZE ); 38 39 /// Loop 40 for(;;) 41 { 42 /// Each 1 sec. Press ESC to exit the program 43 int c = waitKey( 1000 ); 44 45 if( (char)c == 27 ) 46 { break; } 47 48 /// Update map_x & map_y. Then apply remap 49 update_map(); 50 remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) ); 51 52 // Display results 53 imshow( remap_window, dst ); 54 } 55 return 0; 56 } 57 58 /** 59 * @function update_map 60 * @brief Fill the map_x and map_y matrices with 4 types of mappings 61 */ 62 void update_map( void ) 63 { 64 ind = ind%4; 65 66 for( int j = 0; j < src.rows; j++ ) 67 { for( int i = 0; i < src.cols; i++ ) 68 { 69 switch( ind ) 70 { 71 case 0: 72 if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 ) 73 { 74 map_x.at<float>(j,i) = 2*( i - src.cols*0.25f ) + 0.5f ; 75 map_y.at<float>(j,i) = 2*( j - src.rows*0.25f ) + 0.5f ; 76 } 77 else 78 { map_x.at<float>(j,i) = 0 ; 79 map_y.at<float>(j,i) = 0 ; 80 } 81 break; 82 case 1: 83 map_x.at<float>(j,i) = (float)i ; 84 map_y.at<float>(j,i) = (float)(src.rows - j) ; 85 break; 86 case 2: 87 map_x.at<float>(j,i) = (float)(src.cols - i) ; 88 map_y.at<float>(j,i) = (float)j ; 89 break; 90 case 3: 91 map_x.at<float>(j,i) = (float)(src.cols - i) ; 92 map_y.at<float>(j,i) = (float)(src.rows - j) ; 93 break; 94 } // end of switch 95 } 96 } 97 inqd++; 98 }