OpenCV 图像旋转和缩放

本文详细介绍了如何使用OpenCV库实现图像旋转和缩放,包括推导旋转变换公式、利用函数计算旋转矩阵以及对图像进行仿射变换的完整过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

旋转变换公式的推导:

如下图, 在2维坐标上,有一点p(x, y) , 直线op的长度为r, 直线op和x轴的正向的夹角为a。 直线op围绕原点做逆时针方向b度的旋转,到达p’ (s,t) 


则有

s = r cos(a + b) = r cos(a)cos(b) – r sin(a)sin(b)   (1.1)
t  = r sin(a + b)  = r sin(a)cos(b)  + r cos(a) sin(b)  (1.2)
其中 x = r cos(a)  , y = r sin(a)
代入(1.1), (1.2) ,
s = x cos(b) – y sin(b)    (1.3)
t  = x sin(b)  + y cos(b)    (1.4)
用行列式表示如下



用到的一些OpenCV中的函数:

 

(1)    CvMat*cv2DRotationMatrix(CvPoint2D32f center, double angle, double scale, CvMat*map_matrix);

         Mat getRotationMatrix2D(Point2f center, double angle, double scale );

              说明:计算旋转加缩放的仿射矩阵

              参数:center:旋转中心

                       angle:旋转度数,正值表示逆时针旋转。

                       scale:各方向同性的缩放尺度

                       map_matrix:输出参数,仿射变换矩阵,浮点型2*3矩阵

              返回值:仿射变换矩阵

              注意:默认的变换是以相反的顺序进行的,即从目标到源。对于目标图像中的任一点(x,y),先计算出它在

                       源图像中的坐标,再将此点的像素值拷贝到目标图像中,所以计算出的变换矩阵是从目标到源的变换矩阵。

例如逆时针旋转30度,不做缩放,计算出的变换矩阵为:


 

(2)    void cvWarpAffine(const CvArr* src,CvArr* dst, const CvMat* map_matrix,

                                      intflags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, CvScalar fillval=cvScalarAll(0) );

         void warpAffine(InputArray src, OutputArray dst, InputArray M, Sizedsize, int flags=INTER_LINEAR,

                                    int borderMode = BORDER_CONSTANT, constScalar& borderValue=Scalar() );

              说明:对图像做仿射变换

              参数:M:输入参数,2*3的仿射变换矩阵

                       dsize:输出图像的尺寸

                       flags:差值方法,若设置WARP_INVERSE_MAP标识,指明M是目的到源的变换。

                       borderMode:边界处理方法

              注意:当设置标志位WARP_INVERSE_MAP时,目标图像的计算公式为:

                      

                       否则,先调用invertAffineTransform()计算出M的逆仿射变换M’,然后将M’带入以上公式进行变换。

 

第一种方法  //////////////////////////////////////////////////////////////////

#include 
#include 
#include 
 
using namespace std; 
using namespace cv; 
 
#define SCALE 0.5   //缩放比例 
 
int main() 

    Mat src = imread("pic3.png"); 
    Mat dst;//输出图像 
 
    int angle = 30;//旋转角度(正值表示逆时针旋转) 
 
    int length;//输出图像的宽度或高度 
    //为了保证无论如何旋转都能放下,输出图像的长和宽都设为输入图像对角线长度乘以SCALE 
    //但如果是缩小(SCALE<=1),这样会导致临时图像中放不下原图,所以对于所有缩小的情况,输出图像和临时图像的长宽都设为原图的对角线长度 
    if(SCALE <= 1) 
        length = sqrt(src.cols*src.cols + src.rows*src.rows); 
    else 
        length = sqrt(src.cols*src.cols + src.rows*src.rows) * SCALE; 
    //建立临时图像,长宽都是源图像的对角线长度,将源图像复制到临时图像的中心后再变换 
    Mat tempImg(length,length,src.type());//临时图像,大小和输出图像一样大 
    int ROI_x = length/2 - src.cols/2;//ROI矩形左上角的x坐标 
    int ROI_y = length/2 - src.rows/2;//ROI矩形左上角的y坐标 
    Rect ROIRect(ROI_x,ROI_y,src.cols,src.rows);//ROI矩形 
    Mat tempImgROI2(tempImg,ROIRect);//tempImg的中间部分 就是在图像tempTmage 中按照ROIRect 中的

