图像旋转的MATLAB和OpenCV源码!

图像旋转的意义就不多说了,直接上源码吧!

源码中用到的lena.jpg、lena_gray.png、pool.jpg图像的下载链接分别为:

http://pan.baidu.com/s/1sl1jEKt

http://pan.baidu.com/s/1bo5zC2F
http://pan.baidu.com/s/1dFv2MM9

先要说明的是,MATLAB得出的图像和OpenCV得出的源码在数据上是有差别的,但是都是对的!

先上MATLAB处理灰度图像的源码:

 

clear all;
close all;
clc;
a=imread('lena.jpg');
a=rgb2gray(a);
a1=imrotate(a,30,'bilinear');%%旋转函数,30为旋转角度,bilinear为旋转后不是整数点的像素值 通过双线性插值得到。当旋转角度为正时,逆时针旋转;当旋转角度为负时,顺时针旋转。
figure,imshow(a);
figure,imshow(a1);

 

再上MATLAB处理彩色图像的源码:

 

clear all;
close all;
clc;
a=imread('lena.jpg');

R=a(:,:,1);
G=a(:,:,2);
B=a(:,:,3);

R_r=imrotate(R,30,'bilinear');%旋转函数,30为旋转角度,bilinear为旋转后不是整数点的像素值 通过双线性插值得到。当旋转角度为正时,逆时针旋转;当旋转角度为负时,顺时针旋转。
G_r=imrotate(G,30,'bilinear');
B_r=imrotate(B,30,'bilinear');

a1(:,:,1)=R_r;
a1(:,:,2)=G_r;
a1(:,:,3)=B_r;

figure,imshow(a);
figure,imshow(a1);

 

再上OpenCV处理灰度级图像旋转的C源码(不使用MAT类):

 

#include <opencv2/opencv.hpp>  
#include <opencv2/legacy/compat.hpp> 
#include <fstream>
using namespace std;  
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  


IplImage *FitRotate (IplImage* Img_old, double angle,int method) //使用透视变换实现图像的旋转

{

	IplImage* Img_tmp = NULL; 

	double anglerad  = (CV_PI* (angle/180)) ;//把角度制化为弧度制
	//计算旋转之后图片的新高度和宽度
	int newheight =int (fabs(( sin(anglerad)*Img_old->width )) + fabs(( cos(anglerad)*Img_old->height )) );
	int newwidth  =int (fabs(( sin(anglerad)*Img_old->height)) + fabs(( cos(anglerad)*Img_old->width)) );
	     
	Img_tmp = cvCreateImage(cvSize(newwidth,newheight), IPL_DEPTH_8U, 1);
	cvFillImage(Img_tmp,0);//如果return Img_tmp;则旋转后的图像与输入图像大小不一致

	IplImage* dst = cvCloneImage( Img_old );//如果return dst;则旋转后的图像与输入图像大小一致

	     
	float m[6];            
	CvMat M = cvMat( 2, 3, CV_32F, m );

	//从这里开始是核心算法

	  CvPoint2D32f src_point[4];
      CvPoint2D32f dst_point[4];

      src_point[0].x=0.0;                    src_point[0].y=0.0;
      src_point[1].x=0.0;                    src_point[1].y=(float) Img_old->height; 
      src_point[2].x=(float) Img_old->width; src_point[2].y=(float) Img_old->height;
      src_point[3].x=(float) Img_old->width; src_point[3].y=0.0;


      dst_point[0].x=0;               
      dst_point[0].y=(float) fabs(( sin(anglerad)*Img_old->width ));

      dst_point[1].x=(float) fabs(( sin(anglerad)*Img_old->height));              
      dst_point[1].y=(float) fabs(( sin(anglerad)*Img_old->width ))+(float) fabs(( cos(anglerad)*Img_old->height));
    
      dst_point[2].x=(float) fabs(( sin(anglerad)*Img_old->height))+(float) fabs(( cos(anglerad)*Img_old->width));
      dst_point[2].y=(float) fabs(( cos(anglerad)*Img_old->height));

      dst_point[3].x=(float) fabs(( cos(anglerad)*Img_old->width));
      dst_point[3].y=0;
    
       
      float newm[9];            
      CvMat newM = cvMat( 3, 3, CV_32F, newm );
      cvWarpPerspectiveQMatrix(src_point,dst_point,&newM);
   
      cvWarpPerspective(Img_old,dst,&newM,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0) );
      cvWarpPerspective(Img_old,Img_tmp,&newM,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0) );

   
     return Img_tmp;
	 //return dst;

    }

