OpenCV C++ 图像几何变换详解:插值缩放、翻转、旋转与 ROI 提取

在图像处理领域,经常需要对图像进行各种几何变换,例如缩放、翻转、旋转以及提取感兴趣区域(ROI)。这些操作不仅能帮助我们预处理图像数据,还能用于数据增强、目标定位等任务。本文将介绍如何使用 OpenCV C++ 实现以下功能:

  • 图片插值缩放
  • 图片翻转
  • 图片旋转
  • 图片 ROI 提取

下面我们将详细讲解每个操作的原理、函数使用及示例代码。

1. 图片插值缩放

图片缩放常用于图像大小调整、数据增强和多尺度分析。OpenCV 提供的 cv::resize 函数可以根据指定的目标尺寸或者缩放因子对图像进行缩放,支持多种插值方法,包括最近邻插值、双线性插值、立方插值等。插值方法查询

主要函数

void cv::resize(InputArray src, OutputArray dst, Size dsize,
                double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
  • src:输入图像
  • dst:输出图像
  • dsize:目标尺寸(宽、高);若设置为 Size() 则通过 fx、fy 缩放
  • fx, fy:沿 x 和 y 方向的缩放因子
  • interpolation:插值方法(常用:INTER_NEAREST、INTER_LINEAR、INTER_CUBIC 等)

参考代码

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    // 读取图像
    Mat image = imread("E:/image/lena.png");
    if (image.empty()) {
        std::cerr << "加载图像失败!" << std::endl;
        return -1;
    }

    // 缩放到目标尺寸
    Mat resizedImage;
    resize(image, resizedImage, Size(800, 600), 0, 0, INTER_LINEAR);

    // 或者使用缩放因子 fx=0.5, fy=0.5
    Mat scaledImage;
    resize(image, scaledImage, Size(), 0.5, 0.5, INTER_CUBIC);

    imshow("Original", image);
    imshow("Resized", resizedImage);
    imshow("Scaled", scaledImage);
    waitKey(0);
    return 0;
}

2. 图片翻转

图片翻转常用于数据增强、镜像效果展示以及图像对称性分析。OpenCV 提供了 cv::flip 函数,可以沿水平方向、垂直方向或者同时翻转。

主要函数

void cv::flip(InputArray src, OutputArray dst, int flipCode);
  • src:输入图像
  • dst:输出图像
  • flipCode
    • 0:垂直翻转
    • 1:水平翻转
    • < 0:同时垂直和水平翻转

参考代码

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    Mat image = imread("image.jpg");
    if(image.empty()){
        std::cerr << "加载图像失败!" << std::endl;
        return -1;
    }

    Mat flipHorizontal, flipVertical, flipBoth;
    // 水平翻转
    flip(image, flipHorizontal, 1);
    // 垂直翻转
    flip(image, flipVertical, 0);
    // 同时水平和垂直翻转
    flip(image, flipBoth, -1);

    imshow("Original", image);
    imshow("Flip Horizontal", flipHorizontal);
    imshow("Flip Vertical", flipVertical);
    imshow("Flip Both", flipBoth);
    waitKey(0);
    return 0;
}

该示例展示了如何根据不同的 flipCode 参数实现图像翻转,为数据增强提供了简单而有效的方式。

3. 图片旋转

图片旋转在图像对齐、目标检测和增强处理中十分常用。OpenCV 通常结合 cv::getRotationMatrix2Dcv::warpAffine 来实现图像旋转。

主要函数

  • cv::getRotationMatrix2D:计算旋转矩阵
Mat cv::getRotationMatrix2D(Point2f center, double angle, double scale);
  • center:旋转中心
  • angle:旋转角度(逆时针为正)
  • scale:缩放因子

cv::warpAffine:对图像应用仿射变换

