博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
重映射和仿射(remap函数)
阅读量:4158 次
发布时间:2019-05-26

本文共 9338 字,大约阅读时间需要 31 分钟。



本文转自:

重映射在图像处理中主要的功能为:将一个图像中一个位置的像素放置到另一个图像指定位置的过程,可以根据自己设定的函数将图像进行变换,较常见的功能有关于x轴翻转,关于y轴翻转,关于x、y轴翻转;仿射变换在图像处理中的主要功能为:对图像进行缩放、旋转、平移、扭曲等。

1、原理

从下面三个链接可以详细的了解到重映射和仿射变换的原理

重映射:

仿射变换:

学习OpenCV:

2、代码实现

程序的功能是:生成两个窗口分别显示重映射的结果和仿射变换的结果

重映射窗口上建立了一个滑动条

0表示:显示原图

1表示:图像宽高缩小一半,并显示在中间

2表示:图像上下颠倒

3表示:图像左右颠倒

4表示:同时执行上下和左右的颠倒

仿射变换窗口建立两个滑动条,一个为缩放功能,一个为旋转功能

旋转的角度为-180—180

缩放因子为:0.1-1.0

[cpp]
  1. #include "stdafx.h"  
  2.   
  3.  #include "opencv2/highgui/highgui.hpp"  
  4.  #include "opencv2/imgproc/imgproc.hpp"  
  5.  #include <iostream>  
  6.  #include <stdio.h>  
  7.   
  8.  using namespace cv;  
  9.   
  10.   
  11.  /// Global variables  
  12.  Mat src;  
  13.  Mat warp_dst;  
  14.  const char* remaptrackbarname="remapvalue";  
  15.  const char* warprotatetrackbarname="warprotatevalue";  
  16.  const char* warpscaletrackbarname="warpscalevalue";  
  17.  const char* remap_window = "Remap demo";  
  18.  const char* warprotate_window="warprotate demo";  
  19.  const int remapmaxcount=4,warprotatemaxcount=360,warpscalemaxcount=10;  
  20.  int remapvalue,warprotatevalue=180, warpscalevalue=10;  
  21.   
  22.  /// Function Headers  
  23.  void update_map( void );  
  24.  void remapcontrol(int,void*);  
  25.  void warprotatecontrol(int,void*);  
  26.  void warpaffinecontrol();  
  27.   
  28.  /** 
  29.  * @function main 
  30.  */  
  31.  int main( int argc, char** argv )  
  32.  {  
  33.    /// Load the image  
  34.    src = imread( "scenery.jpg", 1 );  
  35.   
  36.   /// Create dst, map_x and map_y with the same size as src:  
  37.   
  38.   
  39.   /// Create window  
  40.   namedWindow( remap_window, CV_WINDOW_AUTOSIZE );  
  41.   namedWindow(warprotate_window,CV_WINDOW_AUTOSIZE);  
  42.   createTrackbar(remaptrackbarname,remap_window,&remapvalue,remapmaxcount,remapcontrol);  
  43.   createTrackbar(warprotatetrackbarname,warprotate_window,&warprotatevalue,warprotatemaxcount,warprotatecontrol);  
  44.   createTrackbar(warpscaletrackbarname,warprotate_window,&warpscalevalue,warpscalemaxcount,warprotatecontrol);   
  45.   remapcontrol(0,0);  
  46.   warpaffinecontrol();  
  47.   warprotatecontrol(0,0);  
  48.   waitKey();  
  49.   
  50.   return 0;  
  51.  }  
  52.   
  53.  /** 
  54.  * @function update_map 
  55.  * @brief Fill the map_x and map_y matrices with 4 types of mappings 
  56.  */  
  57.   void remapcontrol(int,void*)  
  58.   {  
  59.       Mat  dst, map_x, map_y;   
  60.       dst.create( src.size(), src.type() );  
  61.       map_x.create( src.size(), CV_32FC1 );  
  62.       map_y.create( src.size(), CV_32FC1 );  
  63.       forint j = 0; j < src.rows; j++ )  
  64.       { forint i = 0; i < src.cols; i++ )  
  65.       {  
  66.           switch( remapvalue )  
  67.           {  
  68.           case 0:               
  69.               map_x.at<float>(j,i) = i ;  
  70.               map_y.at<float>(j,i) = j ;  
  71.               break;  
  72.   
  73.           case 1:  
  74.               if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )  
  75.               {  
  76.                   map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;  
  77.                   map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;  
  78.               }  
  79.               else  
  80.               { map_x.at<float>(j,i) = 0 ;  
  81.               map_y.at<float>(j,i) = 0 ;  
  82.               }  
  83.               break;  
  84.           case 2:  
  85.               map_x.at<float>(j,i) = i ;  
  86.               map_y.at<float>(j,i) = src.rows - j ;  
  87.               break;  
  88.           case 3:  
  89.               map_x.at<float>(j,i) = src.cols - i ;  
  90.               map_y.at<float>(j,i) = j ;  
  91.               break;  
  92.           case 4:  
  93.               map_x.at<float>(j,i) = src.cols - i ;  
  94.               map_y.at<float>(j,i) = src.rows - j ;  
  95.               break;  
  96.           } // end of switch  
  97.       }  
  98.       }  
  99.       remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );  
  100.   
  101.       /// Display results  
  102.       imshow( remap_window, dst );  
  103.   }  
  104.   void warprotatecontrol(int,void*)  
  105.   {  
  106.       Mat warp_rotate_dst;  
  107.       Mat rot_mat( 2, 3, CV_32FC1 );  
  108.       Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );  
  109.       double angle =warprotatevalue-180;  
  110.       double scale =double(warpscalevalue)/10;  
  111.       printf("%f\n",scale);  
  112.       /// 通过上面的旋转细节信息求得旋转矩阵  
  113.       rot_mat = getRotationMatrix2D( center, angle, scale );  
  114.   
  115.       /// 旋转已扭曲图像  
  116.       warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );  
  117.       imshow(warprotate_window,warp_rotate_dst);  
  118.   }  
  119.    void warpaffinecontrol()  
  120.     {  
  121.         Point2f srcTri[3];  
  122.         Point2f dstTri[3];  
  123.         Mat warp_mat( 2, 3, CV_32FC1 );  
  124.         warp_dst = Mat::zeros( src.rows, src.cols, src.type() );  
  125.   
  126.         srcTri[0] = Point2f( 0,0 );  
  127.         srcTri[1] = Point2f( src.cols - 1, 0 );  
  128.         srcTri[2] = Point2f( 0, src.rows - 1 );  
  129.   
  130.         dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );  
  131.         dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );  
  132.         dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );  
  133.         warp_mat = getAffineTransform( srcTri, dstTri );  
  134.         warpAffine( src, warp_dst, warp_mat, warp_dst.size() );  
  135.     };  