int main()
{

	IplImage *pSrcImage = cvLoadImage("lena.png", CV_LOAD_IMAGE_UNCHANGED);  
	//IplImage *pOutImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U,1);
	IplImage *pOutImage = NULL;

	pOutImage=FitRotate(pSrcImage,70,1);

	cvSaveImage("pOutImage_lena.png",pOutImage);  

	const char *pstrWindowsATitle = "原图";  
	const char *pstrWindowsBTitle = "变换后的图"; 
	//创建窗口      
	cvNamedWindow(pstrWindowsATitle, CV_WINDOW_AUTOSIZE);      
	cvNamedWindow(pstrWindowsBTitle, CV_WINDOW_AUTOSIZE);
	//在指定窗口中显示图像      
	cvShowImage(pstrWindowsATitle, pSrcImage);    
	cvShowImage(pstrWindowsBTitle, pOutImage);    
	//等待按键事件      
	cvWaitKey();      
	cvDestroyWindow(pstrWindowsATitle);  
	cvDestroyWindow(pstrWindowsBTitle); 
	cvReleaseImage(&pSrcImage);  
	cvReleaseImage(&pOutImage);    

return 0;
}

 

再上OpenCV处理RGB图像旋转的C源码(不使用MAT类):

 

#include <opencv2/opencv.hpp>  
#include <opencv2/legacy/compat.hpp> 
#include <fstream>
using namespace std;  
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  


int main()  
{  
    double degree = 30; // rotate 30 degree  
    double angle = degree  * CV_PI / 180.; // angle in radian  
    double a = sin(angle), b = cos(angle); // sine and cosine of angle  
  
    // Load source image as you wish  
    IplImage *imgSrc = cvLoadImage("lena.jpg");  
    int w_src = imgSrc->width;  
    int h_src = imgSrc->height;  
    cvNamedWindow ("src", 1);  
    cvShowImage ("src", imgSrc);  
    // Make w_dst and h_dst to fit the output image  
    int w_dst = int(h_src * fabs(a) + w_src * fabs(b));  
    int h_dst = int(w_src * fabs(a) + h_src * fabs(b));  
  
    // map matrix for WarpAffine, stored in statck array  
    double map[6];  
    CvMat map_matrix = cvMat(2, 3, CV_64FC1, map);  
  
    // Rotation center needed for cv2DRotationMatrix  
    CvPoint2D32f pt = cvPoint2D32f(w_src / 2, h_src / 2);  
    cv2DRotationMatrix(pt, degree, 1.0, &map_matrix);  
  
    // Adjust rotation center to dst's center,  
    // otherwise you will get only part of the result  
    map[2] += (w_dst - w_src) / 2;  
    map[5] += (h_dst - h_src) / 2;  
  
  
    // We need a destination image  
  
    IplImage *imgDst = cvCreateImage(cvSize(w_dst, h_dst), 8, 3); //按我的想像,如果把3改成1就能处理灰度图像才对,但要报错
    cvWarpAffine(  
        imgSrc,   
        imgDst,  
        &map_matrix,  
        CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS,  
        cvScalarAll(0)  
        );  

	//cvSaveImage("lena_gray_rotation.png",imgDst);  //将图像保存到硬盘
  
    // Don't forget to release imgSrc and imgDst if you no longer need them  
    cvNamedWindow( "dst_big", 1 );  
    cvShowImage( "dst_big", imgDst);  
  
    cvWaitKey(0);  
    cvReleaseImage(&imgSrc);  
    cvReleaseImage(&imgDst);  
    return 0;  
}  

 

