OpenCV透视变换应用之书本视图矫正+广告屏幕切换

 更新时间:2022年08月03日 15:42:12   作者:我今年十六岁  
透视变换是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面绕迹线旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。本文将为大家介绍两个OpenCV透视变换应用,需要的可以参考一下

一、透视变换的实际应用场景

我们在出门坐车时,经常会看到司机会使用一种行车辅助工具,这其中就使用到了透视变换的相关操作,协助司机安全行车。

可以看出,自身小车周围路况的正常显示,便利了司机的行车操作 

像这种透视变换的实际生活应用,其实还有许多,接下来,我们就来学习一下OpenCV的透视变换

二、案例了解透视变换--书本视图矫正

原图:

目标:需要使用透视变换 将书桌上的课本 正视视角查看

结果展示:

书本视图矫正完整代码如下:【这里是鼠标点击从左上角开始顺时针选取4个点透视变换】

#include <iostream>
#include <opencv2/opencv.hpp>
#include<vector>
using namespace cv;
using namespace std;
 
//鼠标操作 自己准备结构体
struct imagedata
{
    Mat img;//目标图像 用于点击 确定坐标
    vector<Point2f> points;//存放原图的坐标 通过鼠标的点击进行存放
};
 
//鼠标操作的回调函数:用于选择四个角的点(使用方法:从左上角开始顺时针选择四个点,选完之后回车操作)
void mouseHundle(int event,int x,int y,int flag,void *arg)
{
    //强制转换
    struct imagedata * d = (struct imagedata*)arg;
    //如果按下的是鼠标左键
    if(event==EVENT_LBUTTONDOWN)
    {
        //用圆形来标记下鼠标按下左键标记的位置
        circle(d->img,Point(x,y),3,Scalar(255,0,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("D:/00000000000003jieduanshipincailliao/book2.jpg");
    Mat result=Mat::zeros(400,500,CV_8UC1);//最终结果显示 单通道
 
    //准备坐标:存放四个转换以后的坐标
    vector<Point2f>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);
 
    //利用RANSAC算法  计算得到转换映射矩阵3*3
    Mat res=findHomography(data.points,obj,CV_RANSAC);
    //查看转换矩阵
    //imshow("res",res);
 
    //原图转换出来结果图
    warpPerspective(image,result,res,result.size());
    //查看转换结果图 透视变换
    imshow("result",result);
 
    waitKey(0);
}
 
int main(int argc, char *argv[])
{
    example_1();
    return 0;
}

以上是使用鼠标点击确定坐标,当然,我们也可以在代码中写上选定的坐标进行透视变换的相关操作。 依然选取左上角开始顺时针坐标选取,这里以左上角为例,其他三个点可以类比左上角坐标选择来确定下坐标选取

可以看到左上角坐标 x=282,y=43

自己定下透视变换使用到的四个坐标 直接回车 即可查看透视变换结果

    //鼠标操作  鼠标处理的回调函数
    //setMouseCallback("image",mouseHundle,&data);
 
    //不使用鼠标点击,自己定下透视变换的四个坐标
    vector<Point2f>src;
    src.push_back(Point2f(283,134));
    src.push_back(Point2f(745,234));
    src.push_back(Point2f(578,463));
    src.push_back(Point2f(61,299));
 
    //按任意键关闭当前显示的窗口,显示下一个窗口
    waitKey(0);
 
    //利用RANSAC算法  计算得到转换映射矩阵3*3
    Mat res=findHomography(src,obj,CV_RANSAC);
    //查看转换矩阵
    //imshow("res",res);

程序运行 直接回车操作 查看

三、案例了解透视变换--广告屏幕切换

背景图片: 

想要切换的广告图片: 

目标:选择广告屏幕 切换 广告屏幕内容

结果:广告屏上面的 内容推荐 成功切换成自己想要切换的广告图片

实现方法:处理后两张图片的叠加,就是先将想要更换的广告屏填充黑色背景图,再将自己想要的广告图片 两张图片叠加就能达到切换广告屏幕的效果

广告屏幕切换完整代码如下:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
 
struct imagedata
{
    Mat img;//目标图像
    vector <Point2f> 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(255,0,0),3,CV_AA);//在图上标记,圆心为点击的位置
 
        imshow("dst",d->img);//在dst背景图中显示鼠标选取的图片
 
        if(d->points.size()<4)//只存下来,最先点的前四个点
        {
            d->points.push_back(Point2f(x,y));//把鼠标操作点击的点存起来
        }
    }
}
 
