第六章 - 图像变换 - 图像拉伸、收缩、扭曲、旋转[1] - 仿射变换(cvWarpAffine)
拉伸、收缩、扭曲、旋转是图像的几何变换,在三维视觉技术中大量应用到这些变换,又分为仿射变换和透视变换。仿射变换通常用单应性建模,利用cvWarpAffine解决密集映射,用cvTransform解决稀疏映射。仿射变换可以将矩形转换成平行四边形,它可以将矩形的边压扁但必须保持边是平行的,也可以将矩形旋转或者按比例变化。透视变换提供了更大的灵活性,一个透视变换可以将矩阵转变成梯形。当然,平行四边形也是梯形,所以仿射变换是透视变换的子集。
本小节实现图像的仿射变换。
------------------------------------------------------------------------------------
以下是本例程用到的方法:
CloneImage
制作图像的完整拷贝
IplImage* cvCloneImage(
const IplImage* image );
image
原图像.
函数 cvCloneImage
制作图像的完整拷贝包括头、ROI和数据
-----------------------------
GetAffineTransform
由三对点计算仿射变换
CvMat* cvGetAffineTransform( const CvPoint2D32f* src,const
CvPoint2D32f* dst, CvMat* map_matrix );
src
输入图像的三角形顶点坐标。
dst
输出图像的相应的三角形顶点坐标。
map_matrix
指向2×3输出矩阵的指针。
函数cvGetAffineTransform计算满足以下关系的仿射变换矩阵:

这里,dst(i)=
(x'i,y'i),src(i)=
(xi,yi),i = 0..2.
-----------------------------
WarpAffine
对图像做仿射变换
void cvWarpAffine( const CvArr* src, CvArr* dst, constCvMat*
map_matrix,
int
flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
CvScalar fillval=cvScalarAll(0) );
src
输入图像.
dst
输出图像.
map_matrix
2×3 变换矩阵
flags
插值方法和以下开关选项的组合:
· CV_WARP_FILL_OUTLIERS -
填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
· CV_WARP_INVERSE_MAP - 指定
map_matrix是输出图像到输入图像的反变换,因此可以直接用来做象素插值。否则, 函数从 map_matrix 得到反变换。
fillval
用来填充边界外面的值
函数 cvWarpAffine 利用下面指定的矩阵变换输入图像:
- 如果没有指定 CV_WARP_INVERSE_MAP ,

- 否则,

