#include "cv.h" #include "highgui.h" #include "math.h" int main( int argc, char** argv ) { IplImage* src; /* the first command line parameter must be image file name */ if( argc==2 && (src = cvLoadImage(argv[1], -1))!=0) { IplImage* dst = cvCloneImage( src ); int delta = 1; int angle = 0; cvNamedWindow( "src", 1 ); cvShowImage( "src", src ); for(;;) { float m[6]; double factor = (cos(angle*CV_PI/180.) + 1.1)*3; CvMat M = cvMat( 2, 3, CV_32F, m ); int w = src->width; int h = src->height; m[0] = (float)(factor*cos(-angle*2*CV_PI/180.)); m[1] = (float)(factor*sin(-angle*2*CV_PI/180.)); m[2] = w*0.5f; m[3] = -m[1]; m[4] = m[0]; m[5] = h*0.5f; cvGetQuadrangleSubPix( src, dst, &M, 1, cvScalarAll(0)); cvNamedWindow( "dst", 1 ); cvShowImage( "dst", dst ); if( cvWaitKey(5) == 27 ) break; angle = (angle + delta) % 360; } } return 0; }
描述:图像旋转是指把定义的图像绕某一点以逆时针或顺时针方向旋转一定的角度,通常是指绕图像的中心以逆时针方向旋转。 首先根据旋转的角度、图象对角线的长度计算旋转后的图像的最大宽度、高度,根据旋转后图象最大的宽度、高度生成新的缓冲区,假设图像的左上角为(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)点处。注意在新缓冲区中与原图没有对应的象素点的值用白色代替
opencv 任意角度旋转图像:
IplImage * CCropMeasureView::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, 3); cvFillImage(Img_tmp,0);//目的图像 使用扩展的大小 IplImage* dst = cvCloneImage( Img_old );//目的图像 与原图像等大 float m[6]; CvMat M = cvMat( 2, 3, CV_32F, m ); if(1==method) { //方法一 提取象素四边形,使用子象素精度 int w = Img_old->width; int h = Img_old->height; m[0] = (float)(cos(angle*CV_PI/180.)); m[1] = (float)(sin(angle*CV_PI/180.)); m[2] = w*0.5f; m[3] = -m[1]; m[4] = m[0]; m[5] = h*0.5f; cvGetQuadrangleSubPix( Img_old, dst, &M, 1, cvScalarAll(0)); cvGetQuadrangleSubPix( Img_old, Img_tmp, &M, CV_INTER_LINEAR, cvScalarAll(0));//+CV_WARP_FILL_OUTLIERS //方法一 提取象素四边形,使用子象素精度 } if(2==method) { //方法二 使用 二维旋转的仿射变换矩阵 存在问题 要求输入和输出图像一样大 旋转中心不对 CvPoint2D32f center; center.x=float (Img_old->width/2.0+0.5);//float (Img_tmp->width/2.0+0.5); center.y=float (Img_old->height/2.0+0.5);//float (Img_tmp->height/2.0+0.5); cv2DRotationMatrix( center, angle,1, &M); cvWarpAffine( Img_old, dst, &M,CV_INTER_LINEAR,cvScalarAll(0) );//小图 //小目标图像 //对图像进行扩展 // 只能一定角度以内 不同象限的不同对待 int dx=int((newwidth -Img_old->width )/2+0.5); int dy=int((newheight-Img_old->height)/2+0.5); uchar* old_ptr,*temp_ptr; for( int y=0 ; y<Img_old->height; y++) //为了不越界 { for (int x=0 ; x< Img_old->width; x++) { old_ptr = &((uchar*)(Img_old->imageData + Img_old->widthStep*y))[(x)*3]; temp_ptr = &((uchar*)(Img_tmp->imageData + Img_tmp->widthStep*(y+dy)))[(x+dx)*3]; temp_ptr[0]=old_ptr[0]; //green temp_ptr[1]=old_ptr[1]; //blue temp_ptr[2]=old_ptr[2]; //Red } } center.x=float (Img_tmp->width/2.0+0.5); center.y=float (Img_tmp->height/2.0+0.5); cv2DRotationMatrix( center, angle,1, &M); IplImage* temp = cvCloneImage( Img_tmp );//生成输出图像 cvWarpAffine( Img_tmp, temp , &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0) );//大图 Img_tmp=cvCloneImage( temp ); //问题 //cvWarpAffine( Img_tmp, Img_tmp, &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0) );//大图 //方法二 使用 二维旋转的仿射变换矩阵 } if(3==method) { //方法三 透视变换 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) ); //方法三 透视变换 } // cvNamedWindow( "dst_litter", 1 ); // cvShowImage( "dst_litter", dst ); // cvNamedWindow( "dst_big", 1 ); // cvShowImage( "dst_big", Img_tmp ); return Img_tmp; }
#include <cv.h> #include <highgui.h> #pragma comment(lib, "cv.lib") #pragma comment(lib, "cxcore.lib") #pragma comment(lib, "highgui.lib") 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("test.png"); 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); cvWarpAffine( imgSrc, imgDst, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0) ); // 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文档:http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html