[英]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.