Opencv图像处理---仿射变换

理论

  • 任何变换都可以以矩阵乘法(线性变换)的形式表示,然后是矢量加法(平移)。
  • 从上面,我们可以使用仿射变换来表达:
  1. 旋转(线性变换)
  2. 转换(矢量加法)
  3. 比例运算(线性变换)
  • 表示仿射变换的常用方法是使用2×3矩阵。Opencv图像处理---仿射变换_第1张图片

如何得到仿射变换?

  • 我们提到仿射变换基本上是两个图像之间的关系。 关于这种关系的信息大致可以通过两种方式得出:
  1. 我们知道X和T,我们也知道它们是相关的。 然后我们的工作是找到M.
  2. 我们知道M和X.要获得T,我们只需要应用T =M⋅X。 我们对M的信息可以是明确的(即具有2乘3矩阵),或者它可以作为点之间的几何关系。
  • 让我们解释一下(b)。 由于M涉及02图像,我们可以分析两个图像中三个点相关的最简单的情况。 请看下图:
  • 点1,2和3(在图像1中形成三角形)被映射到图像2中,仍然形成三角形,但现在它们已经变得众所周知。 如果我们找到具有这3个点的仿射变换(您可以根据需要选择它们),那么我们可以将这个找到的关系应用于图像中的整个像素。

代码


#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include 
#include 
using namespace cv;
using namespace std;
const char* source_window = "Source image";
const char* warp_window = "Warp";
const char* warp_rotate_window = "Warp + Rotate";
int main( int, char** argv )
{
  Point2f srcTri[3];
  Point2f dstTri[3];
  Mat rot_mat( 2, 3, CV_32FC1 );
  Mat warp_mat( 2, 3, CV_32FC1 );
  Mat src, warp_dst, warp_rotate_dst;
  src = imread( argv[1], 1 );
  warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
  srcTri[0] = Point2f( 0,0 );
  srcTri[1] = Point2f( src.cols - 1.f, 0 );
  srcTri[2] = Point2f( 0, src.rows - 1.f );
  dstTri[0] = Point2f( src.cols*0.0f, src.rows*0.33f );
  dstTri[1] = Point2f( src.cols*0.85f, src.rows*0.25f );
  dstTri[2] = Point2f( src.cols*0.15f, src.rows*0.7f );
  warp_mat = getAffineTransform( srcTri, dstTri );
  warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
  Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
  double angle = -50.0;
  double scale = 0.6;
  rot_mat = getRotationMatrix2D( center, angle, scale );
  warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
  namedWindow( source_window, WINDOW_AUTOSIZE );
  imshow( source_window, src );
  namedWindow( warp_window, WINDOW_AUTOSIZE );
  imshow( warp_window, warp_dst );
  namedWindow( warp_rotate_window, WINDOW_AUTOSIZE );
  imshow( warp_rotate_window, warp_rotate_dst );
  waitKey(0);
  return 0;
}

 

解释

  • 声明我们将使用的一些变量,例如用于存储结果的矩阵和用于存储定义我们的仿射变换的2D点的2个点阵列。
  • 加载图片
  • 将目标图像初始化为与源具有相同的大小和类型:
  • 仿射变换:正如我们在上面解释的那样,我们需要两组3个点来推导仿射变换关系。 看一看:
  • 使用两组点,我们使用OpenCV函数cv :: getAffineTransform计算仿射变换:
  • 我们将刚刚找到的仿射变换应用于src图像

(1)src:输入图像

(2)warp_dst:输出图像

(3)warp_mat:仿射变换

(4)warp_dst.size():输出图像的所需大小

  • 旋转:要旋转图像,我们需要知道两件事:
  1. 图像将旋转的中心
  2. 要旋转的角度。 在OpenCV中,正角度是逆时针的
  3. 可选:比例因子
  • 我们使用OpenCV函数cv :: getRotationMatrix2D生成旋转矩阵,它返回一个2×3矩阵.
  • 我们现在将找到的旋转应用于我们之前的Transformation的输出。
  • 最后,我们将结果显示在两个窗口加上原始图像中以获得良好的衡量标准:Opencv图像处理---仿射变换_第2张图片
  • 我们只需要等到用户退出程序

效果

  • 在编译上面的代码之后,我们可以给它一个图像的路径作为参数。 例如,对于像这样的图片:Opencv图像处理---仿射变换_第3张图片
  • 在应用第一个仿射变换后,我们获得:Opencv图像处理---仿射变换_第4张图片
  • 最后,在应用负旋转(记住负方向顺时针)和比例因子后,我们得到:Opencv图像处理---仿射变换_第5张图片

你可能感兴趣的:(OpenCV教程)