图像旋转

  参考原文http://vipbase.net/ipbook/chap02.htm   

   这里主要讨论以图象的中心为圆心旋转。旋转之后若要保持目标区域大小不变,则整幅图像变大;若要保持整幅图像的大小不变,则旋转出去的部分需要裁剪掉。

 

 

         旋转前的图

    旋转后的图

 

旋转后保持原图大小,转出的部分被裁掉

    以顺时针旋转为例来堆到旋转变换公式。如下图所示。

 

旋转前:

x0=rcosby0=rsinb

旋转a角度后:

x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina

y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa

矩阵形式为

逆变换为

 

    上面的公式是以图像的左下角为原点旋转的。现我们要以图像的中心为原点旋转。因此需要先将坐标平移到图像中心,如下所示

设图象的宽为w,高为h,容易得到:

逆变换为

     现在可以分三步来完成旋转变换:

     1. 将坐标系x'o'y'平移到xoy ;  2. 在xoy坐标系下作旋转变换;  3.变换后将坐标系平移回原来位置。

     用矩阵表示就是        

   其中R表示旋转变换矩阵。当旋转不改变图像大小时,T 与 T' 互为逆矩阵;当旋转后图像变大时,T 与 T'不是逆矩阵关系,因为图像变大了,第一次平移和第二次平移坐标系的距离不一样。因此当图像变大时,公式应该如下:

    由于算法实现过程中我们需要的是逆变换的公式,因此我们只写出逆变换的表达式,如下:

       其中wn ,hn 表示新图像的宽和高,wo, ho 表示原图像的宽和高。

     这样,对于新图中的每一点,我们就可以根据上面逆变换公式求出对应原图中的点,得到它的灰度。如果超出原图范围,则设置为背景色。要注意的是,由于有浮点运算,计算出来点的坐标可能不是整数,采用取整处理,即找最接近的点,这样会带来一些误差(图象可能会出现锯齿)。更精确的方法是采用插值,这里暂不讨论。

    C++代码如下:

复制代码
/*
* rotate.cpp
* 图像旋转变换(顺时针)
* Created on: 2011-10-10
* Author: LiChanghai
*/
// 以图像中心为坐标原点,旋转后不改变图像大小
// 函数返回值为指针,指向新申请的内存区域
// 因为新图像大小改变了,需要返回新图像的尺寸
// 因此形参的高度和宽度都采用指针变量
#include<string.h>
#include<stdlib.h>
#include<cmath>
#define pi 3.1415926535
unsigned char * rotate(unsigned char *pImage, int *width, int *height, int biBitCount, float angle)
{
//定义以图像中心为原点的坐标系下原图像和新图像的四个角点坐标
float src_x1, src_y1, src_x2, src_y2, src_x3, src_y3, src_x4, src_y4;
float dst_x1, dst_y1, dst_x2, dst_y2, dst_x3, dst_y3, dst_x4, dst_y4;

//定义新图像的高度和宽度
int wnew, hnew;

//定义计算过程中需要的相关变量
float sina, cosa, temp1, temp2, alpha;

//角度转化为弧度
alpha=pi*angle/180;

cosa = float(cos(double(alpha)));
sina = float(sin(double(alpha)));

//原图像的四个角点的坐标
src_x1 = float(-0.5*(*width)); src_y1 = float(0.5*(*height));
src_x2 = float(0.5*(*width)); src_y2 = src_y1;
src_x3 = src_x1; src_y3 = float(-0.5*(*height));
src_x4 = src_x2; src_y4 = src_y3;

//计算新图像的四个角点坐标
dst_x1 = cosa*src_x1+sina*src_y1;
dst_y1 = -sina*src_x1+cosa*src_y1;

dst_x2 = cosa*src_x2+sina*src_y2;
dst_y2 = -sina*src_x2+cosa*src_y2;

dst_x3 = cosa*src_x3+sina*src_y3;
dst_y3 = -sina*src_x3+cosa*src_y3;

dst_x4 = cosa*src_x4+sina*src_y4;
dst_y4 = -sina*src_x4+cosa*src_y4;

//计算新图像的高度和宽度
float t1 = fabs(dst_x4-dst_x1), t2 = fabs(dst_x3-dst_x2);
wnew = int(t1>t2 ? t1:t2);
t1 = fabs(dst_y4-dst_y1), t2 = fabs(dst_y3-dst_y2);
hnew = int(t1>t2 ? t1:t2);

// 计算旋转变换中的两个中间变量,便于以后计算
temp1=float( -0.5*wnew*cosa+0.5*hnew*sina+0.5*(*width));
temp2=float(-0.5*wnew*sina-0.5*hnew*cosa+0.5*(*height));
//计算原图像和新图像每行像素所占的字节数(必须是4的倍数)
int lineByte = ((*width) * biBitCount/8+3)/4*4;
int lineByte2=(wnew * biBitCount/8+3)/4*4;

//申请新的位图数据存储空间
unsigned char *pImage2;
pImage2=new unsigned char[lineByte2*hnew];

//将新图像设置为背景色
memset(pImage2, 0, lineByte2*hnew);

//遍历新图像的每一个像素进行判断
int x, y, x0, y0; // x0, y0为原图像中对应坐标
for(y=0; y<hnew; y++)
for(x=0; x<wnew; x++)
{
x0= int(x*cosa-y*sina+temp1);
y0= int(x*sina+y*cosa+temp2);
//如果在原图像范围内则复制像素值
if( (x0>=0) && (x0<(*width)) && (y0>=0) && (y0<(*height)))
{
*(pImage2+lineByte2*y+x) = *(pImage+lineByte*y0+x0);
}
}

//修改原图像的高度和宽度
*width = wnew;
*height = hnew;
delete [ ] pImage; //释放原内存空间
return pImage2;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像数据增强是一种广泛应用于计算机视觉任务中的技术,它可以通过对原始图像进行一系列变换来增加训练数据的多样性。图片旋转是其中一种常见的数据增强方式之一。 在图像旋转过程中,可以使用旋转矩阵来对图像进行变换。旋转矩阵定义了一个旋转角度和旋转中心点,通过将每个像素点围绕中心点按照指定的角度进行旋转,从而实现图像旋转操作。 在进行图像旋转时,可以选择不同的角度来生成不同方向的旋转图像。常见的角度包括90度、180度和270度等,也可以使用任意角度进行旋转。 以下是一个使用Python和OpenCV库进行图像旋转的示例代码: ```python import cv2 def rotate_image(image, angle): # 获取图像尺寸 height, width = image.shape[:2] # 计算旋转中心点 center = (width / 2, height / 2) # 定义旋转矩阵 rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # 执行旋转操作 rotated_image = cv2.warpAffine(image, rotation_matrix, (width, height)) return rotated_image # 读取图像 image = cv2.imread('image.jpg') # 旋转图像 rotated_image = rotate_image(image, 90) # 显示旋转后的图像 cv2.imshow('Rotated Image', rotated_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上代码中,`rotate_image` 函数用于对图像进行旋转操作。首先获取图像的尺寸,然后通过 `cv2.getRotationMatrix2D` 函数计算旋转矩阵。最后使用 `cv2.warpAffine` 函数执行旋转操作,生成旋转后的图像。 请注意,以上代码仅为示例,实际使用时可能需要根据具体需求进行调整。另外,OpenCV还提供了其他图像旋转的函数和参数选项,可以根据需要进行更灵活的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值