前言
一、透视变换的概念
二、透视变换工作原理
三、相关函数
1.findHomography函数
2.warpPerspective函数
3.getPerspectiveTransform函数
四、透视变换案例
案例1:文稿矫正
案例2:广告屏换图
五、总结
本文以实现广告屏换图为目标,学习OpenCV透视变化相关知识,核心的内容包括:OpenCV透视变化概念、透视变化工作原理,以及广告屏换图、文稿矫正的实现
- 仿射变换与透视变换在图像还原、图像局部变化处理方面有重要意义
- 通常情况下,在2D平面中,仿射变换的应用较多,在3D平面中,透视变换又有了自己的一席之地,两种变换原理相似,结果也类似,可针对不同的场合使用适当的变换
- 仿射变换和透视变换的数学原理不需深究,在应用层面,仿射变换是图像基于3个固定顶点的变换,如下图所示:
函数功能:找到两个平面之间的变换矩阵
参数:如下表所示
函数功能:对图像进行透视变换,变形
参数:
- src – 输入图像
- dst – 大小为dsize且类型与src相同的输出图像
- M – 3×3变换矩阵
- dsize – 输出图像的大小
函数功能:根据源图像和目标图像上的四对点坐标来计算从原图像透视变换到目标头像的透视变换矩阵
参数:
- src – 源图像中四边形顶点的坐标
- dst – 目标图像中相应四边形顶点的坐标
案例1 完整代码
#include
#include
using namespace cv;
using namespace std;
struct imagedata
{
Mat img;//目标图像
vector points;//3D点
};
//鼠标操作函数:用于选择四个角的点(使用方法有顺序的,从左上角顺时针选择,选完之后回车)
void mouseHundle(int event,int x,int y,int flag,void *per)
{
struct imagedata * d=(struct imagedata*)per;
if(event==EVENT_LBUTTONDOWN)
{
//确定按下的是鼠标左键
//用圆形标记一下鼠标按下左键标记的位置
circle(d->img,Point(x,y),3,Scalar(0,255,0),3,CV_AA);//在图上标记,圆心为点击的位置
imshow("image",d->img);//原窗口上显示
if(d->points.size()<4)
{
d->points.push_back(Point2f(x,y));//把点击的点存起来
}
}
}
void example_1()
{
Mat image=imread("C:/Users/86177/Desktop/image/777.jpg");
Mat result=Mat::zeros(400,500,CV_8UC1);//400*500的大小,但是里面没有东西
//存放四个转换以后的坐标
vector obj;
obj.push_back(Point2f(0,0));
obj.push_back(Point2f(500,0));
obj.push_back(Point2f(500,400));
obj.push_back(Point2f(0,400));//转换后的坐标
imshow("image",image);
struct imagedata data;
data.img=image;
setMouseCallback("image",mouseHundle,&data);//鼠标处理的回调函数
waitKey(0);//按任意键关闭当前显示的窗口,显示下一个窗口
Mat res=findHomography(data.points,obj,CV_RANSAC);//利用RANSAC算法计算出来一个小矩阵
warpPerspective(image,result,res,result.size()); //结果转换
imshow("result",result);
waitKey(0);
}
int main(int argc, char *argv[])
{
example_1();
return 0;
}
案例2 完整代码
#include
#include
using namespace cv;
using namespace std;
struct imagedata
{
Mat img;//目标图像
vector points;//3D点
};
//鼠标操作函数:用于选择四个角的点(使用方法有顺序的,从左上角顺时针选择,选完之后回车)
void mouseHundle(int event,int x,int y,int flag,void *ptr)
{
struct imagedata * d=(struct imagedata*)ptr;
if(event==EVENT_LBUTTONDOWN)
{
//确定按下的是鼠标左键
//用圆形标记一下鼠标按下左键标记的位置
circle(d->img,Point(x,y),3,Scalar(0,255,0),3,CV_AA);//在图上标记,圆心为点击的位置
//imshow("image",d->img);//原窗口上显示
imshow("dst",d->img);//原窗口上显示
if(d->points.size()<4)//只存下来,最先点的前四个点
{
d->points.push_back(Point2f(x,y));//把鼠标操作点击的点存起来
}
}
}
void example_2()
{
Mat image1=imread("C:/Users/86177/Desktop/image/2222.jpg");//广告屏替换图片路径
Mat image2=imread("C:/Users/86177/Desktop/image/city.jpg");//背景图片路径
Mat dst=image2.clone();//克隆
vector obj;
obj.push_back(Point2f(0,0));
obj.push_back(Point2f(image1.cols,0));
obj.push_back(Point2f(image1.cols,image1.rows));
obj.push_back(Point2f(0,image1.rows));//转换后的坐标
imshow("dst",dst);
struct imagedata data;
data.img =dst;
setMouseCallback("dst",mouseHundle,&data);//鼠标处理的回调函数
waitKey(0);//按任意键关闭当前显示的窗口,显示下一个窗口
Mat res=findHomography(obj,data.points,CV_RANSAC);//利用RANSAC算法,3*3变换矩阵
warpPerspective(image1,dst,res,dst.size());//透视转换
imshow("warpPerspective",dst);
Point pts[4];
for(int i=0;i<4;i++)
{
pts[i]=data.points[i];
}
fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
image2+=dst;
imshow("final",image2);
waitKey(0);
}
int main(int argc, char *argv[])
{
example_2();
return 0;
}
PS: 案例代码使用说明,需要选择四个点,且必须顺时针选择,因为代码中只设置存储4个点,超出选择无效,选择完毕后按 Enter 即可显示效果
- 本文核心内容包括:OpenCV透视变化概念、透视变化工作原理
- 以广告屏换图、文稿矫正的实现为例子,讲解了OpenCV透视变化的实战案例,案例完成的效果还是挺有意思的!
- 在我们的日常生活中,已经有很多软件用到了我们的透视变换的知识,例如,我们办公扫描文件时用的扫描软件,很大程度上,节省了我们的时间,提高了工作效率!
以上就是本文的全部内容啦!如果对您有帮助,麻烦点赞啦!收藏啦!欢迎各位评论区留言!! !