void example_2()
{
    Mat image1=imread("D:/00000000000003jieduanshipincailliao/0802.jpg");//想要切换的广告内容
    Mat image2=imread("D:/00000000000003jieduanshipincailliao/city.jpg");//纽约时代广场图片背景
 
    Mat dst=image2.clone();//背景图片 克隆
 
    //存放原图坐标 想要切换的广告屏图片
    vector <Point2f>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);
 
    //计算得到转换映射矩阵 3*3  原图坐标转换为鼠标选择
    Mat res = findHomography(obj,data.points,CV_RANSAC);
    //imshow("res",res);
    //透视变换
    warpPerspective(image1,dst,res,dst.size());
    //仅有的却换后的广告图图片
    //imshow("image1",dst);
 
    Point pts[4];
    for(int i=0;i<4;i++)
    {
        pts[i]=data.points[i];
    }
    //鼠标点选的四个坐标的区域填充成黑色
    fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
    //imshow("image2",image2);
 
    //将仅有的却换后的广告图图片 和  鼠标点选的四个坐标的区域填充成黑色的背景图图片 叠加
    image2+=dst;
    //显示出最后广告换屏结果图片
    imshow("final",image2);
 
    waitKey(0);
}
 
int main(int argc, char *argv[])
{
    example_2();
    return 0;
}

到此这篇关于OpenCV透视变换应用之书本视图矫正+广告屏幕切换的文章就介绍到这了,更多相关OpenCV透视变换应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言malloc分配问题详解

    C语言malloc分配问题详解

    这篇文章主要介绍了c语言 malloc函数的分配问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • strcat 函数的使用指南

    strcat 函数的使用指南

    strcat是连接字符串的函数。函数返回指针,两个参数都是指针,第一个参数所指向的内存的地址必须能容纳两个字符串连接后的大小。
    2015-09-09
  • C++中的动态规划子序列问题分析探讨

    C++中的动态规划子序列问题分析探讨

    可能有些读者有接触过动态规划,可能也有一些读者以前完全不知道动态规划这个东西,别担心,我这篇文章会为读者做一个入门,好让读者掌握这个重要的知识点
    2023-03-03
  • 深入分析为Visual Assist设置快捷键的方法

    深入分析为Visual Assist设置快捷键的方法

    本篇文章是对为Visual Assist设置快捷键的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言、C++中的union用法总结

    C语言、C++中的union用法总结

    这篇文章主要介绍了C语言、C++中的union用法总结,本文讲解了什么是union、C中使用union、当union遇到对象等内容,需要的朋友可以参考下
    2014-10-10
  • C++变量初始化形式及其默认初始值问题

    C++变量初始化形式及其默认初始值问题

    这篇文章主要介绍了C++变量初始化形式及其默认初始值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • C++17中std::string_view的使用

    C++17中std::string_view的使用

    std::string_view是C++17标准库中的一种新类型,它提供了对一个字符序列的非拥有式视图,本文主要介绍了C++17中std::string_view的使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • C++实现神经BP神经网络

    C++实现神经BP神经网络

    这篇文章主要为大家详细介绍了C++实现神经BP神经网络,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • 详解C语言中的fopen()函数和fdopen()函数

    详解C语言中的fopen()函数和fdopen()函数

    这篇文章主要介绍了详解C语言中的fopen()函数和fdopen()函数,注意其之间指针功能相关的区别,需要的朋友可以参考下
    2015-08-08
  • C++如何在构造函数和析构函数中调用虚拟函数

    C++如何在构造函数和析构函数中调用虚拟函数

    这篇文章主要介绍了C++如何在构造函数和析构函数中调用虚拟函数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08

最新评论