14.OpenCV C++ 图像几何变换详解:插值缩放、翻转、旋转与 ROI 提取
在图像处理领域,经常需要对图像进行各种几何变换,例如缩放、翻转、旋转以及提取感兴趣区域(ROI)。这些操作不仅能帮助我们预处理图像数据,还能用于数据增强、目标定位等任务。函数可以根据指定的目标尺寸或者缩放因子对图像进行缩放,支持多种插值方法,包括最近邻插值、双线性插值、立方插值等。OpenCV 提供的 cv::resize。对于旋转后图像的尺寸处理,可以根据需要调整输出图像尺寸,防止部分内容被裁剪
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::getRotationMatrix2D 和 cv::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;
}
优化点
- 计算新图像尺寸:
- 旋转后图像的宽度
newWidth = rows * sin(angle) + cols * cos(angle) - 旋转后图像的高度
newHeight = rows * cos(angle) + cols * sin(angle)
- 旋转后图像的宽度
- 调整平移量:
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::getRotationMatrix2D和cv::warpAffine组合实现图像旋转; - 图片 ROI 提取:使用
cv::Rect从图像中截取感兴趣区域。 - 透视变换
这些基本操作在图像预处理、数据增强以及特定应用中都发挥着重要作用。希望这篇博文能帮助大家更好地掌握 OpenCV 图像几何变换的技术,为后续项目开发提供有力支持!
更多推荐
所有评论(0)