2010-02-18 42 views
25

Tôi cần phải xoay ảnh theo góc rất nhỏ, như 1-5 độ. Có OpenCV cung cấp cách đơn giản để thực hiện điều đó không? Từ tài liệu đọc tôi có thể giả thiết rằng getAffineTransform() nên tham gia, nhưng không có ví dụ trực tiếp làm cái gì đó như:OpenCV: cách xoay IplImage?

IplImage *rotateImage(IplImage *source, double angle); 

Trả lời

42

Nếu bạn sử dụng OpenCV> 2.0 nó là dễ dàng như

using namespace cv; 

Mat rotateImage(const Mat& source, double angle) 
{ 
    Point2f src_center(source.cols/2.0F, source.rows/2.0F); 
    Mat rot_mat = getRotationMatrix2D(src_center, angle, 1.0); 
    Mat dst; 
    warpAffine(source, dst, rot_mat, source.size()); 
    return dst; 
} 

Lưu ý: góc là theo độ, không radian.

Xem tài liệu giao diện C++ để biết thêm chi tiết và thích ứng như bạn cần:

4

Kiểm tra câu trả lời của tôi đến một vấn đề tương tự:

Rotating an image in C/C++

Về cơ bản, sử dụng cvWarpAffine - Tôi đã mô tả cách lấy ma trận chuyển đổi 2x3 từ góc trong câu trả lời trước của tôi.

5

Edit: Để cử tri xuống: Xin vui lòng bình luận lý do xuống bỏ phiếu một thử và thử nghiệm mã?

#include "cv.h" 
#include "highgui.h" 
#include "math.h" 
int main(int argc, char** argv) 
{ 
    IplImage* src = cvLoadImage("lena.jpg", 1);  
    IplImage* dst = cvCloneImage(src); 

    int delta = 1; 
    int angle = 0; 
    int opt = 1; // 1: rotate & zoom 
       // 0: rotate only 
    double factor; 
    cvNamedWindow("src", 1); 
    cvShowImage("src", src); 

    for(;;) 
    { 
    float m[6]; 
    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.05) * 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; 

    cvGetQuadrangleSubPix(src, dst, &M); 
    cvNamedWindow("dst", 1); 
    cvShowImage("dst", dst); 
    if(cvWaitKey(1) == 27) 
     break; 
    angle =(int)(angle + delta) % 360; 
    }  
    return 0; 
} 

CẬP NHẬT: Xem đoạn mã sau để luân chuyển sử dụng warpaffine https://code.google.com/p/opencvjp-sample/source/browse/trunk/cpp/affine2_cpp.cpp?r=48

#include <cv.h> 
#include <highgui.h> 

using namespace cv; 