需要说明的是,按理在OpenCV处理RGB图像旋转的源码中,把语句 IplImage *imgDst = cvCreateImage(cvSize(w_dst, h_dst), 8, 3); 中的3改成1,应该就可以处理灰度图像才对,但我试了,报错,不知道怎么回事!我的源图像是灰度图像也报错!

结果如下图所示:

MATLAB的结果:

OpenCV的结果:


 

再上OpenCV的C++源码(使用MAT类,并且RGB和灰度图像都能处理)

 

//OpenCV版本2.4.9  
//交流QQ2487872782 


#include <opencv2/core/core.hpp>        
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp>  
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
cv::Mat angelRotate(cv::Mat& src, int angle)
{
    // 角度转换
    float alpha = float(angle * CV_PI / 180);
    // 构造旋转矩阵
    float rotateMat[3][3] = { 
        {cos(alpha), -sin(alpha), 0},
        {sin(alpha), cos(alpha), 0}, 
        {0, 0, 1} };
    int nSrcRows = src.rows;
    int nSrcCols = src.cols;
    // 计算旋转后图像矩阵各个顶点位置
    float a1 = nSrcCols * rotateMat[0][0] ;
    float b1 = nSrcCols * rotateMat[1][0] ;
    float a2 = nSrcCols * rotateMat[0][0] + 
        nSrcRows * rotateMat[0][1];
    float b2 = nSrcCols * rotateMat[1][0] +
        nSrcRows * rotateMat[1][1];
    float a3 = nSrcRows * rotateMat[0][1];
    float b3 = nSrcRows * rotateMat[1][1];
    // 计算出极值点
    float kxMin =  min( min( min(0.0f,a1), a2 ), a3);
    float kxMax =  max( max( max(0.0f,a1), a2 ), a3);
    float kyMin =  min( min( min(0.0f,b1), b2 ), b3);
    float kyMax =  max( max( max(0.0f,b1), b2 ), b3);
    // 计算输出矩阵的尺寸
    int nRows = int(abs(kxMax - kxMin));
    int nCols = int(abs(kyMax - kyMin));
    cv::Mat dst(nRows, nCols, src.type(),cv::Scalar::all(0)); 
    for( int i = 0; i < nRows; ++i)
    {       
        for (int  j = 0; j < nCols; ++j)
        {
            // 旋转坐标转换
            int x =  (j + kxMin) * rotateMat[0][0] -
                (i + kyMin) * rotateMat[0][1] ;
            int y = -(j + kxMin) * rotateMat[1][0] + 
                (i + kyMin) * rotateMat[1][1] ;
            if( (x >= 0) && (x < nSrcCols) && 
                (y >= 0) && (y < nSrcRows) ) 
            {  
                dst.at<cv::Vec3b>(i,j) = 
                    src.at<cv::Vec3b>(y,x);
            }
        }
    }
    return dst;
}
int main()
{
    /*cv::Mat srcImage = cv::imread("pool.jpg"); */
	cv::Mat srcImage = cv::imread("lena_gray.png"); 
    if(!srcImage.data) 
        return -1;
    cv::imshow("srcImage", srcImage); 
    int angle = 30;
    cv::Mat resultImage = angelRotate(srcImage, angle);
    imshow("resultImage", resultImage);
    cv::waitKey(0);
    return 0;
}

 

运行结果如下图所示:

 

图像处理开发资料、图像处理开发需求、图像处理接私活挣零花钱,可以搜索公众号"qxsf321",并关注!
图像处理开发资料、图像处理开发需求、图像处理接私活挣零花钱,可以搜索公众号"qxsf321",并关注!
图像处理开发资料、图像处理开发需求、图像处理接私活挣零花钱,可以搜索公众号"qxsf321",并关注!

发布了192 篇原创文章 · 获赞 219 · 访问量 94万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览