void cv::warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize);
  • M:旋转矩阵
  • dsize:输出图像尺寸
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    Mat image = imread("E:/image/lena.png");
    if (image.empty()) {
        std::cerr << "加载图像失败!" << std::endl;
        return -1;
    }

    // 定义旋转中心为图像中心,旋转 45 度,缩放因子为 1
    Point2f center(image.cols / 2.0, image.rows / 2.0);
    Mat rotationMat = getRotationMatrix2D(center, 45, 1);

    // 计算旋转后的图像尺寸(可选)
    Mat rotatedImage;
    warpAffine(image, rotatedImage, rotationMat, image.size());

    imshow("Original", image);
    imshow("Rotated", rotatedImage);
    waitKey(0);
    return 0;
}

上述代码实现了以图像中心为旋转中心的 45 度旋转。

对于旋转后图像的尺寸处理,可以根据需要调整输出图像尺寸,防止部分内容被裁剪。
关于重新计算图片大小公式参考网友图:

在这里插入图片描述
参考代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 读取图像
    Mat image = imread("E:/image/lena.png");
    if (image.empty()) {
        cerr << "加载图像失败!" << endl;
        return -1;
    }

    // 旋转角度
    double angle = 45.0;

    // 计算旋转矩阵
    Point2f center(image.cols / 2.0, image.rows / 2.0);
    Mat rotationMat = getRotationMatrix2D(center, angle, 1.0);

    // 计算旋转后的新尺寸
    double cosA = abs(rotationMat.at<double>(0, 0));
    double sinA = abs(rotationMat.at<double>(0, 1));
    int newWidth = int(image.rows * sinA + image.cols * cosA);
    int newHeight = int(image.rows * cosA + image.cols * sinA);

    // 调整旋转矩阵的平移量,确保图像完整显示
    rotationMat.at<double>(0, 2) += (newWidth - image.cols) / 2.0;
    rotationMat.at<double>(1, 2) += (newHeight - image.rows) / 2.0;

    // 进行仿射变换
    Mat rotatedImage;
    warpAffine(image, rotatedImage, rotationMat, Size(newWidth, newHeight));

    // 显示结果
    imshow("Original", image);
    imshow("Rotated", rotatedImage);
    waitKey(0);

    return 0;
}

优化点

  1. 计算新图像尺寸
    • 旋转后图像的宽度 newWidth = rows * sin(angle) + cols * cos(angle)
    • 旋转后图像的高度 newHeight = rows * cos(angle) + cols * sin(angle)
  2. 调整平移量
    • rotationMat.at<double>(0,2)rotationMat.at<double>(1,2) 分别调整 X、Y 方向的偏移,使旋转后的图像居中。

这样,旋转后的图像可以完整保留,不会被裁剪!

4. 图片 ROI(感兴趣区域)提取

图像 ROI 提取指的是从原始图像中截取一个矩形区域进行单独处理。ROI 常用于目标跟踪、特征提取和图像分割等任务。OpenCV 通过对 cv::Mat 对象使用 cv::Rect 来实现 ROI 提取。

参考代码

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    Mat image = imread("image.jpg");
    if(image.empty()){
        std::cerr << "加载图像失败!" << std::endl;
        return -1;
    }

    // 定义 ROI 区域,左上角坐标 (100, 100),宽度 200,高度 150
    Rect roi(100, 100, 200, 150);
    Mat imageROI = image(roi);

    imshow("Original", image);
    imshow("ROI", imageROI);
    waitKey(0);
    return 0;
}

在该示例中,通过定义 cv::Rect 对象,我们轻松从原始图像中提取出了一个区域进行后续处理。

5. 小结

本文详细介绍了 OpenCV C++ 中常用的几何变换操作,包括:

  • 插值缩放:使用 cv::resize 函数调整图像尺寸,并选择合适的插值方法;
  • 图片翻转:利用 cv::flip 函数实现水平、垂直或双向翻转;
  • 图片旋转:通过 cv::getRotationMatrix2Dcv::warpAffine 组合实现图像旋转;
  • 图片 ROI 提取:使用 cv::Rect 从图像中截取感兴趣区域。
  • 透视变换

这些基本操作在图像预处理、数据增强以及特定应用中都发挥着重要作用。希望这篇博文能帮助大家更好地掌握 OpenCV 图像几何变换的技术,为后续项目开发提供有力支持!

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