C++ OpenCV透视变换改进

Stella981
• 阅读 677

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为4379,预计阅读11分钟

前言

前一篇《 C++ OpenCV透视变换综合练习》中针对透视变换做了一个小练习,上篇中我们用多边形拟合的点集来计算离最小旋转矩形最近的点来定义为透视变换的点,效果是有,无意间又想了一个新的思路,在原来的点的基础上效果会更好一点,其中就用到了直线拟合的方法,今天这篇就说一下优化的思路及直线拟合的函数。

C++ OpenCV透视变换改进

实现效果

C++ OpenCV透视变换改进

C++ OpenCV透视变换改进

放大图

直线拟合函数

C++ OpenCV透视变换改进

微卡智享

  void cv::fitLine(

参数说明:

  • points: 用于拟合直线的输入点集,可以是二维点的cv::Mat数组,也可以是二维点的STL vector。

  • line: 输出的直线,对于二维直线而言类型为cv::Vec4f,对于三维直线类型则是cv::Vec6f,输出参数的前半部分给出的是直线的方向,而后半部分给出的是直线上的一点(即通常所说的点斜式直线)。

  • distType: 距离类型,拟合直线时,要使输入点到拟合直线的距离和最小化(即下面公式中的cost最小化),可供选的距离类型如下表所示,ri表示的是输入的点到直线的距离。

    CV_DIST_USER =-1, /* User defined distance */

  • param:距离参数,跟所选的距离类型有关,值可以设置为0,cv::fitLine()函数本身会自动选择最优化的值。

  • reps:拟合直线所需要的径向精度,一般设置为0.01或1e-2。

  • **aeps:**拟合直线所需要的角度精度,一般设置为0.01或1e-2。

实现思路

C++ OpenCV透视变换改进

微卡智享

步骤

1

旋转矩形的点和上一步获取的最近点设置一个阈值距离,在距离内的都列入当前区域的直线拟合点,超过阈值的用最近点加上阈值重新算为计算点来进行拟合

2

根据不同区域计算直线拟合

3

求到的直线拟合点实现每两条求交点

4

得到的4个交点做为透视变换的坐标点

01

阈值范围内的直线拟合

C++ OpenCV透视变换改进

先以左边区域为例,首先我们设定了一个距离为15的阈值,白色的是我们上一篇中求到的最近的点(点1和2),蓝色为最小旋转矩形的角点(点3和4),我们通过计算点1到点3的距离,还有点2到点4的距离都小于15,那我们把这4个点都列入到左边区域,用来计算直接拟合。

C++ OpenCV透视变换改进紫色线即为上面4个点采用直线拟合后的结果

左边的区域拟合直线,因为都在阈值内,所以拟合出的直线比原来只求最近点连起来的效果要更好一点。接下来我们看看超过阈值的处理。

02

超出阈值的直线拟合

C++ OpenCV透视变换改进

上图中可以看到,右下的区域点在阈值范围内是无问题了,右上的旋转矩形角点(点4)与最近点(点2)距离挺远,肯定超出阈值了,如果还把点4也加入到拟合点计算的话,直线会多出来不少,所以我们就在根据(点2)的坐标,在X轴和Y轴都加上阈值的范围,计算出新的拟合点,即上图红圈标识的,用点1,点2,点3和红色拟合点来进行直线拟合,得到的效果如下:

C++ OpenCV透视变换改进

03

每两条直线拟合求交点

C++ OpenCV透视变换改进

直线拟合的函数,输出的参数line里面有说到了是Vec4f的类型,输出参数的前半部分给出的是直线的方向,而后半部分给出的是直线上的一点(即通常所说的点斜式直线)。

方程式:y-y1=k(x-x1)

其中(x1,y1)为坐标系上过直线的一点的坐标,k为该直线的斜率。

推导:若直线L1经过点P1(x1,y1),且斜率为k,求L1方程。

设点P(x,y)是直线上不同于点P1的任意一点,直线PP1的斜率应等于直线L1的斜率,根据经过两点的直线的斜率公式得k=(y-y1)/(x-x1) (且:x≠x1)

所以,直线L1:y-y1=k(x-x1)

说明:

(1)这个方程是由直线上一点和斜率确定的,这一点必须在直线上,否则点斜式方程不成立;

(2)当直线l的倾斜角为0°时,直线方程为y=y1;

(3)当直线倾斜角为90°时,直线没有斜率,它的方程不能用点斜式表示,这时直线方程为x=x1。

我们直线拟合的得到的4个Vec4f就需要每两个求交点最后得到上图中红圈的1,2,3,4的4个交点。根据斜率和点的计算

kk1*x+b1=kk2*x+b2

可以得到:x=(b2-b1)/(kk1-kk2) 

进而得到:y=(kk1*(b2-b1)/(kk1-kk2))+b1

核心代码

C++ OpenCV透视变换改进

微卡智享

重新计算区域及直线拟合的函数

定义的默认阈值是15。

//采用重新定义点做直线拟合后找到的对应点

根据两点及斜率求交点

//求两条直线的交叉点

透视变换的新坐标代码

上一篇中透视变换的新坐标我们直接是用的最小外接矩形的4个点,不过个别图中会矩形特别大,整个透视变换后的拉伸有点太夸张了,所以这里我们改了方法,先求出最小旋转矩形中最左和最上的坐标,然后计算出最小旋转矩形的长和高,来定义一个新的矩形进行透视变换。

        //根据最小矩形和多边形拟合的最大四个点计算透视变换矩阵    

C++ OpenCV透视变换改进

C++ OpenCV透视变换改进

扫描二维码

获取更多精彩

微卡智享

C++ OpenCV透视变换改进

「 往期文章 」

.net5发布在Windows2008的几个注意事项

C++ OpenCV透视变换综合练习

.Net5 Windows Form App中Linq的分组查询使用

本文分享自微信公众号 - 微卡智享(VaccaeShare)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
翼
3年前
js 数组 转为树形结构
需要转换为树形的数组vardata{"orderById":null,"platformCommissionProportion":1,"name":"添加剂","pid":13,"id":26
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
C++ OpenCV透视变换综合练习
学更好的别人,做更好的自己。——《微卡智享》本文长度为3879字,预计阅读9分钟前言以前的文章《COpenCV之透视变换(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fmp
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这