函数与 cvGetQuadrangleSubPix 类似,但是不完全相同。cvWarpAffine
要求输入和输出图像具有同样的数据类型,有更大的资源开销(因此对小图像不太合适)而且输出图像的部分可以保留不变。而 cvGetQuadrangleSubPix
可以精确地从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,而且总是全部改变输出图像的内容。要变换稀疏矩阵,使用 cxcore 中的函数
cvTransform 。
-----------------------------
|
2DRotationMatrix |
|
2DRotationMatrix CvMat* [ α β | (1-α)*center.x - where |
------------------------------------------------------------------------------------
/*code*/
- #include <highgui.h>
- #include <cv.h>
- int main(int argc, char** argv)
- {
- CvPoint2D32f srcTri[3], dstTri[3]; //二维坐标下的点,类型为浮点
- CvMat* rot_mat = cvCreateMat( 2, 3, CV_32FC1 ); //多通道矩阵
- CvMat* warp_mat = cvCreateMat( 2, 3, CV_32FC1 );
- IplImage *src, *dst;
- if( argc == 2 && ( ( src = cvLoadImage( argv[1], 1 ) ) != 0 ) )
- {
- dst = cvCloneImage( src ); //制作图像的完整拷贝
- dst ->origin = src ->origin;
- /*
- int origin; /* 0 - 顶—左结构,
- 1 - 底—左结构 (Windows bitmaps 风格)
- */
- cvZero( dst ); //清空数组
- //计算矩阵仿射变换
- srcTri[0].x = 0;
- srcTri[0].y = 0;
- srcTri[1].x = src -> width - 1; //缩小一个像素
- srcTri[1].y = 0;
- srcTri[2].x = 0;
- srcTri[2].y = src -> height - 1;
- //改变目标图像大小
- dstTri[0].x = src -> width * 0.0;
- dstTri[0].y = src -> height * 0.33;
- dstTri[1].x = src -> width * 0.85;
- dstTri[1].y = src -> height * 0.25;
- dstTri[2].x = src -> width * 0.15;
- dstTri[2].y = src -> height * 0.7;
- cvGetAffineTransform( srcTri, dstTri, warp_mat ); //由三对点计算仿射变换
- cvWarpAffine( src, dst, warp_mat ); //对图像做仿射变换
- cvCopy( dst, src ); //将dst拷贝给src
- //计算旋转仿射变换
- CvPoint2D32f center = cvPoint2D32f( src -> width / 2, src -> height / 2 );
- double angle = -50.0; //旋转角度,负值表示顺时针
- double scale = 0.6; //各项同性的尺度因子
- cv2DRotationMatrix( center, angle, scale, rot_mat );
- cvWarpAffine( src, dst, rot_mat ); //将src仿射变换存入dst
- //输出
- cvNamedWindow( "Affine_Transform", 1 );
- cvShowImage( "Affine_Transform", dst ); //最终是输出dst
- cvWaitKey();
- }
- cvReleaseImage( &dst );
- cvReleaseMat( &rot_mat );
- cvReleaseMat( &warp_mat );
- return 0;
- }
第六章 - 图像变换 - 图像拉伸、收缩、扭曲、旋转[1] - 仿射变换(cvWarpAffine)的更多相关文章
- 第六章 - 图像变换 - 图像拉伸、收缩、扭曲、旋转[2] - 透视变换(cvWarpPerspective)
透视变换(单应性?)能提供更大的灵活性,但是一个透视投影并不是线性变换,因此所采用的映射矩阵是3*3,且控点变为4个,其他方面与仿射变换完全类似,下面的例程是针对密集变换,稀疏图像变换则采用cvPer ...
- 第五、六章:图像&链接
图像有很多存储格式:JPEG.png.gif等,它们的文件大小也不同,使用的图片类型对于页面响应速度有不同的要求.下面就会简单阐述不同的格式的图片的特点. 1.JPEG格式 JPEG格式适用于彩色照片 ...
- o'Reill的SVG精髓(第二版)学习笔记——第六章
第六章:坐标系统变换 想要旋转.缩放或者移动图片到新的位置.可以给对应的SVG元素添加transform属性. 6.1 translate变换 可以为<use>元素使用x和y属性,以在特性 ...
- OpenCV2:第六章 图像几何变换
一.简介 图像的几何变换有距离变换 坐标映射 平移 镜像 旋转 缩放 仿射变换等 二.重映射 把一张图像重新排列像素,比如倒置 CV_EXPORTS_W void remap( InputArr ...
- Android群英传笔记——第六章:Android绘图机制与处理技巧
Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...
- 精通Web Analytics 2.0 (8) 第六章:使用定性数据解答”为什么“的谜团
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第六章:使用定性数据解答"为什么"的谜团 当我走进一家超市,我不希望员工会认出我或重新为我布置商店. 然而, ...
- Laxcus大数据管理系统2.0(8)- 第六章 网络通信
第六章 网络通信 Laxcus大数据管理系统网络建立在TCP/IP网络之上,从2.0版本开始,同时支持IPv4和IPv6两种网络地址.网络通信是Laxcus体系里最基础和重要的一环,为了能够利用有限的 ...
- 第六章 Qt布局管理器Layout
第六章 Qt布局管理器Layout 大家有没有发现一个现象,我们放置一个组件,给组件最原始的定位是给出这个控件的坐标和宽高值,这样Qt就知道这个组件的位置.当用户改变窗口的大小,组件还静静地呆在原来的 ...
- Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧
第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...
随机推荐
- ios initialize和init等方法
在程序运行过程中,创建多个类对象,只会调用一次initialize [ɪˈnɪʃəˌlaɪz] .而创建几个类对象就会调用几次init; 创建一个类aa,分别重写 initialize和init方法 ...
- Java 入门 代码2浮点数据类型
/** * 基本数据类型之浮点类型 */ public class DataTypeDemo2 { public static void main(String[] args) { double d1 ...
- Mysql 复合键索引性能
数据库的常见的索引一般是单个字段,如果多个字段的组合,那么就组成了复合索引.对于组合索引,如果 对其中一字段做为条件查询,会出现什么情况呢? 一.例子 mysql> show create ta ...
- 使用Process类重定向输出与错误时遇到的问题 (转)
程序中要调用外部程序cmd.exe执行一些命令行,并取得屏幕输出,使用了Process类,基本代码如下: Process process = new Process(); process.StartI ...
- 在sqlServer中把数据导出为insert脚本
有时候为了把数据导出为insert脚本,不得不用一些小工具,或者通过自己写存储过程来完成这一操作.其实SqlServer本身就有这种功能.以下是详细步骤:
- Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮
上次介绍了 Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 现在开始介绍如何配置审批流,首先在form上添加三个按钮,Submit, Agree, Reject: 1. ...
- 移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题
移动端浏览器隐私模式/无痕模式使用本地存储localStorage/sessionStorage的问题 开发H5 webapp时经常需要使用本地存储,如localStorage和sessionStor ...
- [ACM_数学] 大菲波数 (hdu oj 1715 ,java 大数)
大菲波数 Problem Description Fibonacci数列,定义如下:f(1)=f(2)=1f(n)=f(n-1)+f(n-2) n>=3.计算第n项Fibonacci数值. ...
- servlet web文件上传
web文件上传也是一种POST方式,特别之处在于,需设置FORM的enctype属性为multipart/form-data. 并且需要使用文件域. servlet的代码比较关键是这几句: // 使用 ...
- (笔记)VC6插件安装(VC6LineNumberAddin)
VC6插件安装步骤如下: 1.下载VC6LineNumberAddin插件及注册文件.(以下是参考链接:) http://files.cnblogs.com/files/tdyizhen1314/VC ...