在 C 中的 OpenCV 中旋转图像而不进行裁剪

新手上路,请多包涵

我想旋转图像,但不裁剪就无法获得旋转图像

我的原图:

在此处输入图像描述

现在我使用这段代码:

 #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

// Compile with g++ code.cpp -lopencv_core -lopencv_highgui -lopencv_imgproc

int main()
{
    cv::Mat src = cv::imread("im.png", CV_LOAD_IMAGE_UNCHANGED);
    cv::Mat dst;

    cv::Point2f pc(src.cols/2., src.rows/2.);
    cv::Mat r = cv::getRotationMatrix2D(pc, -45, 1.0);

    cv::warpAffine(src, dst, r, src.size()); // what size I should use?

    cv::imwrite("rotated_im.png", dst);

    return 0;
}

并获得如下图像:

在此处输入图像描述

但我想得到这个:

在此处输入图像描述

原文由 Manuel Ignacio López Quintero 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

我的回答受到以下帖子/博客条目的启发:

主要观点:

  • 通过向新图像中心添加平移来调整旋转矩阵
  • 使用 cv::RotatedRect 尽可能依赖现有的opencv功能

使用 opencv 3.4.1 测试的代码:

 #include "opencv2/opencv.hpp"

int main()
{
    cv::Mat src = cv::imread("im.png", CV_LOAD_IMAGE_UNCHANGED);
    double angle = -45;

    // get rotation matrix for rotating the image around its center in pixel coordinates
    cv::Point2f center((src.cols-1)/2.0, (src.rows-1)/2.0);
    cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
    // determine bounding rectangle, center not relevant
    cv::Rect2f bbox = cv::RotatedRect(cv::Point2f(), src.size(), angle).boundingRect2f();
    // adjust transformation matrix
    rot.at<double>(0,2) += bbox.width/2.0 - src.cols/2.0;
    rot.at<double>(1,2) += bbox.height/2.0 - src.rows/2.0;

    cv::Mat dst;
    cv::warpAffine(src, dst, rot, bbox.size());
    cv::imwrite("rotated_im.png", dst);

    return 0;
}

原文由 Lars Schillingmann 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您有图像的旋转和缩放:

 #include "opencv2/opencv.hpp"
#include <functional>
#include <vector>

bool compareCoords(cv::Point2f p1, cv::Point2f p2, char coord)
{
    assert(coord == 'x' || coord == 'y');

    if (coord == 'x')
        return p1.x < p2.x;

    return p1.y < p2.y;
}

int main(int argc, char** argv)
{

    cv::Mat image = cv::imread("lenna.png");

    float angle = 45.0;  // degrees
    float scale = 0.5;
    cv::Mat_<float> rot_mat = cv::getRotationMatrix2D( cv::Point2f( 0.0f, 0.0f ), angle, scale );

    // Image corners
    cv::Point2f pA = cv::Point2f(0.0f, 0.0f);
    cv::Point2f pB = cv::Point2f(image.cols, 0.0f);
    cv::Point2f pC = cv::Point2f(image.cols, image.rows);
    cv::Point2f pD = cv::Point2f(0.0f, image.rows);

    std::vector<cv::Point2f> pts = { pA, pB, pC, pD };
    std::vector<cv::Point2f> ptsTransf;
    cv::transform(pts, ptsTransf, rot_mat );

    using namespace std::placeholders;
    float minX = std::min_element(ptsTransf.begin(), ptsTransf.end(), std::bind(compareCoords, _1, _2, 'x'))->x;
    float maxX = std::max_element(ptsTransf.begin(), ptsTransf.end(), std::bind(compareCoords, _1, _2, 'x'))->x;
    float minY = std::min_element(ptsTransf.begin(), ptsTransf.end(), std::bind(compareCoords, _1, _2, 'y'))->y;
    float maxY = std::max_element(ptsTransf.begin(), ptsTransf.end(), std::bind(compareCoords, _1, _2, 'y'))->y;

    float newW = maxX - minX;
    float newH = maxY - minY;

    cv::Mat_<float> trans_mat = (cv::Mat_<float>(2,3) << 0, 0, -minX, 0, 0, -minY);
    cv::Mat_<float> M = rot_mat + trans_mat;

    cv::Mat warpedImage;
    cv::warpAffine( image, warpedImage, M, cv::Size(newW, newH) );

    cv::imshow("lenna", image);
    cv::imshow("Warped lenna", warpedImage);

    cv::waitKey();
    cv::destroyAllWindows();
    return 0;
}

在此处输入图像描述在此处输入图像描述

原文由 orbit 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题