Goal
In this tutorial you will learn how to:
a. Use the OpenCV function cv::remap to implement simple remapping routines.
a.使用OpenCV函数cv::remap进行图像的重映射。
Theory
What is remapping?
It is the process of taking pixels from one place in the image and locating them in another position in a new image.
把图像中的一个像素定位到新的图像中的另外一个位置。
To accomplish the mapping process, it might be necessary to do some interpolation for non-integer pixel locations, since there will not always be a one-to-one-pixel correspondence between source and destination images.
为了完成映射过程,可能需要非整数的像素位置进行插值,由于源图像和目标图像可能不是一一对应的关系。
We can express the remap for every pixel location (x,y) as:
g(x,y)=f(h(x,y))
where g() is the remapped image, f() the source image and h(x,y) is the mapping function that operates on (x,y).
g()是映射后的图像,f()是原图像,h(x,y)是映射变换函数。
Let's think in a quick example. Imagine that we have an image I and, say, we want to do a remap such that:
What would happen? It is easily seen that the image would flip in the x direction. For instance, consider the input image:
可以轻易的看处理,图像在X方向进行了对调。
observe how the red circle changes positions with respect to x (considering x the horizontal direction):
- In OpenCV, the function cv::map offers a simple remapping implementation.
- 在OpenCV中,函数:cv::map可以实现这个功能。
Code
- What does this program do?
- Loads an image(加载图像)
- Each second, apply 1 of 4 different remapping processes to the image and display them indefinitely in a window.(没过1秒,进行四种重映射过程)
- Wait for the user to exit the program(等待用户退出)
- The tutorial code's is shown lines below. You can also download it from here
Code
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
Mat src, dst;
Mat map_x, map_y;
const char* remap_window = "Remap demo";
int ind = 0;
void update_map( void );
int main(int argc, const char** argv)
{
CommandLineParser parser(argc, argv, "{@image |lena.jpg|input image name}");
std::string filename = parser.get<std::string>(0);
src = imread( filename, IMREAD_COLOR );
dst.create( src.size(), src.type() );
map_x.create( src.size(), CV_32FC1 );//CV_32FC1因为就一个数据。
map_y.create( src.size(), CV_32FC1 );//CV_32FC1因为就一个数据。
namedWindow( remap_window, WINDOW_AUTOSIZE );
for(;;)
{
char c = (char)waitKey( 1000 );
if( c == 27 )
{ break; }
update_map();//更新映射函数
remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
//输入,输出,X方向上的映射函数,Y方向上的映射函数,插值类型,边框,值
// Display results
imshow( remap_window, dst );
}
return 0;
}
void update_map( void )
{
ind = ind%4;
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{
switch( ind )
{
case 0:
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
map_x.at<float>(j,i) = 2*( i - src.cols*0.25f ) + 0.5f ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25f ) + 0.5f ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
break;
case 1:
map_x.at<float>(j,i) = (float)i ;
map_y.at<float>(j,i) = (float)(src.rows - j) ;
break;
case 2:
map_x.at<float>(j,i) = (float)(src.cols - i) ;
map_y.at<float>(j,i) = (float)j ;
break;
case 3:
map_x.at<float>(j,i) = (float)(src.cols - i) ;
map_y.at<float>(j,i) = (float)(src.rows - j) ;
break;
} // end of switch
}
}
ind++;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin