将图像旋转90度,180度或270度

1''*_*1'' 27 opencv rotation

我需要将图像旋转90度,180度或270度.在OpenCV4Android中我可以使用:

Imgproc.getRotationMatrix2D(new Point(center, center), degrees, 1);
Imgproc.warpAffine(src, dst, rotationMatrix, dst.size());
Run Code Online (Sandbox Code Playgroud)

但是,这是我的图像处理算法的一个巨大瓶颈.当然,通过90度的倍数的简单旋转比最一般的情况简单得多warpAffine,并且可以更有效地完成.例如,对于180度,我可以使用:

Core.flip(src, dst, -1);
Run Code Online (Sandbox Code Playgroud)

其中-1表示翻转水平轴和垂直轴.是否有类似的优化我可以用于90或270度旋转?

Ste*_*ing 45

我不太了解java api,这个代码是由c ++开发的.逻辑应该是相同的,使用transpose + flip来旋转90n的图像(n属于N = - 最小值int,.....,-3,-2,-1,0,1,2, 3,...,int的最大值)

/*
 *@brief rotate image by multiple of 90 degrees
 *
 *@param source : input image
 *@param dst : output image
 *@param angle : factor of 90, even it is not factor of 90, the angle
 * will be mapped to the range of [-360, 360].
 * {angle = 90n; n = {-4, -3, -2, -1, 0, 1, 2, 3, 4} }
 * if angle bigger than 360 or smaller than -360, the angle will
 * be map to -360 ~ 360.
 * mapping rule is : angle = ((angle / 90) % 4) * 90;
 *
 * ex : 89 will map to 0, 98 to 90, 179 to 90, 270 to 3, 360 to 0.
 *
 */
void rotate_image_90n(cv::Mat &src, cv::Mat &dst, int angle)
{   
   if(src.data != dst.data){
       src.copyTo(dst);
   }

   angle = ((angle / 90) % 4) * 90;

   //0 : flip vertical; 1 flip horizontal
   bool const flip_horizontal_or_vertical = angle > 0 ? 1 : 0;
   int const number = std::abs(angle / 90);          

   for(int i = 0; i != number; ++i){
       cv::transpose(dst, dst);
       cv::flip(dst, dst, flip_horizontal_or_vertical);
   }
}
Run Code Online (Sandbox Code Playgroud)

编辑:提高性能,感谢TimZaman的评论和1''的实施

void rotate_90n(cv::Mat const &src, cv::Mat &dst, int angle)
{        
     CV_Assert(angle % 90 == 0 && angle <= 360 && angle >= -360);
     if(angle == 270 || angle == -90){
        // Rotate clockwise 270 degrees
        cv::transpose(src, dst);
        cv::flip(dst, dst, 0);
    }else if(angle == 180 || angle == -180){
        // Rotate clockwise 180 degrees
        cv::flip(src, dst, -1);
    }else if(angle == 90 || angle == -270){
        // Rotate clockwise 90 degrees
        cv::transpose(src, dst);
        cv::flip(dst, dst, 1);
    }else if(angle == 360 || angle == 0 || angle == -360){
        if(src.data != dst.data){
            src.copyTo(dst);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你的循环使它比必要的配合更昂贵. (2认同)

小智 15

这是您使用谷歌时的第一个结果,这些解决方案都没有真正回答这个问题,或者是正确还是简洁.

Core.rotate(Mat src, Mat dst, Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE
Run Code Online (Sandbox Code Playgroud)


Joe*_*ply 9

这将以任意度数旋转图像,使用最有效的方法为90的倍数.

    void
    rotate_cw(const cv::Mat& image, cv::Mat& dest, int degrees)
    {
        switch (degrees % 360) {
            case 0:
                dest = image.clone();
                break;
            case 90:
                cv::flip(image.t(), dest, 1);
                break;
            case 180:
                cv::flip(image, dest, -1);
                break;
            case 270:
                cv::flip(image.t(), dest, 0);
                break;
            default:
                cv::Mat r = cv::getRotationMatrix2D({image.cols/2.0F, image.rows/2.0F}, degrees, 1.0);
                int len = std::max(image.cols, image.rows);
                cv::warpAffine(image, dest, r, cv::Size(len, len));
                break; //image size will change
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是使用opencv 3.0,只需通过cv :: rotate命令即可完成:

cv::rotate(image, dest, e.g. cv::ROTATE_90_COUNTERCLOCKWISE);
Run Code Online (Sandbox Code Playgroud)


1''*_*1'' 6

这是使用Android API的解决方案.在这里,我用它来旋转相机的图像,可以安装在各种方向.

if (mCameraOrientation == 270) {
    // Rotate clockwise 270 degrees
    Core.flip(src.t(), dst, 0);
} else if (mCameraOrientation == 180) {
    // Rotate clockwise 180 degrees
    Core.flip(src, dst, -1);
} else if (mCameraOrientation == 90) {
    // Rotate clockwise 90 degrees
    Core.flip(src.t(), dst, 1);
} else if (mCameraOrientation == 0) {
    // No rotation
    dst = src;
}
Run Code Online (Sandbox Code Playgroud)