目录
[opencv 图像的缩放(放大,缩小),翻转,旋转1、图像的缩放,旋转过程中为什么需要插值:2、常见的插值算法包括:3、图像的缩放,翻转,旋转:(1)图像的缩放 cv2::resize(),用于改变图像大小的函数,它可以用于图像的放大、缩小操作:函数原型:示例:将一个图像缩小为原来的一半(2)图像的翻转 cv2::flip(),用于实现图像翻转(镜像)操作的函数,它可以在水平方向、垂直方向或者同时在两个方向上进行翻转:函数原型:示例:将一个图像沿水平方向进行翻转(3)图像的旋转 cv2::warpAffine(),用于实现图像仿射变换的函数(图像仿射变换是指对图像进行平移、旋转、缩放、翻转等几何变换的操作)函数原型:示例:将一个图像按照指定角度进行旋转上面例子旋转后图像并不能保证完全可见,还需要计算旋转后图像的宽度和高度,以及旋转后中心点坐标。](#opencv 图像的缩放(放大,缩小),翻转,旋转1、图像的缩放,旋转过程中为什么需要插值:2、常见的插值算法包括:3、图像的缩放,翻转,旋转:(1)图像的缩放 cv2::resize(),用于改变图像大小的函数,它可以用于图像的放大、缩小操作:函数原型:示例:将一个图像缩小为原来的一半(2)图像的翻转 cv2::flip(),用于实现图像翻转(镜像)操作的函数,它可以在水平方向、垂直方向或者同时在两个方向上进行翻转:函数原型:示例:将一个图像沿水平方向进行翻转(3)图像的旋转 cv2::warpAffine(),用于实现图像仿射变换的函数(图像仿射变换是指对图像进行平移、旋转、缩放、翻转等几何变换的操作)函数原型:示例:将一个图像按照指定角度进行旋转上面例子旋转后图像并不能保证完全可见,还需要计算旋转后图像的宽度和高度,以及旋转后中心点坐标。)
opencv 图像的缩放(放大,缩小),翻转,旋转
1、图像的缩放,旋转过程中为什么需要插值:
通过使用适当的插值方法,可以确保图像在变换过程中保持合理的视觉品质和准确性;
(1)非整数坐标位置: 在进行缩放、翻转、旋转等变换时,新位置的坐标通常是浮点数,不一定是整数。例如,对于一个2倍放大的操作,像素的坐标会变成原来的两倍,如1.5、3.7等。但图像只能在整数坐标位置获取像素值;
(2)保持图像连续性: 插值算法可以保持图像在变换过程中的连续性和平滑性,避免出现锯齿状的边缘或形变;
2、常见的插值算法包括:
最近邻插值(cv2::INTER_NEAREST): 选择距离变换位置最近的一个像素的值作为新位置的像素值;
双线性插值(cv2::INTER_LINEAR): 使用相邻四个像素的加权平均值来估计新位置的像素值;
双三次插值(cv2::INTER_CUBIC): 使用相邻16个像素的加权平均值来估计新位置的像素值;
3、图像的缩放,翻转,旋转:
(1)图像的缩放 cv2::resize(),用于改变图像大小的函数,它可以用于图像的放大、缩小操作:
函数原型:
void cv::resize(
InputArray src,
OutputArray dst,
Size dsize,
double fx = 0,
double fy = 0,
int interpolation = INTER_LINEAR
);
参数解释:
src:输入图像;
dst:输出图像;
dsize:输出图像的大小,通常使用cv::Size()来指定;
fx:沿水平轴的缩放因子,如果设置为0,则通过 fy 来确定缩放比例;
fy:沿垂直轴的缩放因子,如果设置为0,则通过 fx 来确定缩放比例;
interpolation:插值算法(
INTER_NEAREST
INTER_LINEAR 默认
INTER_CUBIC 适合放大操作
);
示例:将一个图像缩小为原来的一半
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
//读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy4.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
imshow("src", src);
// 通过指定缩放因子,将图像缩小为原来的一半
cv::Mat amplify1, amplify2, reduce1, reduce2;
cv::resize(src, amplify1, cv::Size(), 0.5, 0.5, cv::INTER_LINEAR);
cv::imshow("amplify1", amplify1);
// 通过指定输出图像的尺寸,将图像缩小为原来的一半
int w = src.cols;
int h = src.rows;
cv::resize(src, amplify2, cv::Size(w/2, h/2), 0, 0, cv::INTER_LINEAR);
cv::imshow("amplify2", amplify2);
// 通过指定缩放因子,将图像放大为原来的1.5倍
cv::resize(src, reduce1, cv::Size(), 1.5, 1.5, cv::INTER_LINEAR);
cv::imshow("reduce1", reduce1);
// 通过指定输出图像的尺寸,将图像放大为原来的1.5倍
cv::resize(src, reduce2, cv::Size(w*1.5, h*1.5), 0, 0, cv::INTER_LINEAR);
cv::imshow("reduce2", reduce2);
waitKey();
destroyAllWindows();
return 0;
}
(2)图像的翻转 cv2::flip(),用于实现图像翻转(镜像)操作的函数,它可以在水平方向、垂直方向或者同时在两个方向上进行翻转:
函数原型:
void cv::flip(
InputArray src,
OutputArray dst,
int flipCode
);
参数解释:
src:输入图像;
dst:输出图像;
flipCode:翻转方式(
0 -> 沿x轴翻转(垂直翻转)(上下翻转)
1 -> 沿y轴翻转(水平翻转)(左右翻转)
-1 -> 同时沿x和y轴翻转(对角线翻转)
);
示例:将一个图像沿水平方向进行翻转
cs
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
//读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
imshow("src", src);
cv::Mat flipped_image;
cv::flip(src, flipped_image, 1); // 沿y轴翻转
cv::imshow("Flipped Image", flipped_image);
waitKey();
destroyAllWindows();
return 0;
}
(3)图像的旋转 cv2::warpAffine(),用于实现图像仿射变换的函数(图像仿射变换是指对图像进行平移、旋转、缩放、翻转等几何变换的操作)
void cv::warpAffine(
InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar()
);
1、参数解释:
src:输入图像;
dst:输出图像;
M:仿射变换矩阵,用于定义变换关系,这里定义的是旋转矩阵,需要借助cv2.getRotationMatrix2D()函数定义图像旋转参数,函数返回一个cv::Mat类型的矩阵,其中包含了进行旋转变换的矩阵信息;
dsize:输出图像的大小,通常使用cv::Size()来指定;
flags :插值算法(
INTER_NEAREST
INTER_LINEAR 默认
INTER_CUBIC 适合放大操作
);
borderMode:边界模式,默认为BORDER_CONSTANT常数边界模式;
borderValue:borderValue默认值等于Scalar(),表示创建一个所有通道值为0的常量颜色,
2、定义旋转矩阵:
cv::Mat cv::getRotationMatrix2D(
cv::Point2f center, // 旋转的中心坐标 (x, y),类型为cv::Point2f,使用的是浮点数作为坐标
double angle, // 旋转角度,以度为单位(正值表示逆时针旋转,负值表示顺时针旋转)
double scale // 缩放比例,可选参数,默认为1.0
);
3、注意:
const Scalar& borderValue = Scalar()表达式的含义如下:
Scalar 是OpenCV库中用于表示多通道颜色值的数据类型,可以包括1到4个通道;
borderValue 是函数的参数名,它表示用于边界填充的颜色值;
=Scalar() 表示给定参数的默认值,在这里Scalar()创建了一个所有通道值为0的标量(黑色),用于作为默认的边界填充颜色;
const修饰符,表示borderValue是一个常量引用,即在函数中不能对其进行修改;
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
//读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
//namedWindow("src", WINDOW_NORMAL);
imshow("src", src);
cv::Mat rotated_image;
// 图像src的中心点坐标
cv::Point2f center(src.cols/2.0, src.rows/2.0);
// 定义一个角度
double angle = 45.0;
// 定义了一个旋转矩阵
cv::Mat rotation_matrix = cv::getRotationMatrix2D(center, angle, 1.0);
// 将图像按照定义的rotation_matrix旋转变换的矩阵信息,进行旋转
cv::warpAffine( src, rotated_image, rotation_matrix, src.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255) );
cv::imshow("Rotated Image", rotated_image);
waitKey();
destroyAllWindows();
return 0;
}
上面例子旋转后图像并不能保证完全可见,还需要计算旋转后图像的宽度和高度,以及旋转后中心点坐标
cs
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
//读取图像,BGR存储在Mat矩阵里
Mat src = cv::imread("C:\\cpp\\image\\suzy1.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
//namedWindow("src", WINDOW_NORMAL);
imshow("src", src);
cv::Mat dst;
int w = src.cols;
int h = src.rows;
// 图像src的中心点坐标
cv::Point2f center(w/2.0, h/2.0);
// 定义一个角度
double angle = 45.0;
// 定义了一个旋转矩阵
cv::Mat M = cv::getRotationMatrix2D(center, angle, 1.0);
// 下几行代码用于调整旋转后图像的位置,确保旋转后图像完全可见
double cos = abs(M.at<double>(0, 0));
double sin = abs(M.at<double>(0, 1));
// 旋转后图像的宽度nw和高度nh
int nw = int( abs(cos)*w + abs(sin)*h );
int nh = int( abs(sin)*w + abs(cos)*h );
// 旋转后图像的中心点位置
M.at<double>(0, 2) += (nw/2 - w/2);
M.at<double>(1, 2) += (nh/2 - h/2);
// 由于计算出的 nw 和 nh 可能是浮点数,但 cv::warpAffine()函数的第四个参数(目标图像的大小)需要整数类型
cv::Size newSize(nw, nh);
// 将图像按照定义的rotation_matrix旋转变换的矩阵信息,进行旋转
cv::warpAffine( src, dst, M, newSize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 255, 255) );
cv::imshow("Rotated Image", dst);
waitKey();
destroyAllWindows();
return 0;
}