int 
main(int argc, char **argv) 
{ 
    // (1)load a specified file as a 3-channel color image, 
    // set its ROI, and allocate a destination image 
    const string imagename = argc > 1 ? argv[1] : "../image/building.png"; 
    Mat src_img = imread(imagename); 
    if(!src_img.data) 
    return -1; 
    Mat dst_img = src_img.clone(); 

    // (2)set ROI 
    Rect roi_rect(cvRound(src_img.cols*0.25), cvRound(src_img.rows*0.25), cvRound(src_img.cols*0.5), cvRound(src_img.rows*0.5)); 
    Mat src_roi(src_img, roi_rect); 
    Mat dst_roi(dst_img, roi_rect); 

    // (2)With specified three parameters (angle, rotation center, scale) 
    // calculate an affine transformation matrix by cv2DRotationMatrix 
    double angle = -45.0, scale = 1.0; 
    Point2d center(src_roi.cols*0.5, src_roi.rows*0.5); 
    const Mat affine_matrix = getRotationMatrix2D(center, angle, scale); 

    // (3)rotate the image by warpAffine taking the affine matrix 
    warpAffine(src_roi, dst_roi, affine_matrix, dst_roi.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar::all(255)); 

    // (4)show source and destination images with a rectangle indicating ROI 
    rectangle(src_img, roi_rect.tl(), roi_rect.br(), Scalar(255,0,255), 2); 

    namedWindow("src", CV_WINDOW_AUTOSIZE); 
    namedWindow("dst", CV_WINDOW_AUTOSIZE); 
    imshow("src", src_img); 
    imshow("dst", dst_img); 
    waitKey(0); 

    return 0; 
} 
-1
IplImage* rotate(double angle, float centreX, float centreY, IplImage* src, bool crop) 
{ 
    int w=src->width; 
    int h=src->height; 

     CvPoint2D32f centre; 
     centre.x = centreX; 
     centre.y = centreY; 

     CvMat* warp_mat = cvCreateMat(2, 3, CV_32FC1); 

     cv2DRotationMatrix(centre, angle, 1.0, warp_mat); 

     double m11= cvmGet(warp_mat,0,0); 
     double m12= cvmGet(warp_mat,0,1); 
     double m13= cvmGet(warp_mat,0,2); 
     double m21= cvmGet(warp_mat,1,0); 
     double m22= cvmGet(warp_mat,1,1); 
     double m23= cvmGet(warp_mat,1,2); 
     double m31= 0; 
     double m32= 0; 
     double m33= 1; 
     double x=0; 
     double y=0; 
     double u0= (m11*x + m12*y + m13)/(m31*x + m32*y + m33); 
     double v0= (m21*x + m22*y + m23)/(m31*x + m32*y + m33); 
     x=w; 
     y=0; 
     double u1= (m11*x + m12*y + m13)/(m31*x + m32*y + m33); 
     double v1= (m21*x + m22*y + m23)/(m31*x + m32*y + m33); 
     x=0; 
     y=h; 
     double u2= (m11*x + m12*y + m13)/(m31*x + m32*y + m33); 
     double v2= (m21*x + m22*y + m23)/(m31*x + m32*y + m33); 
     x=w; 
     y=h; 
     double u3= (m11*x + m12*y + m13)/(m31*x + m32*y + m33); 
     double v3= (m21*x + m22*y + m23)/(m31*x + m32*y + m33); 

     int left= MAX(MAX(u0,u2),0); 
     int right= MIN(MIN(u1,u3),w); 
     int top= MAX(MAX(v0,v1),0); 
     int bottom= MIN(MIN(v2,v3),h); 

     ASSERT(left<right&&top<bottom); // throw message? 
     if (left<right&&top<bottom) 
     { 
      IplImage* dst= cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, src->nChannels); 
      cvWarpAffine(src, dst, warp_mat/*, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)*/); 

      if (crop) // crop and resize to initial size 
      { 
       IplImage* dst_crop= cvCreateImage(cvSize(right-left, bottom-top), IPL_DEPTH_8U, src->nChannels); 
       cvSetImageROI(dst,cvRect(left,top,right-left,bottom-top)); 
       cvCopy(dst,dst_crop); 
       cvReleaseImage(&dst); 
       cvReleaseMat(&warp_mat); 
       //ver1 
       //return dst_crop; 
       // ver2 resize 
       IplImage* out= cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, src->nChannels); 
       cvResize(dst_crop,out); 
       cvReleaseImage(&dst_crop); 
       return out; 
      } 
      else 
      { 
       /*cvLine(dst, cvPoint(left,top),cvPoint(left, bottom), cvScalar(0, 0, 255, 0) ,1,CV_AA); 
       cvLine(dst, cvPoint(right,top),cvPoint(right, bottom), cvScalar(0, 0, 255, 0) ,1,CV_AA); 
       cvLine(dst, cvPoint(left,top),cvPoint(right, top), cvScalar(0, 0, 255, 0) ,1,CV_AA); 
       cvLine(dst, cvPoint(left,bottom),cvPoint(right, bottom), cvScalar(0, 0, 255, 0) ,1,CV_AA);*/ 
       cvReleaseMat(&warp_mat); 
       return dst; 
      } 
     } 
     else 
     { 
      return NULL; //assert? 
     } 
} 
+0

tặng một lý do downvoting! 'Nó nói câu trả lời không hữu ích'. Tại sao không? –

3

Đang cập nhật câu trả lời đầy đủ cho OpenCV 2.4 và lên

