在c/c++中,如何最好地旋转IplImage / cv :: Mat 90度? 我认为一定有比使用矩阵进行变换更好的方法,但我似乎在API和在线上找不到其他方法。
从OpenCV3.2开始,生活变得更加轻松了,现在您可以用一行代码旋转图像:
cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);
对于方向,您可以选择以下任何一项:
ROTATE_90_CLOCKWISE
ROTATE_180
ROTATE_90_COUNTERCLOCKWISE
旋转是由转置和翻转组成的。
在OpenCV中可以这样写(以下是Python示例):
img = cv.LoadImage("path_to_image.jpg")
timg = cv.CreateImage((img.height,img.width), img.depth, img.channels) # transposed image
# rotate counter-clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=0)
cv.SaveImage("rotated_counter_clockwise.jpg", timg)
# rotate clockwise
cv.Transpose(img,timg)
cv.Flip(timg,timg,flipMode=1)
cv.SaveImage("rotated_clockwise.jpg", timg)
cv2
,链接如下:https://dev59.com/snE95IYBdhLWcg3wkekf#42359233 - Eran W这是我的 Python cv2
实现:
import cv2
img=cv2.imread("path_to_image.jpg")
# rotate ccw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=0)
# rotate cw
out=cv2.transpose(img)
out=cv2.flip(out,flipCode=1)
cv2.imwrite("rotated.jpg", out)
转置更新:
你应该使用cvTranspose()
或cv::transpose()
,因为(正如你所指出的),它更有效率。同样,我建议升级到OpenCV2.0,因为大多数的cvXXX
函数只是将IplImage*
结构体转换为Mat
对象(没有深层复制)。如果你将图像存储在一个Mat
对象中,Mat.t()
将返回转置。
任意旋转:
你应该使用cvWarpAffine,在变换矩阵的一般框架下定义旋转矩阵。我强烈建议升级到OpenCV2.0,它有几个新特性以及一个封装了矩阵和图像的Mat
类。使用2.0版本可以使用warpAffine进行上述操作。
这是一个没有使用新的C++接口的示例(适用于90度、180度和270度,使用param = 1、2和3)。在使用完图像后,请记得调用cvReleaseImage
释放返回的图像。
IplImage *rotate_image(IplImage *image, int _90_degrees_steps_anti_clockwise)
{
IplImage *rotated;
if(_90_degrees_steps_anti_clockwise != 2)
rotated = cvCreateImage(cvSize(image->height, image->width), image->depth, image->nChannels);
else
rotated = cvCloneImage(image);
if(_90_degrees_steps_anti_clockwise != 2)
cvTranspose(image, rotated);
if(_90_degrees_steps_anti_clockwise == 3)
cvFlip(rotated, NULL, 1);
else if(_90_degrees_steps_anti_clockwise == 1)
cvFlip(rotated, NULL, 0);
else if(_90_degrees_steps_anti_clockwise == 2)
cvFlip(rotated, NULL, -1);
return rotated;
}
以下是我的EmguCV(OpenCV的C#端口)解决方案:
public static Image<TColor, TDepth> Rotate90<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = new Image<TColor, TDepth>(img.Height, img.Width);
CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
rot._Flip(FLIP.HORIZONTAL);
return rot;
}
public static Image<TColor, TDepth> Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = img.CopyBlank();
rot = img.Flip(FLIP.VERTICAL);
rot._Flip(FLIP.HORIZONTAL);
return rot;
}
public static void _Rotate180<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
img._Flip(FLIP.VERTICAL);
img._Flip(FLIP.HORIZONTAL);
}
public static Image<TColor, TDepth> Rotate270<TColor, TDepth>(this Image<TColor, TDepth> img)
where TColor : struct, IColor
where TDepth : new()
{
var rot = new Image<TColor, TDepth>(img.Height, img.Width);
CvInvoke.cvTranspose(img.Ptr, rot.Ptr);
rot._Flip(FLIP.VERTICAL);
return rot;
}
我在寻找一些细节,但没有找到任何示例。因此,我发布了一个transposeImage
函数,希望能帮助其他寻找直接旋转90°而不丢失数据的方法的人:
IplImage* transposeImage(IplImage* image) {
IplImage *rotated = cvCreateImage(cvSize(image->height,image->width),
IPL_DEPTH_8U,image->nChannels);
CvPoint2D32f center;
float center_val = (float)((image->width)-1) / 2;
center.x = center_val;
center.y = center_val;
CvMat *mapMatrix = cvCreateMat( 2, 3, CV_32FC1 );
cv2DRotationMatrix(center, 90, 1.0, mapMatrix);
cvWarpAffine(image, rotated, mapMatrix,
CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS,
cvScalarAll(0));
cvReleaseMat(&mapMatrix);
return rotated;
}
float center_val = (float)((image->width)-1) / 2;