2010-05-20 102 views
2

當我使用此代碼旋轉圖像時,目標圖像大小保持不變,因此圖像被剪切。請給我一個方法/代碼片段來相應地調整大小(像Matlab在imrotate中所做的那樣),以便圖像不會被剪切,並且異常像素會被全部白色而不是黑色填充。我不希望圖像縮小到適合原始大小。我只想旋轉,不縮放。圖像旋轉OpenCV錯誤

void imrotate(std::string imgPath,std::string angleStr,std::string outPath) { 
    size_t found1,found2; 
    found1=imgPath.find_last_of('/'); 
    found2=imgPath.size()-4; 
    IplImage* src=cvLoadImage(imgPath.c_str(), -1);; 
    IplImage* dst; 
    dst = cvCloneImage(src); 
    int angle = atoi(angleStr.c_str()); 
    CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1); 
    CvPoint2D32f center = cvPoint2D32f(
     src->width/2, 
     src->height/2 
    ); 
    double scale = 1; 
    cv2DRotationMatrix(center, angle, scale, rot_mat); 
    cvWarpAffine(src, dst, rot_mat); 
    char angStr[4]; 
    sprintf(angStr,"%d",angle); 
    cvSaveImage(string(outPath+imgPath.substr(found1+1,found2-found1-1)+"_"+angStr+".jpg").c_str(),dst); 
    cvReleaseImage(&src); 
    cvReleaseImage(&dst); 
    cvReleaseMat(&rot_mat); 
} 

原始圖像:

alt text http://freeimagehosting.in/images/185_ElectricalG.jpg

旋轉圖像:

alt text http://freeimagehosting.in/images/638_ElectricalG_60.jpg

回答

2

而不是克隆源圖像,你將不得不創建大圖像的DEST足以取得最終的旋轉圖像,這將是一個正方形,兩邊是源寬o的最大值的1.5倍r高度。

編輯:

需要放大的目的地是通過1個+ SIN(旋轉角),其具有以45度的1.414最大值量...這必須四捨五入爲一個合適的值

+1

不是吧: 「......由於雙方1.414 ...倍多......」 – 2010-05-20 07:37:22

+0

1.414適當調高值......,是的 – 2010-05-20 08:09:07

1

您需要在執行旋轉之前通過填充使源圖像變大。

IplImage* src_b = cvCreateImage(cvSize(src->width+src->width/2,src->height+src->height/2), src->depth, src->nChannels); 
IplImage* dst = cvCreateImage(cvSize(src->width+src->width/2,src->height+src->height/2), src->depth, src->nChannels); 

// copy src to bigger image with white border 
CvPoint offset = cvPoint(src->width/4,+src->height/4); 
cvCopyMakeBorder(src, src_b, offset, IPL_BORDER_CONSTANT, cvScalarAll(255)); 

// find rotation matrix .... 

// Rotate with white fill 
cvWarpAffine(src_2, dst, rot_mat, CV_WARP_FILL_OUTLIERS, cvScalarAll(255)); 

這裏的圖像是1.5大而不是1.414,原因很明顯。

1

這將做你所要求的和更多。 OpenCV的2.4及以上版本:

// 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); 
}