#include "stdafx.h" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include 
#include
using namespace cv; /// Global variables Mat src; Mat warp_dst; const char* remaptrackbarname="remapvalue"; const char* warprotatetrackbarname="warprotatevalue"; const char* warpscaletrackbarname="warpscalevalue"; const char* remap_window = "Remap demo"; const char* warprotate_window="warprotate demo"; const int remapmaxcount=4,warprotatemaxcount=360,warpscalemaxcount=10; int remapvalue,warprotatevalue=180, warpscalevalue=10; /// Function Headers void update_map( void ); void remapcontrol(int,void*); void warprotatecontrol(int,void*); void warpaffinecontrol(); /** * @function main */ int main( int argc, char** argv ) { /// Load the image src = imread( "scenery.jpg", 1 ); /// Create dst, map_x and map_y with the same size as src: /// Create window namedWindow( remap_window, CV_WINDOW_AUTOSIZE ); namedWindow(warprotate_window,CV_WINDOW_AUTOSIZE); createTrackbar(remaptrackbarname,remap_window,&remapvalue,remapmaxcount,remapcontrol); createTrackbar(warprotatetrackbarname,warprotate_window,&warprotatevalue,warprotatemaxcount,warprotatecontrol); createTrackbar(warpscaletrackbarname,warprotate_window,&warpscalevalue,warpscalemaxcount,warprotatecontrol); remapcontrol(0,0); warpaffinecontrol(); warprotatecontrol(0,0); waitKey(); return 0; } /** * @function update_map * @brief Fill the map_x and map_y matrices with 4 types of mappings */ void remapcontrol(int,void*) { Mat dst, map_x, map_y; dst.create( src.size(), src.type() ); map_x.create( src.size(), CV_32FC1 ); map_y.create( src.size(), CV_32FC1 ); for( int j = 0; j < src.rows; j++ ) { for( int i = 0; i < src.cols; i++ ) { switch( remapvalue ) { case 0: map_x.at
(j,i) = i ; map_y.at
(j,i) = j ; break; case 1: if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 ) { map_x.at
(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ; map_y.at
(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ; } else { map_x.at
(j,i) = 0 ; map_y.at
(j,i) = 0 ; } break; case 2: map_x.at
(j,i) = i ; map_y.at
(j,i) = src.rows - j ; break; case 3: map_x.at
(j,i) = src.cols - i ; map_y.at
(j,i) = j ; break; case 4: map_x.at
(j,i) = src.cols - i ; map_y.at
(j,i) = src.rows - j ; break; } // end of switch } } remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) ); /// Display results imshow( remap_window, dst ); } void warprotatecontrol(int,void*) { Mat warp_rotate_dst; Mat rot_mat( 2, 3, CV_32FC1 ); Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); double angle =warprotatevalue-180; double scale =double(warpscalevalue)/10; printf("%f\n",scale); /// 通过上面的旋转细节信息求得旋转矩阵 rot_mat = getRotationMatrix2D( center, angle, scale ); /// 旋转已扭曲图像 warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() ); imshow(warprotate_window,warp_rotate_dst); } void warpaffinecontrol() { Point2f srcTri[3]; Point2f dstTri[3]; Mat warp_mat( 2, 3, CV_32FC1 ); warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); srcTri[0] = Point2f( 0,0 ); srcTri[1] = Point2f( src.cols - 1, 0 ); srcTri[2] = Point2f( 0, src.rows - 1 ); dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 ); dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 ); dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 ); warp_mat = getAffineTransform( srcTri, dstTri ); warpAffine( src, warp_dst, warp_mat, warp_dst.size() ); };

3、运行结果

                                                 

                                                                                图1、原图                                                                    

 

                图2、图像宽高缩小一半                                       图3、  图像上下颠倒   

        

                         图4、图像左右颠倒                                       图5、图像上下左右颠倒

 

                     图6、图像旋转                                                       图7、图像缩小

                 图8、图像仿射

4、用到的类和函数

remap

功能:对图像进行普通几何变换

结构:

[cpp]
  1. void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())  
