7.8透视变换

基本概念

在计算机视觉和图像处理领域中,透视变换(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++实现透视变换。透视变换是一个强大的工具,用于模拟复杂的视角变换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值