赞
踩
在本教程中,您将学习如何:
一个。使用 OpenCV 函数 cv::remap 实现简单的重新映射例程。
我们可以表示每个像素位置的重新映射(x,y)如:
哪里g()是重新映射的图像,f()源图像和ℎ(x,y)是操作的映射函数(x,y).
让我们举个简单的例子。想象一下,我们有一个图像我而且,比如说,我们想做一个重新映射,以便:
会发生什么?很容易看出,图像会在x方向。例如,考虑输入图像:
观察红色圆圈相对于 x 如何改变位置(考虑到x水平方向):
-
- #include "opencv2/imgcodecs.hpp"
- #include "opencv2/highgui.hpp"
- #include "opencv2/imgproc.hpp"
- #include <iostream>
-
- using namespace cv;
-
- void update_map( int &ind, Mat &map_x, Mat &map_y );
-
- int main(int argc, const char** argv)
- {
- CommandLineParser parser(argc, argv, "{@image |chicky_512.png|input image name}");
- std::string filename = parser.get<std::string>(0);
- Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );
- if (src.empty())
- {
- std::cout << "Cannot read image: " << filename << std::endl;
- return -1;
- }
-
- Mat dst(src.size(), src.type());
- Mat map_x(src.size(), CV_32FC1);
- Mat map_y(src.size(), CV_32FC1);
-
- const char* remap_window = "Remap demo";
- namedWindow( remap_window, WINDOW_AUTOSIZE );
-
- int ind = 0;
- for(;;)
- {
- update_map(ind, map_x, map_y);
- remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
-
- imshow( remap_window, dst );
-
- char c = (char)waitKey( 1000 );
- if( c == 27 )
- {
- break;
- }
- }
- return 0;
- }
-
- void update_map( int &ind, Mat &map_x, Mat &map_y )
- {
- for( int i = 0; i < map_x.rows; i++ )
- {
- for( int j = 0; j < map_x.cols; j++ )
- {
- switch( ind )
- {
- case 0:
- if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 )
- {
- map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;
- map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;
- }
- else
- {
- map_x.at<float>(i, j) = 0;
- map_y.at<float>(i, j) = 0;
- }
- break;
- case 1:
- map_x.at<float>(i, j) = (float)j;
- map_y.at<float>(i, j) = (float)(map_x.rows - i);
- break;
- case 2:
- map_x.at<float>(i, j) = (float)(map_x.cols - j);
- map_y.at<float>(i, j) = (float)i;
- break;
- case 3:
- map_x.at<float>(i, j) = (float)(map_x.cols - j);
- map_y.at<float>(i, j) = (float)(map_x.rows - i);
- break;
- default:
- break;
- } // end of switch
- }
- }
- ind = (ind+1) % 4;
- }

加载图像
-
- Mat src = imread( samples::findFile( filename ), IMREAD_COLOR );
- if (src.empty())
- {
- std::cout << "Cannot read image: " << filename << std::endl;
- return -1;
- }
创建目标映像和两个映射矩阵(对于 x 和 y )
- Mat dst(src.size(), src.type());
- Mat map_x(src.size(), CV_32FC1);
- Mat map_y(src.size(), CV_32FC1);
创建一个窗口以显示结果
- const char* remap_window = "Remap demo";
- namedWindow( remap_window, WINDOW_AUTOSIZE );
建立循环。每隔 1000 毫秒,我们就会更新映射矩阵(mat_x 和 mat_y),并将它们应用于我们的源图像:
- int ind = 0;
- for(;;)
- {
- update_map(ind, map_x, map_y);
- remap( src, dst, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
-
- imshow( remap_window, dst );
-
- char c = (char)waitKey( 1000 );
- if( c == 27 )
- {
- break;
- }
- }
- void update_map( int &ind, Mat &map_x, Mat &map_y )
- {
- for( int i = 0; i < map_x.rows; i++ )
- {
- for( int j = 0; j < map_x.cols; j++ )
- {
- switch( ind )
- {
- case 0:
- if( j > map_x.cols*0.25 && j < map_x.cols*0.75 && i > map_x.rows*0.25 && i < map_x.rows*0.75 )
- {
- map_x.at<float>(i, j) = 2*( j - map_x.cols*0.25f ) + 0.5f;
- map_y.at<float>(i, j) = 2*( i - map_x.rows*0.25f ) + 0.5f;
- }
- else
- {
- map_x.at<float>(i, j) = 0;
- map_y.at<float>(i, j) = 0;
- }
- break;
- case 1:
- map_x.at<float>(i, j) = (float)j;
- map_y.at<float>(i, j) = (float)(map_x.rows - i);
- break;
- case 2:
- map_x.at<float>(i, j) = (float)(map_x.cols - j);
- map_y.at<float>(i, j) = (float)i;
- break;
- case 3:
- map_x.at<float>(i, j) = (float)(map_x.cols - j);
- map_y.at<float>(i, j) = (float)(map_x.rows - i);
- break;
- default:
- break;
- } // end of switch
- }
- }
- ind = (ind+1) % 4;
- }

参考文献:
1、《Remapping》------Ana Huamán
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。