什么是仿射变换?

  1. 一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移).

  2. 综上所述, 我们能够用仿射变换来表示:

    1. 旋转 (线性变换)
    2. 平移 (向量加)
    3. 缩放操作 (线性变换)

    你现在可以知道, 事实上, 仿射变换代表的是两幅图之间的 关系 .

我们通常使用  矩阵来表示仿射变换.

考虑到我们要使用矩阵  和  对二维向量  做变换, 所以也能表示为下列形式:

如何求怎样才能求得一个仿射变换?

实现代码:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> using namespace cv;
using namespace std; /// 全局变量
char* source_window = "Source image";
char* warp_window = "Warp";
char* warp_rotate_window = "Warp + Rotate"; /** @function main */
int main(int argc, 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("E:\\VS2015Opencv\\vs2015\\project\\picture\\03.jpg", 1); /// 设置目标图像的大小和类型与源图像一致
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()); /** 对图像扭曲后再旋转 */ /// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
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, CV_WINDOW_AUTOSIZE);
imshow(source_window, src); namedWindow(warp_window, CV_WINDOW_AUTOSIZE);
imshow(warp_window, warp_dst); namedWindow(warp_rotate_window, CV_WINDOW_AUTOSIZE);
imshow(warp_rotate_window, warp_rotate_dst); /// 等待用户按任意按键退出程序
waitKey(0); return 0;
}

 结果如下:

代码解析:

仿射变换: 正如上文所说, 我们需要源图像和目标图像上分别一一映射的三个点来定义仿射变换:

/// 设置源图像和目标图像上的三组点以计算仿射变换
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);

我们获得了用以描述仿射变换的  矩阵 (在这里是 warp_mat)

将刚刚求得的仿射变换应用到源图像

warpAffine()函数有以下参数:
  • src: 输入源图像
  • warp_dst: 输出图像
  • warp_mat: 仿射变换矩阵
  • warp_dst.size(): 输出图像的尺寸
/// 对源图像应用上面求得的仿射变换
warpAffine(src, warp_dst, warp_mat, warp_dst.size());

旋转: 想要旋转一幅图像, 你需要两个参数:

  1. 旋转图像所要围绕的中心
  2. 旋转的角度. 在OpenCV中正角度是逆时针的
  3. 可选择: 缩放因子

我们通过下面的代码来定义这些参数:

再利用OpenCV函数 getRotationMatrix2D 来获得旋转矩阵, 这个函数返回一个  矩阵 (这里是 rot_mat)

最后把旋转应用到仿射变换的输出.

/// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
Point center = Point(warp_dst.cols / , warp_dst.rows / );
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());

OpenCV——仿射变换的更多相关文章

  1. 【OpenCV新手教程之十八】OpenCV仿射变换 &amp; SURF特征点描写叙述合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/33320997 作者:毛星云(浅墨)  ...

  2. OpenCV仿射变换+投射变换+单应性矩阵

    本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~ esti ...

  3. opencv 仿射变换 投射变换, 单应性矩阵

    仿射 estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变. getAffineTransform( ...

  4. opencv 仿射变换

    import cv2 as cv import numpy as np img = cv.imread('../images/face.jpg') h, w = img.shape[:2] mat_s ...

  5. 系列文章 -- OpenCV入门教程

     <OpenCV3编程入门>内容简介&勘误&配套源代码下载 [OpenCV入门教程之十八]OpenCV仿射变换 & SURF特征点描述合辑 [OpenCV入门教程之 ...

  6. 目标检测之harr---角点检测harr 的opencv实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...

  7. 【转】【opencv】仿射变换

    仿射变换 目标 在这个教程中你将学习到如何: 使用OpenCV函数 warpAffine 来实现一些简单的重映射. 使用OpenCV函数 getRotationMatrix2D 来获得一个  旋转矩阵 ...

  8. opencv 用户文档 错误更正 仿射变换

    今天在看opencv官方给出的仿射变换计算仿射变换矩阵的文档的时候,发现官方文档中有个很明显的错误,再次给大家提个醒. 官方文档连接: http://opencv.willowgarage.com/d ...

  9. opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移

    常常需要最图像进行仿射变换,仿射变换后,我们可能需要将原来图像中的特征点坐标进行重新计算,获得原来图像中例如眼睛瞳孔坐标的新的位置,用于在新得到图像中继续利用瞳孔位置坐标. 仿射变换在:http:// ...

随机推荐

  1. Aspcms标签大全及常用标签

    相关解释:1.首页指的是index.html文件.列表页一般指newslist.html,productlist.html等文件,该文件对应于后台栏目添加或修改时的列表模板.内页一般指news.htm ...

  2. IDEA如何快速搭建Java开发环境

    作为IntelliJ IDEA mac新手,IDEA如何快速搭建Java开发环境呢?今天小编就给大家带来了IntelliJ IDEA mac使用教程,想知道IDEA如何快速搭建Java开发环境? 全局 ...

  3. javascript 问题汇总(1)

    1    jquery ajax提交有参数的请求,提示错误“Unsupported Media Type“ 解决:ajax 设置添加  contentType: "application/j ...

  4. js微信禁用右上角的分享按钮,和vue中微信页面禁用右上角的分享按钮的问题

    1.隐藏微信网页右上角的按钮 document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { // 通过下面这个 ...

  5. C语言 三目运算

    C语言 三目运算 功能:为真后可根据条件选择成立两个不同的表达式 如果表达式1值为真选择表达式2 如果表达式1值为假选择表达式3 案例 #define _CRT_SECURE_NO_WARNINGS ...

  6. 用texarea存储数据,查询数据库后原样显示在jsp中,包括空格和回车换行

    用texarea存储数据,查询数据库后原样显示在jsp中,包括空格和回车换行

  7. mysql 基础sql语法总结(一)DDL

    mysql数据库: SQL数据库语言可分为四部分: 1.DDL:对数据库或表的进行操作结构操作 2.DML:对表的记录进行更新(增.删.改)* 3.DQL:对表的内容进行查询 **(重难点) 4.DC ...

  8. window - 安装 tomcat

    一.下载安装包 参考网址:https://archive.apache.org/dist/tomcat 百度网盘:https://pan.baidu.com/s/1mtNuTUCFp-_SIHIp_R ...

  9. BZOJ 3143 游走

    Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...

  10. 曼孚科技:数据标注,AI背后的百亿市场

    ​ 1. 两年前,来自山东农村的王磊成为了一位数据标注员.彼时的他,工作内容非常简单且枯燥:识别图片中人的性别. 然而,一段时间之后,他注意到分配给他的任务开始变得越来越复杂:从识别性别到年龄,从框选 ...