// ROTATE p by R 
/** 
* Rotate p according to rotation matrix (from getRotationMatrix2D()) R 
* @param R  Rotation matrix from getRotationMatrix2D() 
* @param p  Point2f to rotate 
* @return  Returns rotated coordinates in a Point2f 
*/ 
Point2f rotPoint(const Mat &R, const Point2f &p) 
{ 
    Point2f rp; 
    rp.x = (float)(R.at<double>(0,0)*p.x + R.at<double>(0,1)*p.y + R.at<double>(0,2)); 
    rp.y = (float)(R.at<double>(1,0)*p.x + R.at<double>(1,1)*p.y + R.at<double>(1,2)); 
    return rp; 
} 

//COMPUTE THE SIZE NEEDED TO LOSSLESSLY STORE A ROTATED IMAGE 
/** 
* Return the size needed to contain bounding box bb when rotated by R 
* @param R  Rotation matrix from getRotationMatrix2D() 
* @param bb bounding box rectangle to be rotated by R 
* @return  Size of image(width,height) that will compleley contain bb when rotated by R 
*/ 
Size rotatedImageBB(const Mat &R, const Rect &bb) 
{ 
    //Rotate the rectangle coordinates 
    vector<Point2f> rp; 
    rp.push_back(rotPoint(R,Point2f(bb.x,bb.y))); 
    rp.push_back(rotPoint(R,Point2f(bb.x + bb.width,bb.y))); 
    rp.push_back(rotPoint(R,Point2f(bb.x + bb.width,bb.y+bb.height))); 
    rp.push_back(rotPoint(R,Point2f(bb.x,bb.y+bb.height))); 
    //Find float bounding box r 
    float x = rp[0].x; 
    float y = rp[0].y; 
    float left = x, right = x, up = y, down = y; 
    for(int i = 1; i<4; ++i) 
    { 
     x = rp[i].x; 
     y = rp[i].y; 
     if(left > x) left = x; 
     if(right < x) right = x; 
     if(up > y) up = y; 
     if(down < y) down = y; 
    } 
    int w = (int)(right - left + 0.5); 
    int h = (int)(down - up + 0.5); 
    return Size(w,h); 
} 

/** 
* Rotate region "fromroi" in image "fromI" a total of "angle" degrees and put it in "toI" if toI exists. 
* If toI doesn't exist, create it such that it will hold the entire rotated region. Return toI, rotated imge 
* This will put the rotated fromroi piece of fromI into the toI image 
* 
* @param fromI  Input image to be rotated 
* @param toI  Output image if provided, (else if &toI = 0, it will create a Mat fill it with the rotated image roi, and return it). 
* @param fromroi roi region in fromI to be rotated. 
* @param angle  Angle in degrees to rotate 
* @return   Rotated image (you can ignore if you passed in toI 
*/ 
Mat rotateImage(const Mat &fromI, Mat *toI, const Rect &fromroi, double angle) 
{ 
    //CHECK STUFF 
    // you should protect against bad parameters here ... omitted ... 

    //MAKE OR GET THE "toI" MATRIX 
    Point2f cx((float)fromroi.x + (float)fromroi.width/2.0,fromroi.y + 
       (float)fromroi.height/2.0); 
    Mat R = getRotationMatrix2D(cx,angle,1); 
    Mat rotI; 
    if(toI) 
     rotI = *toI; 
    else 
    { 
     Size rs = rotatedImageBB(R, fromroi); 
     rotI.create(rs,fromI.type()); 
    } 

    //ADJUST FOR SHIFTS 
    double wdiff = (double)((cx.x - rotI.cols/2.0)); 
    double hdiff = (double)((cx.y - rotI.rows/2.0)); 
    R.at<double>(0,2) -= wdiff; //Adjust the rotation point to the middle of the dst image 
    R.at<double>(1,2) -= hdiff; 

    //ROTATE 
    warpAffine(fromI, rotI, R, rotI.size(), INTER_CUBIC, BORDER_CONSTANT, Scalar::all(0)); 

    //& OUT 
    return(rotI); 
} 
Các vấn đề liên quan