tutorials open docs comandos image-manipulation opencv

image-manipulation - docs - opencv tutorials



OpenCV: cómo rotar IplImage? (5)

Necesito rotar una imagen en un ángulo muy pequeño, como 1-5 grados. ¿ OpenCV proporciona una forma simple de hacer eso? De la lectura de documentos, puedo suponer que getAffineTransform () debería estar involucrado, pero no hay un ejemplo directo de hacer algo como:

IplImage *rotateImage( IplImage *source, double angle);


Actualizando la respuesta completa para OpenCV 2.4 y posteriores

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


Si usa OpenCV> 2.0 es tan fácil como

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

Nota: el ángulo está en grados, no en radianes.

Consulte la documentación de la interfaz C ++ para obtener más detalles y adaptarse según sea necesario:


Verifique mi respuesta a un problema similar:

Girar una imagen en C / C ++

Básicamente, use cvWarpAffine : describí cómo obtener la matriz de transformación 2x3 desde el ángulo en mi respuesta anterior.


Editar: Para votar abajo: ¿Por favor comente la razón por la que se rechazó votar un código probado y probado?

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

ACTUALIZACIÓN : consulte el siguiente código para la rotación utilizando warpaffine https://code.google.com/p/opencvjp-sample/source/browse/trunk/cpp/affine2_cpp.cpp?r=48

#include <cv.h> #include <highgui.h> using namespace cv; int main(int argc, char **argv) { // (1)load a specified file as a 3-channel color image, // set its ROI, and allocate a destination image const string imagename = argc > 1 ? argv[1] : "../image/building.png"; Mat src_img = imread(imagename); if(!src_img.data) return -1; Mat dst_img = src_img.clone(); // (2)set ROI 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)With specified three parameters (angle, rotation center, scale) // calculate an affine transformation matrix by cv2DRotationMatrix double angle = -45.0, scale = 1.0; Point2d center(src_roi.cols*0.5, src_roi.rows*0.5); const Mat affine_matrix = getRotationMatrix2D( center, angle, scale ); // (3)rotate the image by warpAffine taking the affine matrix warpAffine(src_roi, dst_roi, affine_matrix, dst_roi.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar::all(255)); // (4)show source and destination images with a rectangle indicating ROI rectangle(src_img, roi_rect.tl(), roi_rect.br(), Scalar(255,0,255), 2); namedWindow("src", CV_WINDOW_AUTOSIZE); namedWindow("dst", CV_WINDOW_AUTOSIZE); imshow("src", src_img); imshow("dst", dst_img); waitKey(0); return 0; }


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? } }