void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
src :源图像
dst :目标图像,和map1有同样的size,和src有同样的type
map1 :(x,y)点坐标或者
x坐标,可以是CV_16SC2 , CV_32FC1 , 或者 CV_32FC2类型
map2 :y坐标,可以是 CV_16UC1 , CV_32FC1 类型,如果map1为(x,y)点,map2可以不用
interpolation :插值方法
borderMode:边界插值类型
borderValue :插值数值

函数操作为:

\texttt{dst} (x,y) =  \texttt{src} (map_x(x,y),map_y(x,y))

函数不能in_place操作

getAffineTransform

功能:由三个不共线点计算仿射变换

结构:

[cpp]
  1. Mat getAffineTransform(const Point2f* src, const Point2f* dst)  
Mat getAffineTransform(const Point2f* src, const Point2f* dst)
src:输入图像的三角形顶点坐标

dst:输出图像的相应的三角形顶点坐标

函数操作为:

\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}  map_matrix为2*3的矩阵

 dst(i)=(x'_i,y'_i),src(i)=(x_i, y_i),i=0,1,2

getRotationMatrix2D

功能:计算二维旋转的仿射变换矩阵

结构:

[cpp]
  1. Mat getRotationMatrix2D(Point2f center, double angle, double scale)  
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
center:输入图像的旋转中心坐标

angle:旋转角度(度),正值表示逆时针旋转

scale:缩放因子

函数操作为:

\begin{bmatrix} \alpha &  \beta & (1- \alpha )  \cdot \texttt{center.x} -  \beta \cdot \texttt{center.y} \\ - \beta &  \alpha &  \beta \cdot \texttt{center.x} + (1- \alpha )  \cdot \texttt{center.y} \end{bmatrix}

\begin{array}{l} \alpha =  \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta =  \texttt{scale} \cdot \sin \texttt{angle} \end{array}

warpAffine

功能:对图像做仿射变换

结构:

[cpp]
  1. void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())  
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
src:源图像
dst :目标图像,和src有同样的size和type
M :2×3 变换矩阵
dsize :目标图像的size
flags :
插值方法和以下开关选项的组合:

  • CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
  • CV_WARP_INVERSE_MAP - 指定 map_matrix 是输出图像到输入图像的反变换,因此可以直接用来做象素插值。否则, 函数从 map_matrix 得到反变换。
borderMode :插值类型
borderValue :插值数值

函数操作为:

\texttt{dst} (x,y) =  \texttt{src} ( \texttt{M} _{11} x +  \texttt{M} _{12} y +  \texttt{M} _{13}, \texttt{M} _{21} x +  \texttt{M} _{22} y +  \texttt{M} _{23})

函数 WarpAffine 利用下面指定的矩阵变换输入图像: dst(x',y') \leftarrow src(x,y)

  • 如果没有指定 CV_WARP_INVERSE_MAP , (x',y')^T=map\_matrix \cdot (x,y,1)^T ,
  • 否则,(x, y)^T=map\_matrix \cdot (x',y',1)^T

函数不能in_place操作

你可能感兴趣的文章
数学等于号是=那三个横杠是什么符
查看>>
HTTP协议详解
查看>>
java多线程中的join方法详解
查看>>
ECLIPSE远程调试出现如下问题 ECLIPSE中调试代码提示找不到源
查看>>
java abstract修饰符
查看>>
数组分为两部分,使得其和相差最小
查看>>
有趣的排序——百度2017春招
查看>>
二叉树的最近公共祖先LCA
查看>>
数组中累加和为定值K的最长子数组长度
查看>>
素数对--腾讯2017校招编程
查看>>
JAVA集合--ArrayList实现原理
查看>>
synchronized与Lock
查看>>
数据库索引
查看>>
实现包含min,max,push,pop函数的栈
查看>>
实验2-6 字符型数据的输入输出
查看>>
实验3-5 编程初步
查看>>
实验4-1 逻辑量的编码和关系操作符
查看>>
实验5-2 for循环结构
查看>>
实验5-3 break语句和continue语句
查看>>
实验5-4 循环的嵌套
查看>>