如何使用OpenCV函数 remap 来实现简单重映射
来源:互联网 发布:pandorabox安装python 编辑:程序博客网 时间:2024/05/01 09:45
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/gpu/gpu.hpp"
#include <math.h>
#ifndef _DEBUG
#pragma comment(lib,"IlmImf.lib")
#pragma comment(lib,"libjasper.lib")
#pragma comment(lib,"libjpeg.lib")
#pragma comment(lib,"libpng.lib")
#pragma comment(lib,"libtiff.lib")
#pragma comment(lib,"zlib.lib")
#pragma comment(lib,"opencv_calib3d2411.lib")
#pragma comment(lib,"opencv_contrib2411.lib")
#pragma comment(lib,"opencv_core2411.lib")
#pragma comment(lib,"opencv_features2d2411.lib")
#pragma comment(lib,"opencv_flann2411.lib")
#pragma comment(lib,"opencv_gpu2411.lib")
#pragma comment(lib,"opencv_highgui2411.lib")
#pragma comment(lib,"opencv_imgproc2411.lib")
#pragma comment(lib,"opencv_legacy2411.lib")
#pragma comment(lib,"opencv_ml2411.lib")
#pragma comment(lib,"opencv_nonfree2411.lib")
#pragma comment(lib,"opencv_objdetect2411.lib")
#pragma comment(lib,"opencv_ocl2411.lib")
#pragma comment(lib,"opencv_photo2411.lib")
#pragma comment(lib,"opencv_stitching2411.lib")
#pragma comment(lib,"opencv_superres2411.lib")
#pragma comment(lib,"opencv_ts2411.lib")
#pragma comment(lib,"opencv_video2411.lib")
#pragma comment(lib,"opencv_videostab2411.lib")
#else
#pragma comment(lib,"zlibd.lib")
#pragma comment(lib,"IlmImfd.lib")
#pragma comment(lib,"libjasperd.lib")
#pragma comment(lib,"libjpegd.lib")
#pragma comment(lib,"libpngd.lib")
#pragma comment(lib,"libtiffd.lib")
#pragma comment(lib,"opencv_calib3d2411d.lib")
#pragma comment(lib,"opencv_contrib2411d.lib")
#pragma comment(lib,"opencv_core2411d.lib")
#pragma comment(lib,"opencv_features2d2411d.lib")
#pragma comment(lib,"opencv_flann2411d.lib")
#pragma comment(lib,"opencv_gpu2411d.lib")
#pragma comment(lib,"opencv_highgui2411d.lib")
#pragma comment(lib,"opencv_imgproc2411d.lib")
#pragma comment(lib,"opencv_legacy2411d.lib")
#pragma comment(lib,"opencv_ml2411d.lib")
#pragma comment(lib,"opencv_nonfree2411d.lib")
#pragma comment(lib,"opencv_objdetect2411d.lib")
#pragma comment(lib,"opencv_ocl2411d.lib")
#pragma comment(lib,"opencv_photo2411d.lib")
#pragma comment(lib,"opencv_stitching2411d.lib")
#pragma comment(lib,"opencv_superres2411d.lib")
#pragma comment(lib,"opencv_ts2411d.lib")
#pragma comment(lib,"opencv_video2411d.lib")
#pragma comment(lib,"opencv_videostab2411d.lib")
#endif
using namespace cv;
// remapping an image by creating wave effects
void wave(const cv::Mat &image, cv::Mat &result) {
// the map functions
cv::Mat srcX(image.rows,image.cols,CV_32F); // x-map
cv::Mat srcY(image.rows,image.cols,CV_32F); // y-map
// creating the mapping
for (int i=0; i<image.rows; i++) {
for (int j=0; j<image.cols; j++) {
srcX.at<float>(i,j)= j;
srcY.at<float>(i,j)= i+3*sin(j/6.0);
// horizontal flipping
// srcX.at<float>(i,j)= image.cols-j-1;
// srcY.at<float>(i,j)= i;
}
}
// applying the mapping
remap(image, // source image
result, // destination image
srcX, // x map
srcY, // y map
INTER_LINEAR); // interpolation method
}
int main()
{
cv::Mat image= cv::imread("boldt.jpg",0);
// image is resize for book printing
cv::resize(image, image, cv::Size(), 0.6, 0.6);
cv::namedWindow("Image");
cv::imshow("Image",image);
cv::Mat result;
wave(image,result);
cv::namedWindow("Remapped image");
cv::imshow("Remapped image",result);
cv::waitKey();
return 0;
}
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>
- 如何使用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)
- iOS开发中的两种消息通知机制详解
- Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图
- win7 chrome使用蓝屏的一个解决办法
- ubuntu12.04 minicom 搭建方法总结
- 五句话搞定JavaScript作用域
- 如何使用OpenCV函数 remap 来实现简单重映射
- CodeForces 342A Xenia and Divisors
- VB学习笔记(持续更新)
- Jquery遮罩层实现代码
- 立即执行函数,声明式函数
- [Cloud Computing]Mechanisms: Cloud Workload Scheduler
- 智能科普:VR、AR、MR的区别
- 关于Activity生命周期的一些小总结
- Enigma机密码加密解密的实现