基本概念
在计算机视觉和图像处理领域中,透视变换(Perspective Transformation)是一种重要的几何变换,用于模拟从一个视角到另一个视角的变换,比如从鸟瞰视角到正面视角的变换。透视变换通常用于图像配准、增强现实、三维重建等场景。
透视变换的基本概念
透视变换是一种非线性的几何变换,它通过一个3x3的矩阵来描述,这个矩阵可以将一个平面的坐标映射到另一个平面上。
OpenCV中的透视变换
在OpenCV中,透视变换可以通过 warpPerspective 函数来实现。这个函数需要一个3x3的变换矩阵来指定变换。
函数原型
void warpPerspective(
InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar()
);
参数说明
•src:输入图像。
•dst:输出图像。
•M:一个3x3的透视变换矩阵。
•dsize:输出图像的大小。
•flags:插值方法,默认为 INTER_LINEAR(双线性插值)。
•borderMode:边界处理方法,默认为 BORDER_CONSTANT。
•borderValue:如果使用了 BORDER_CONSTANT,则需要指定边界值。
创建透视变换矩阵
透视变换矩阵通常是通过一组对应点来计算的。给定四组对应点,可以使用 findHomography 或 getPerspectiveTransform 函数来计算变换矩阵。
示例代码1
下面是一个使用OpenCV C++实现透视变换的示例代码:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
// 定义透视变换
void applyPerspectiveTransform(const Mat &src, Mat &dst, const Mat &M, Size dsize)
{
warpPerspective(src, dst, M, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0));
}
int main(int argc, char** argv)
{
//if (argc != 2)
//{
// cout << "Usage: ./PerspectiveTransform <Image Path>" << endl;
// return -1;
//}
// 加载图像
Mat img = imread("586.jpeg");
if (!img.data)
{
cout << "Error opening image" << endl;
return -1;
}
// 定义对应点
vector<Point2f> pts1, pts2;
// 输入图像的四个角点
pts1.push_back(Point2f(0, 0));
pts1.push_back(Point2f(img.cols, 0));
pts1.push_back(Point2f(img.cols, img.rows));
pts1.push_back(Point2f(0, img.rows));
// 输出图像的目标四个角点
pts2.push_back(Point2f(0, 0));
pts2.push_back(Point2f(img.cols / 2, 0));
pts2.push_back(Point2f(img.cols / 2, img.rows));
pts2.push_back(Point2f(0, img.rows));
// 计算透视变换矩阵
Mat M = getPerspectiveTransform(pts1, pts2);
// 定义输出图像大小
Size dsize(img.cols, img.rows);
// 初始化输出矩阵
Mat transformed;
// 应用透视变换
applyPerspectiveTransform(img, transformed, M, dsize);
// 显示结果
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
namedWindow("Flipped Center", WINDOW_NORMAL);
imshow("Flipped Center", transformed);
waitKey(0);
destroyAllWindows();
return 0;
}
代码解释
1. 加载图像:使用 imread 函数加载图像。
2. 定义对应点:定义输入图像的四个角点和输出图像的目标四个角点。
3. 计算透视变换矩阵:使用 getPerspectiveTransform 函数计算透视变换矩阵。
4. 定义输出图像大小:保持输出图像大小不变。
5. 初始化输出矩阵:创建一个新的矩阵来存储变换后的图像。
6. 应用透视变换:使用 warpPerspective 函数应用透视变换。
7. 显示结果:使用 imshow 函数显示原始图像和变换后的图像。
运行结果1
在OpenCV中,透视变换是一种非常强大的图像处理技术,它允许你在二维平面上模拟三维空间中的视点变化。这种变换特别适用于需要进行图像校正或模拟不同视角的应用场景,例如文档扫描、图像拼接等。
透视变换通常涉及一个3x3的矩阵,该矩阵可以将输入图像中的四点映射到输出图像中的另外四点。在C++中使用OpenCV进行透视变换的基本步骤如下:
在C++中使用OpenCV进行透视变换的基本步骤如下:
1. 导入必要的头文件
首先确保你的项目中包含了OpenCV的头文件。
#include <opencv2/opencv.hpp>
using namespace cv;
2. 加载图像
使用imread函数读取一幅图像,并检查是否正确加载。
Mat src = imread("path/to/image.jpg");
if (src.empty()) {
std::cout << "Error: Image not found or unable to open" << std::endl;
return -1;
}
3. 定义源点和目标点
你需要定义源图像上的四个角点以及目标图像上的对应位置。这些点应该按照顺序(例如顺时针或逆时针)指定。
Point2f src_pts[4];
Point2f dst_pts[4];
// 源点
src_pts[0] = Point2f(0, 0);
src_pts[1] = Point2f(src.cols - 1, 0);
src_pts[2] = Point2f(src.cols - 1, src.rows - 1);
src_pts[3] = Point2f(0, src.rows - 1);
// 目标点
dst_pts[0] = Point2f(0, 0);
dst_pts[1] = Point2f(dst.cols - 1, 0);
dst_pts[2] = Point2f(dst.cols - 1, dst.rows - 1);
dst_pts[3] = Point2f(0, dst.rows - 1);
4. 计算透视变换矩阵
使用getPerspectiveTransform函数来计算从源点到目标点的透视变换矩阵。
Mat M = getPerspectiveTransform(src_pts, dst_pts);
5. 应用透视变换
利用warpPerspective函数应用计算出的变换矩阵来对原始图像进行变形。
Mat dst;
warpPerspective(src, dst, M, Size(dst.cols, dst.rows));
6. 显示结果
最后,你可以使用imshow函数显示变换后的图像,并等待用户按键后退出。
namedWindow("Result", WINDOW_NORMAL);
imshow("Result", dst);
waitKey(0); // Wait for a keystroke in the window
请注意,上述代码示例中的目标图像尺寸(dst.cols 和 dst.rows)需要根据实际情况设定。如果你想要创建一个新的大小,而不是直接复制源图像的大小,可以在调用warpPerspective时指定新的尺寸。
透视变换的原理较为复杂,涉及到线性代数中的矩阵运算,如果你对数学原理感兴趣,建议深入学习相关的数学背景知识。
示例代码2
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat src = imread("89.jpeg");
if (src.empty())
{
std::cout << "Error: Image not found or unable to open" << std::endl;
return -1;
}
Point2f src_pts[4];
Point2f dst_pts[4];
//Mat dst(src.cols / 2, src.rows/2,CV_8SC3);
// 源点
src_pts[0] = Point2f(0, 0);
src_pts[1] = Point2f(src.cols - 1, 0);
src_pts[2] = Point2f(src.cols - 1, src.rows - 1);
src_pts[3] = Point2f(0, src.rows - 1);
// 目标点
dst_pts[0] = Point2f(0, 0);
// dst_pts[1] = Point2f(dst.cols - 1, 0);
//dst_pts[2] = Point2f(dst.cols - 1, dst.rows - 1);
// dst_pts[3] = Point2f(0, dst.rows - 1);
dst_pts[1] = Point2f(src.cols/2 - 1, 0);
dst_pts[2] = Point2f(src.cols / 2 - 1, src.rows/2 - 1);
dst_pts[3] = Point2f(0, src.rows / 2 - 1);
Mat M = getPerspectiveTransform(src_pts, dst_pts);
Mat dst;
warpPerspective(src, dst, M, Size(dst.cols, dst.rows));
namedWindow("源图", WINDOW_NORMAL);
imshow("源图", src);
namedWindow("Result", WINDOW_NORMAL);
imshow("Result", dst);
waitKey(0); // Wait for a keystroke in the window
return 0;
}
运行结果2
透视变换的常见应用场景
•图像配准:将两张或多张图像对齐,使它们之间的相对位置一致。
•三维重建:通过多视角的图像重建三维模型。
•增强现实:在实时视频流中添加虚拟对象,使其看起来像是在现实世界中存在。
示例代码3
计算透视变换矩阵的示例
下面是使用 findHomography 计算透视变换矩阵的示例代码:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void calculatePerspectiveTransform(const Mat &src, Mat &M, const vector<Point2f> &pts1, const vector<Point2f> &pts2)
{
// 使用findHomography计算透视变换矩阵
M = findHomography(pts1, pts2);
}
// 定义透视变换
void applyPerspectiveTransform(const Mat &src, Mat &dst, const Mat &M, Size dsize)
{
warpPerspective(src, dst, M, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0));
}
int main(int argc, char** argv)
{
/*if (argc != 2)
{
cout << "Usage: ./PerspectiveTransform <Image Path>" << endl;
return -1;
}*/
// 加载图像
Mat img = imread("896.png");
if (!img.data)
{
cout << "Error opening image" << endl;
return -1;
}
// 定义对应点
vector<Point2f> pts1, pts2;
// 输入图像的四个角点
pts1.push_back(Point2f(0, 0));
pts1.push_back(Point2f(img.cols, 0));
pts1.push_back(Point2f(img.cols, img.rows));
pts1.push_back(Point2f(0, img.rows));
// 输出图像的目标四个角点
pts2.push_back(Point2f(0, 0));
pts2.push_back(Point2f(img.cols / 2, 0));
pts2.push_back(Point2f(img.cols / 2, img.rows));
pts2.push_back(Point2f(0, img.rows));
// 计算透视变换矩阵
Mat M;
calculatePerspectiveTransform(img, M, pts1, pts2);
// 定义输出图像大小
Size dsize(img.cols, img.rows);
// 初始化输出矩阵
Mat transformed;
// 应用透视变换
applyPerspectiveTransform(img, transformed, M, dsize);
// 显示结果
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
namedWindow("Transformed Image", WINDOW_NORMAL);
imshow("Transformed Image", transformed);
waitKey(0);
destroyAllWindows();
return 0;
}
代码解释
1. 加载图像:使用 imread 函数加载图像。
2. 定义对应点:定义输入图像的四个角点和输出图像的目标四个角点。
3. 计算透视变换矩阵:使用 findHomography 函数计算透视变换矩阵。
4. 定义输出图像大小:保持输出图像大小不变。
5. 初始化输出矩阵:创建一个新的矩阵来存储变换后的图像。
6. 应用透视变换:使用 warpPerspective 函数应用透视变换。
7. 显示结果:使用 imshow 函数显示原始图像和变换后的图像。
运行结果3
通过这些示例,你应该能够理解如何在OpenCV中使用C++实现透视变换。透视变换是一个强大的工具,用于模拟复杂的视角变换。