如何使用OpenCV函数 remap 来实现简单重映射
来源:互联网 发布:ledrom编辑软件 编辑:程序博客网 时间:2024/05/01 16:54
Remapping 重映射¶
目标¶
本教程向你展示如何使用OpenCV函数 remap 来实现简单重映射.
理论¶
重映射是什么意思?¶
把一个图像中一个位置的像素放置到另一个图片指定位置的过程.
为了完成映射过程, 有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标不是一一对应的.
我们通过重映射来表达每个像素的位置 :
这里 是目标图像, 是源图像, 是作用于 的映射方法函数.
让我们来思考一个快速的例子. 想象一下我们有一个图像 , 我们想满足下面的条件作重映射:
会发生什么? 图像会按照 轴方向发生翻转. 例如, 源图像如下:
看到红色圈关于 x 的位置改变( 轴水平翻转):
通过 OpenCV 的函数 remap 提供一个简单的重映射实现.
代码¶
- 本程序做什么?
- 装载一幅图像.
- 程序按秒循环, 在一个窗口中顺序出现4种重映射过程对相同的图像.
- 等待用户按 ‘ESC’ 键退出程序。
- 下面是本教程代码. 你也可以从 这里 下载。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace cv; /// Global variables Mat src, dst; Mat map_x, map_y; char* remap_window = "Remap demo"; int ind = 0; /// Function Headers void update_map( void ); /** * @function main */ int main( int argc, char** argv ) { /// Load the image src = imread( argv[1], 1 ); /// Create dst, map_x and map_y with the same size as src: dst.create( src.size(), src.type() ); map_x.create( src.size(), CV_32FC1 ); map_y.create( src.size(), CV_32FC1 ); /// Create window namedWindow( remap_window, CV_WINDOW_AUTOSIZE ); /// Loop while( true ) { /// Each 1 sec. Press ESC to exit the program int c = waitKey( 1000 ); if( (char)c == 27 ) { break; } /// Update map_x & map_y. Then apply remap update_map(); remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) ); /// Display results imshow( remap_window, dst ); } return 0; } /** * @function update_map * @brief Fill the map_x and map_y matrices with 4 types of mappings */ 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.25 ) + 0.5 ; map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ; } else { map_x.at<float>(j,i) = 0 ; map_y.at<float>(j,i) = 0 ; } break; case 1: map_x.at<float>(j,i) = i ; map_y.at<float>(j,i) = src.rows - j ; break; case 2: map_x.at<float>(j,i) = src.cols - i ; map_y.at<float>(j,i) = j ; break; case 3: map_x.at<float>(j,i) = src.cols - i ; map_y.at<float>(j,i) = src.rows - j ; break; } // end of switch } } ind++;}
说明¶
首先准备程序用到的变量:
Mat src, dst;Mat map_x, map_y;char* remap_window = "Remap demo";int ind = 0;
加载一幅图像:
src = imread( argv[1], 1 );
创建目标图像和两个映射矩阵.( x 和 y )
dst.create( src.size(), src.type() );map_x.create( src.size(), CV_32FC1 );map_y.create( src.size(), CV_32FC1 );
创建一个窗口用于展示结果.
namedWindow( remap_window, CV_WINDOW_AUTOSIZE );
建立一个间隔1000毫秒的循环,每次循环执行更新映射矩阵参数并对源图像进行重映射处理(使用 mat_x 和 mat_y),然后把更新后的目标图像显示出来:
while( true ){ /// Each 1 sec. Press ESC to exit the program int c = waitKey( 1000 ); if( (char)c == 27 ) { break; } /// Update map_x & map_y. Then apply remap update_map(); remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) ); /// Display results imshow( remap_window, dst );}
上面用到的重映射函数 remap. 参数说明:
- src: 源图像
- dst: 目标图像,与 src 相同大小
- map_x: x方向的映射参数. 它相当于方法 的第一个参数
- map_y: y方向的映射参数. 注意 map_y 和 map_x 与 src 的大小一致。
- CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值).
- BORDER_CONSTANT: 默认
如何更新重映射矩阵 mat_x 和 mat_y? 请继续看:
更新重映射矩阵: 我们将分别使用4种不同的映射:
图像宽高缩小一半,并显示在中间:
所有成对的参数 处理后都符合: 和
图像上下颠倒:
图像左右颠倒:
同时执行b和c的操作:
下面的代码片段说明上述的映射过程. 在这里 map_x 代表第一个坐标 h(i,j) , map_y 是第二个坐标.
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.25 ) + 0.5 ; map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ; } else { map_x.at<float>(j,i) = 0 ; map_y.at<float>(j,i) = 0 ; } break; case 1: map_x.at<float>(j,i) = i ; map_y.at<float>(j,i) = src.rows - j ; break; case 2: map_x.at<float>(j,i) = src.cols - i ; map_y.at<float>(j,i) = j ; break; case 3: map_x.at<float>(j,i) = src.cols - i ; map_y.at<float>(j,i) = src.rows - j ; break; } // end of switch } } ind++;}
结果¶
上面的代码编译后, 运行时给一个图片路径参数. 例如,使用下面的图片:
图像宽高缩小一半,并显示在中间:
图像上下颠倒:
图像左右颠倒:
两个方向同时颠倒:
翻译者¶
opencvzy@ OpenCV中文网站 <java5100@gmail.com>
Help and Feedback
You did not find what you were looking for?- Ask a question in the user group/mailing list.
- If you think something is missing or wrong in the documentation, please file abug report.
- 如何使用OpenCV函数 remap 来实现简单重映射
- 如何使用OpenCV函数 remap 来实现简单重映射
- opencv重映射remap( )函数
- OpenCV:remap()简单重映射
- 转 OpenCV:remap()简单重映射
- opencv中的重映射:remap()函数
- opencv3实现重映射-remap函数
- Android Jni opencv中的重映射:remap()函数
- 【opencv练习25 - remap重映射】
- opencv学习(三十四)之重映射remap
- Opencv 中重映射的remap函数中map_x,map_y的困惑说明
- OpenCV代码提取:remap函数的实现
- OpenCV代码提取:remap函数的实现
- 重映射和仿射(remap函数)
- chapter14_4重映射—remap()
- opencv Remap 图像的映射
- 重映射函数remap的使用,以图像在x和y方向的翻转为例!
- STM32 复用 与 重映射(USART Remap)
- Android中的Web Service学习(一)——Web Service介绍
- maven工程引用仓库中没有的包
- Java集合Map<K,V>,HashMap<K,V>的使用,for循环正解
- Layer2交换机QinQ和VTP
- Hibernate 笔记(2)-封装HibernateSessionFactory
- 如何使用OpenCV函数 remap 来实现简单重映射
- js实现表格添加数据
- 把过程与函数说透
- Windows安装WAMP详细教程
- sublime text3打开文件,中文乱码问题解决办法
- javax.servlet.*需要的两个包
- hdu 3866 Moonfang's Birthday 排序?贪心?二分?思维?
- 程序包的创建与应用
- iOS---NSNotification通知