//四个元素选出一个区域,当然该区域是以矩阵的形式表达的。
    src.copyTo(tempImgROI2);//将原图src复制到tempImg的中心   即矩阵tempImgROI2的位置。
 
    Point2f center(length/2,length/2);//旋转中心 
    Mat M = getRotationMatrix2D(center,angle,SCALE);//计算旋转的仿射变换矩阵 
 
    //输出看看算出的矩阵是什么 
    cout<<"变换矩阵:"<<endl; 
    cout<<M.at(0,0)<<","<<M.at(0,1)<<","<<M.at(0,2)<<","<<endl; 
    cout<<M.at(1,0)<<","<<M.at(1,1)<<","<<M.at(1,2)<<","<<endl; 
 
    warpAffine(tempImg,dst,M,Size(length,length));//仿射变换 
 
    //显示 
    imshow("src",src); 
    imshow("tempImg",tempImg); 
    imshow("dst",dst); 
 
    waitKey(0); 
    return 0; 

 

 

第二种方法  //////////////////////////////////////////////////////////////////

 

#include"cv.h"
#include"highgui.h"
int main (int argc,char argv)
{
    // 载入图像并显示
     IplImage *src=cvLoadImage("C:\\111.jpg",1);
  cvNamedWindow ("src", 1); 
        cvShowImage ("src", src); 

  //设置旋转角度和缩放尺寸 
  double degree=200.0;
  double scale=1;
  double angle = degree  * CV_PI / 180.; // angle in radian 
        double a = sin(angle), b = cos(angle); // sine and cosine of angle 

        //确定旋转中心
  CvPoint2D32f center=cvPoint2D32f(src->width/2,src->height/2);

  //确定旋转后图像的大小,并创建旋转后的图像dst
        int w_src = src->width; 
        int h_src = src->height; 
  int w_dst = int(h_src * fabs(a) + w_src * fabs(b)); 
        int h_dst = int(w_src * fabs(a) + h_src * fabs(b));
  IplImage *dst = cvCreateImage(cvSize(w_dst, h_dst), 8, 3);
  
  //创建旋转缩放映射矩阵
  double map[6];
  //CvMat* rot_mat=cvCreateMat(2,3,CV_64FC1,map);// CvMat 是opencv的数据结构 
  //“rot_mat” 就代表了CvMat结构的所有元素,或者说是数据,“&rot_mat”就代表了存储这些数据的地址。当然 rot_mat的值应该是结构体的首地址,
  //所以在调用cv2DRotationMatrix函数式直接写为cv2DRotationMatrix(center,angle,scale,rot_mat);
  //若是要释放内存的话也就要写为 cvRealseMat(&rot_mat)

  CvMat rot_mat = cvMat(2, 3, CV_64FC1, map);

 

        //计算 旋转和缩放 变换矩阵
  //cv2DRotationMatrix(center,angle,scale,rot_mat);
  cv2DRotationMatrix(center,angle,scale,&rot_mat);

  //将旋转图像的旋转中心与新建图像的中心对其?

  map[2] += (w_dst - w_src) / 2; 
        map[5] += (h_dst - h_src) / 2;

  //对原图进行旋转缩放并获取最后结果dst
  cvWarpAffine(src,dst,&rot_mat);

 

  //显示最后结果
  cvNamedWindow("Affine_Transform",CV_WINDOW_AUTOSIZE);
  cvShowImage("Affine_Transform",dst);

  //释放内存
  cvWaitKey();
  cvReleaseImage(&dst);
     cvReleaseImage(&src);
  cvDestroyAllWindows();
   
  return 0;
 
 }
  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值