2010-05-20 2 views
2

Lorsque j'utilise ce code pour faire pivoter l'image, la taille de l'image de destination reste la même et l'image est donc tronquée. Veuillez me fournir un extrait de code/way pour le redimensionner en conséquence (comme le fait Matlab dans imrotate) afin que l'image ne soit pas coupée et que les pixels aberrants soient remplis de tout blanc au lieu de noir. Je ne veux pas que l'image soit réduite pour correspondre à la taille d'origine. Je veux juste la rotation, pas d'échelle.Rotation de l'image Erreur 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); 
} 

image originale:

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

pivotée Image:

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

Répondre

2

lieu de cloner l'image source en tant que dest vous allez devoir créer une image grand assez pour prendre l'image pivotée finale, qui sera un carré avec des côtés 1,5 fois le plus grand de la largeur de la source o r hauteur.

Edit:

Le montant dont vous avez besoin pour agrandir la destination par est 1 + sin (angle de rotation), qui a une valeur maximale à 45 degrés de 1,414 ... Ce doit être arrondi à un approprié valeur

+1

est-il pas: "... un carré 1,414 ... fois ..." –

+0

a convenablement arrondi valeur de 1,414 ..., oui –

1

Vous devez agrandir l'image source en effectuant un bourrage avant d'effectuer la rotation.

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

Ici l'image est 1.5 plus grande au lieu de 1.414 pour des raisons évidentes.

1

Cela fera ce que vous demandez et plus encore. OpenCV 2.4 et au-dessus:

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