本文转自:http://blog.csdn.net/chenjiazhou12/article/details/21827069
重映射在图像处理中主要的功能为:将一个图像中一个位置的像素放置到另一个图像指定位置的过程,可以根据自己设定的函数将图像进行变换,较常见的功能有关于x轴翻转,关于y轴翻转,关于x、y轴翻转;仿射变换在图像处理中的主要功能为:对图像进行缩放、旋转、平移、扭曲等。
1、原理
从下面三个链接可以详细的了解到重映射和仿射变换的原理
重映射:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/remap/remap.html#remap
仿射变换:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html#warp-affine
学习OpenCV:http://download.csdn.net/detail/chenjiazhou12/7083295
2、代码实现
程序的功能是:生成两个窗口分别显示重映射的结果和仿射变换的结果
重映射窗口上建立了一个滑动条
0表示:显示原图
1表示:图像宽高缩小一半,并显示在中间
2表示:图像上下颠倒
3表示:图像左右颠倒
4表示:同时执行上下和左右的颠倒
仿射变换窗口建立两个滑动条,一个为缩放功能,一个为旋转功能
旋转的角度为-180—180
缩放因子为:0.1-1.0
[cpp] view plain copy print ?
- #include "stdafx.h"
-
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include <iostream>
- #include <stdio.h>
-
- using namespace cv;
-
-
-
- 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;
-
-
- void update_map( void );
- void remapcontrol(int,void*);
- void warprotatecontrol(int,void*);
- void warpaffinecontrol();
-
-
-
-
- int main( int argc, char** argv )
- {
-
- src = imread( "scenery.jpg", 1 );
-
-
-
-
-
- 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;
- }
-
-
-
-
-
- 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<float>(j,i) = i ;
- map_y.at<float>(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<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 2:
- map_x.at<float>(j,i) = i ;
- map_y.at<float>(j,i) = src.rows - j ;
- break;
- case 3:
- map_x.at<float>(j,i) = src.cols - i ;
- map_y.at<float>(j,i) = j ;
- break;
- case 4:
- map_x.at<float>(j,i) = src.cols - i ;
- map_y.at<float>(j,i) = src.rows - j ;
- break;
- }
- }
- }
- remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );
-
-
- 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() );
- };
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
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<float>(j,i) = i ;
map_y.at<float>(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<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 2:
map_x.at<float>(j,i) = i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
case 3:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = j ;
break;
case 4:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(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] view plain copy print ?
- 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 :插值数值
函数操作为:
函数不能in_place操作
getAffineTransform
功能:由三个不共线点计算仿射变换
结构:
[cpp] view plain copy print ?
- Mat getAffineTransform(const Point2f* src, const Point2f* dst)
Mat getAffineTransform(const Point2f* src, const Point2f* dst)
src:输入图像的三角形顶点坐标
dst:输出图像的相应的三角形顶点坐标
函数操作为:
map_matrix为2*3的矩阵
getRotationMatrix2D
功能:计算二维旋转的仿射变换矩阵
结构:
[cpp] view plain copy print ?
- Mat getRotationMatrix2D(Point2f center, double angle, double scale)
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
center:输入图像的旋转中心坐标
angle:旋转角度(度),正值表示逆时针旋转
scale:缩放因子
函数操作为:
warpAffine
功能:对图像做仿射变换
结构:
[cpp] view plain copy print ?
- 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 :插值数值
函数操作为:
函数 WarpAffine 利用下面指定的矩阵变换输入图像:
- 如果没有指定 CV_WARP_INVERSE_MAP , ,
- 否则,
函数不能in_place操作