C++ 使用 OpenCV 将图像旋转 90 度的最简单方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2259678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:45:39  来源:igfitidea点击:

Easiest way to rotate by 90 degrees an image using OpenCV?

c++imageopencvrotation

提问by Ben H

What is the best way (in c/c++) to rotate an IplImage/cv::Mat by 90 degrees? I would assume that there must be something better than transforming it using a matrix, but I can't seem to find anything other than that in the API and online.

将 IplImage/cv::Mat 旋转 90 度的最佳方法是什么(在 c/c++ 中)?我认为一定有比使用矩阵转换它更好的东西,但我似乎无法在 API 和在线中找到除此之外的任何东西。

回答by sastanin

Rotation is a composition of a transpose and a flip.

旋转是转置和翻转的组合。

R_{+90} = F_x \circ T

R_{+90} = F_x \circ T

R_{-90} = F_y \circ T

R_{-90} = F_y \circ T

Which in OpenCV can be written like this (Python example below):

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

回答by Morris Franken

As of OpenCV3.2, life just got a bit easier, you can now rotate an image in a single line of code:

从 OpenCV3.2 开始,生活变得更轻松了,您现在可以在一行代码中旋转图像:

cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);

For the direction you can choose any of the following:

对于方向,您可以选择以下任何一项:

ROTATE_90_CLOCKWISE
ROTATE_180
ROTATE_90_COUNTERCLOCKWISE

回答by Jacob

Update for transposition:

换位更新:

You should use cvTranspose()or cv::transpose()because (as you rightly pointed out) it's more efficient. Again, I recommend upgrading to OpenCV2.0 since most of the cvXXXfunctions just convert IplImage*structures to Matobjects (no deep copies). If you stored the image in a Matobject, Mat.t()would return the transpose.

您应该使用cvTranspose()orcv::transpose()因为(正如您正确指出的那样)它更有效。同样,我建议升级到 OpenCV2.0,因为大多数cvXXX函数只是将IplImage*结构转换为Mat对象(没有深拷贝)。如果您将图像存储在Mat对象中,Mat.t()将返回转置。

Any rotation:

任意旋转:

You should use cvWarpAffine by defining the rotation matrix in the general framework of the transformation matrix. I would highly recommend upgrading to OpenCV2.0which has several features as well as a Matclass which encapsulates matrices and images. With 2.0 you can use warpAffineto the above.

您应该通过在转换矩阵的一般框架中定义旋转矩阵来使用 cvWarpAffine。我强烈建议升级到OpenCV2.0,它有几个特性以及一个Mat封装矩阵和图像的类。使用 2.0 你可以使用warpAffine到上面。

回答by Eran W

Here is my python cv2implementation:

这是我的pythoncv2实现:

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)

回答by Andres Hurtis

This is an example without the new C++ interface (works for 90, 180 and 270 degrees, using param = 1, 2 and 3). Remember to call cvReleaseImageon the returned image after using it.

这是一个没有新 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;
}

回答by mpen

Here's my EmguCV (a C# port of OpenCV) solution:

这是我的 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;
}

Shouldn't be too hard to translate it back into C++.

将它翻译回 C++ 应该不会太难。

回答by Artem

Well I was looking for some details and didn't find any example. So I am posting a transposeImagefunction which, I hope, will help others who are looking for a direct way to rotate 90° without losing data:

好吧,我正在寻找一些细节,但没有找到任何示例。所以我发布了一个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;
}

Question : Why this?

问题:为什么会这样?

float center_val = (float)((image->width)-1) / 2; 

Answer : Because it works :) The only center I found that doesn't translate image. Though if somebody has an explanation I would be interested.

答:因为它有效:) 我发现的唯一一个不翻译图像的中心。虽然如果有人有解释,我会感兴趣。