当前位置:   article > 正文

4.OpenCV之透视转换_warpperspective( inputarray src, outputarray dst,

warpperspective( inputarray src, outputarray dst, inputarray m, s

Q1:引用传参VS指针传参的区别?

A1:关键点:区分指针和引用的区别。

指针引用
变量,独立,可变,可空,替身,无类型检查别名,依赖,不变,本体,有类型检查

C/C++引用与指针的联系

一、仿射变换和透视变换详解

二、透视变换

(一)重要函数

1. findHomography函数

  计算多个二维点对之间的最优单映射变换矩阵 H(3行x3列) ,使用最小均方误差或者RANSAC方法。
  函数功能:找到两个平面之间的变换矩阵。

Mat cv::findHomography ( InputArray srcPoints,
InputArray dstPoints,
int method = 0,
double ransacReprojThreshold = 3,
OutputArray mask = noArray(),
const int maxIters = 2000,
const double confidence = 0.995
)

在这里插入图片描述

2. warpPerspective函数

void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
参数说明:
src – 输入图像
dst – 大小为dsize且类型与src相同的输出图像
M – 3×3变换矩阵
dsize – 输出图像的大小
  图中红点即为固定顶点,在变换先后固定顶点的像素值不变,图像整体则根据变换规则进行变换。同理,透视变换是图像基于4个固定顶点的变换,如图所示:

在这里插入图片描述

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

struct imgdata
{
    Mat img;
    vector<Point2f> points;//存储操作点
};

void mouseHandle(int event, int x, int y, int flag, void *ptr)
{
    struct imgdata *data = (struct imgdata *)ptr;
    //鼠标事件获取
    if(event == EVENT_LBUTTONDOWN)//按压鼠标左键
    {
        //绘制一个标记点:BGR
        circle(data->img, Point(x, y),3,Scalar(0,0,255),3,CV_AA);
        imshow("img",data->img);
        //判断是否存储足够的标记点
        if(data->points.size()<4)
            data->points.push_back(Point2f(x,y));
    }
}
void eg1()
{
    Mat img = imread("book.webp");
    imshow("img", img);

    Mat resimg = Mat::zeros(img.rows,img.cols,CV_8UC1);//8通道

    //存储透视转换后的坐标:与原坐标相反(镜像效果
    vector<Point2f> obj;
    obj.push_back(Point2f(0,0));
    obj.push_back(Point2f(img.cols/2,0));
    obj.push_back(Point2f(img.cols/2,img.rows/2));
    obj.push_back(Point2f(0,img.rows/2));
    
    struct imgdata data;
    data.img = img;

    setMouseCallback("img", mouseHandle, &data);

    waitKey(0);//等待键盘操作
    //操作四个标记点:计算变换矩阵
    Mat res = findHomography(data.points,obj,CV_RANSAC);
    imshow("res",res);

    //透视转换
    warpPerspective(img,resimg,res,resimg.size());

    imshow("resimg", resimg);
    waitKey(0);
}
int main()
{
    eg1();
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

(二)具体实现

  透视变换结合图像处理。将一张背景图片中的某块区域替换为另一张图片透视转换后的效果图。

1. 效果展示

在这里插入图片描述

2. 核心代码

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

struct imgdata
{
    Mat img;
    vector<Point2f> points;//存储操作点
};

void mouseHandle(int event, int x, int y, int flag, void *ptr)
{
    struct imgdata *data = (struct imgdata *)ptr;
    //鼠标事件获取
    if(event == EVENT_LBUTTONDOWN)//按压鼠标左键
    {
        //绘制一个标记点:BGR
        circle(data->img, Point(x, y),3,Scalar(0,0,255),3,CV_AA);
        imshow("dst",data->img);
        //判断是否存储足够的标记点
        if(data->points.size()<4)
            data->points.push_back(Point2f(x,y));
    }
}

void eg2()
{
    Mat img1 = imread("A.png");
    imshow("img1",img1);

    Mat img2 = imread("B.png");
    imshow("img2",img2);

    vector<Point2f> obj;
    obj.push_back(Point2f(0,0));
    obj.push_back(Point2f(img1.cols,0));
    obj.push_back(Point2f(img1.cols,img1.rows));
    obj.push_back(Point2f(0,img1.rows));

    struct imgdata data;
    Mat dst = img2.clone();
    data.img = dst;
    imshow("dst",dst);

    setMouseCallback("dst", mouseHandle, &data);
    waitKey(0);//等待键盘操作

    //将需要替换的图透视变换到大图进行变换2
    Mat res = findHomography(obj, data.points, CV_RANSAC);

    //透视转换
    warpPerspective(img1, dst, res, dst.size());
    imshow("warpPerspective", dst);

    Point pts[4];
    for (int i = 0; i < 4; i++)
    {
        pts[i] = data.points[i];
    }

    //进行填充(0,0,0)
    fillConvexPoly(img2, pts, 4, Scalar(0), CV_AA);
    imshow("....", img2);

    //进行或操作
    img2 += dst;
    imshow("finally", img2);

    waitKey(0);
}

int main()
{
    eg2();
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/153535
推荐阅读
相关标签
  

闽ICP备14008679号