簡體   English   中英

圖像旋轉OpenCV錯誤

[英]Image rotate OpenCV error

當我使用此代碼旋轉圖像時,目標圖像大小保持不變,因此圖像被裁剪。 請向我提供一種方法/代碼段,以進行相應的調整大小(例如Matlab進行旋轉),以免圖像被裁剪,異常像素被全白而不是黑色填充。 我不希望圖像按比例縮小以適合原始大小。 我只想旋轉,不縮放。

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

原始圖片:

替代文字http://freeimagehosting.in/images/185_ElectricalG.jpg

旋轉圖像:

替代文字http://freeimagehosting.in/images/638_ElectricalG_60.jpg

無需克隆源圖像作為目標,您將必須創建足夠大的圖像以拍攝最終旋轉的圖像,該圖像將是一個正方形,其邊長為源寬度或高度的1.5倍。

編輯:

將目標放大所需的數量為1 + sin(旋轉角度),最大值在45度為1.414 ...必須四舍五入為合適的值

這將滿足您的要求,甚至更多。 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);
}

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

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.414大1.5。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM