Image manipulation OpenCV:如何旋转IplImage?
我需要将图像旋转很小的角度,比如1-5度。OpenCV是否提供了简单的方法?通过阅读文档,我可以假设应该涉及getAffineTransform(),但没有直接的例子可以这样做:Image manipulation OpenCV:如何旋转IplImage?,image-manipulation,opencv,Image Manipulation,Opencv,我需要将图像旋转很小的角度,比如1-5度。OpenCV是否提供了简单的方法?通过阅读文档,我可以假设应该涉及getAffineTransform(),但没有直接的例子可以这样做: IplImage *rotateImage( IplImage *source, double angle); 检查我对类似问题的回答: 本质上,使用-我在上一个回答中描述了如何从角度获取2x3变换矩阵。如果使用OpenCV>2.0,它与 using namespace cv; Mat rotateImage(c
IplImage *rotateImage( IplImage *source, double angle);
检查我对类似问题的回答:
本质上,使用-我在上一个回答中描述了如何从角度获取2x3变换矩阵。如果使用OpenCV>2.0,它与
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;
}
注意:角度以度为单位,而不是弧度
<> P>参见C++接口文档以了解更多细节并根据需要进行修改:
#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;
}
更新:请参阅以下使用WarpeAffine进行旋转的代码
#包括
#包括
使用名称空间cv;
int
主(内部argc,字符**argv)
{
//(1)将指定文件加载为3通道彩色图像,
//设置其ROI,并分配目标图像
常量字符串imagename=argc>1?argv[1]:“./image/building.png”;
Mat src_img=imread(图像名称);
如果(!src_img.data)
返回-1;
Mat dst_img=src_img.clone();
//(2)设定投资回报率
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)具有指定的三个参数(角度、旋转中心、比例)
//用CV2D旋转矩阵计算仿射变换矩阵
双角度=-45.0,比例=1.0;
点2D中心(src_roi.cols*0.5,src_roi.rows*0.5);
常数矩阵仿射矩阵=getRotationMatrix2D(中心、角度、比例);
//(3)使用仿射矩阵通过扭曲仿射旋转图像
翘曲仿射(src_roi,dst_roi,仿射矩阵,dst_roi.size(),内部线性,边界常数,标量::全部(255));
//(4)使用指示ROI的矩形显示源图像和目标图像
矩形(src_img,roi_rect.tl(),roi_rect.br(),标量(255,0255),2);
namedWindow(“src”,CV\u窗口\u自动调整大小);
namedWindow(“dst”,CV_窗口_自动调整大小);
imshow(“src”,src_img);
imshow(“dst”,dst_img);
等待键(0);
返回0;
}
IplImage*旋转(双角度、浮动中心、浮动中心、IplImage*src、bool裁剪)
{
int w=src->宽度;
int h=src->高度;
CV2D32F中心;
center.x=centreX;
centre.y=centreY;
CvMat*warp_mat=cvCreateMat(2,3,CV_32FC1);
CV2旋转矩阵(中心、角度、1.0、翘曲垫);
双m11=cvmGet(经垫,0,0);
双m12=cvmGet(经垫,0,1);
双m13=cvmGet(经垫,0,2);
双m21=cvmGet(翘曲垫,1,0);
双m22=cvmGet(翘曲垫,1,1);
双m23=cvmGet(翘曲垫,1,2);
双m31=0;
双m32=0;
双m33=1;
双x=0;
双y=0;
双u0=(m11*x+m12*y+m13)/(m31*x+m32*y+m33);
双v0=(m21*x+m22*y+m23)/(m31*x+m32*y+m33);
x=w;
y=0;
双u1=(m11*x+m12*y+m13)/(m31*x+m32*y+m33);
双v1=(m21*x+m22*y+m23)/(m31*x+m32*y+m33);
x=0;
y=h;
双u2=(m11*x+m12*y+m13)/(m31*x+m32*y+m33);
双v2=(m21*x+m22*y+m23)/(m31*x+m32*y+m33);
x=w;
y=h;
双u3=(m11*x+m12*y+m13)/(m31*x+m32*y+m33);
双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=最大值(最大值(v0,v1),0);
int-bottom=MIN(MIN(v2,v3),h);
断言(左更新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);
}
//按R旋转p
/**
*根据旋转矩阵旋转p(来自getRotationMatrix2D())R
*@param R来自getRotationMatrix2D()的旋转矩阵
*@param p Point2f要旋转
*@return返回点2f中的旋转坐标
*/
点2F旋转点(常数材料和R、常数点2F和p)
{
点2f-rp;
rp.x=(浮动)(R.at(0,0)*p.x+R.at(0,1)*p.y+R.at(0,2));
rp.y=(浮动)(R.at(1,0)*p.x+R.at(1,1)*p.y+R.at(1,2));
返回rp;
}
//计算无损存储旋转图像所需的大小
/**
*返回按R旋转时包含边界框bb所需的大小
*@param R来自getRotationMatrix2D()的旋转矩阵
*@param bb边界框矩形将按R旋转
*@返回图像的大小(宽度、高度),当按R旋转时,该图像将完全包含bb
*/
尺寸旋转图像bb(常数矩阵和R、常数矩形和bb)
{
//旋转矩形坐标
向量rp;
反向推回(旋转点(R,点2F(bb.x,bb.y));
反向推回(旋转点(R,点2F(bb.x+bb.width,bb.y));
反向推回(旋转点(R,点2F(bb.x+bb.width,bb.y+bb.height));
反向推回(旋转点(R,点2F(bb.x,bb.y+bb.height));
//查找浮点边界框r
浮动x=rp[0].x;
浮动y=rp[0].y;
左浮动=x,右浮动=x,上浮动=y,下浮动=y;
对于(inti=1;ix)left=x;
如果(右y)向上=y;
如果(向下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?
}
}
// 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);
}