您的位置:首页 > 运维架构 > 网站架构

OpenCV中文网站例程——图像旋转和缩放

2014-03-31 15:05 441 查看
相关知识点参考:http://xiangge2009.blog.sohu.com/147112222.html

首先根据旋转的角度、图象对角线的长度计算旋转后的图像的最大宽度、高度,根据旋转后图象最大的宽度、高度生成新的缓冲区,假设图像的左上角为(left, top),右下角为(right, bottom),则图像上任意点(x, y)绕其中心(xcenter, ycenter)逆时针旋转angle角度后,新的坐标位置(x1, y1)的计算公式为:

xcenter = (width+1)/2+left;

ycenter = (height+1)/2+top;

x1= (x-xcenter)cosθ- (y-ycenter)sinθ+xcenter;

y1= (x-xcenter)sinθ+ (y-ycenter)cosθ+ycenter;

与图像的镜像变换相类似,把原图中的象素值读入新缓冲区的(x1,y1)点处。注意在新缓冲区中与原图没有对应的象素点的值用白色代替。

GetQuadrangleSubPix

提取象素四边形,使用子象素精度
void cvGetQuadrangleSubPix( const CvArr* src, CvArr* dst, const CvMat* map_matrix );


src 输入图像.

dst 提取的四边形.

map_matrix 3 × 2 变换矩阵 [A|b] .

函数 cvGetQuadrangleSubPix 以子象素精度从图像 src 中提取四边形,使用子象素精度,并且将结果存储于 dst ,计算公式是:

( + () / 2, + () / 2) = (11 + 12 + 1,21 + 22 + 2)

其中 A和 b 均来自映射矩阵(译者注:A, b为几何形变参数)

其中在非整数坐标的象素点值通过双线性变换得到。当函数需要图像边界外的像素点时,使用重复边界模式(replication border

mode)恢复出所需的值。多通道图像的每一个通道都单独计算。

例子结果:(图像结果都是动态显示)

例子程序:

#include "cv.h"

#include "highgui.h"

#include "math.h"

int main (int argc, char **argv)

{

IplImage *src = 0;

IplImage *dst = 0;

/* the first command line parameter must be image file name */

if ((src = cvLoadImage ("E://lena.jpg", -1)) != 0)

{

int delta = 1;

int angle = 0;

int opt = 1; // 1: 旋转加缩放

// 0: 仅仅旋转

double factor;

dst = cvCloneImage (src);

cvNamedWindow ("src", 1);

cvShowImage ("src", src);

for (;;)

{

float m[6];

// Matrix m looks like:

//

// [ m0 m1 m2 ] ===> [ A11 A12 b1 ]

// [ m3 m4 m5 ] [ A21 A22 b2 ]

//

CvMat M = cvMat (2, 3, CV_32F, m);

int w = src->width;

int h = src->height;

if (opt)
// 旋转加缩放

factor = (cos (angle * CV_PI / 180.) + 1.0) * 2;

else // 仅仅旋转

factor = 1;

m[0] = (float) (factor * cos (-angle * 2 * CV_PI / 180.));

m[1] = (float) (factor * sin (-angle * 2 * CV_PI / 180.));

m[3] = -m[1];

m[4] = m[0];

// 将旋转中心移至图像中间

m[2] = w * 0.5f;

m[5] = h * 0.5f;

// dst(x,y) = A * src(x,y) + b

cvZero (dst);

cvGetQuadrangleSubPix (src, dst, &M);

cvNamedWindow ("dst", 1);

cvShowImage ("dst", dst);

if (cvWaitKey (1) == 27)//ESC

break;

angle = (int) (angle + delta) % 360; //旋转角度变换步长为1

} // for-loop

}

return 0;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: