OpenCV-透视变换及对二维点求透视变换之后的坐标
OpenCV-透视变换及对二维点求透视变换之后的坐标
微信公众号:幼儿园的学霸
个人的学习笔记,关于OpenCV,关于机器学习, …。问题或建议,请公众号留言;
目录
前言
基本原理
OpenCV透视变换函数代码
前言
在做车道线检测中用到了透视变换的一点内容,用于将相机拍摄的图像转换到道路平行的视角下,即鸟瞰图,然后在鸟瞰图中进行车道线检测。
如图1、图2所示分别为相机拍摄的原始图像和逆透视变换后的图像,一般来说逆透视变换后的两条车道线应该是平行的,此处不平行应是透视变换矩阵没有选好,在实际项目中发现没有影响,毕竟图2中过滤掉了大部分杂乱线段。此处对逆透视变换内容进行记录,方便日后查找。
图1 原始图像
图2 鸟瞰图
基本原理
透视变换(Perspective Transformation)是将成像投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。如图3,通过透视变换ABC变换到A'B'C'。
图3 透视变换示意
透视变换通用公式为:
其中为源图像的像素坐标,为源图像变换后的点所对应的像素坐标。透视变换矩阵可以拆程如下4个部分:
,表示图像的线性变换,比如scaling,shearing和ratotion,产生透视变换,用于平移。
根据透视变换的通用公式,可以得到透视变换的数学表达式为:
从上面的计算公式可以看到,透视变换部分是其分母,而线性变换和平移部分是作为分子存在的。
因此,给定透视变换对应的四对点坐标,可以求得透视变换矩阵;反之,给定透视变换矩阵,也可以对图像或者坐标点完成透视变换。
OpenCV透视变换函数
在我所写车道线检测代码中,透视变换部分用到了以下3个函数
//用于求得透视变换的变换矩阵,
//src::源图像上的四个顶点坐标
//dst::src的坐标在目标图像上的对应坐标
//返回值:3X3的透视变换矩阵
//在车道线检测代码中作用:得到将原始图转换到鸟瞰图的转换矩阵
cv::Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst)
//求得点/点数组在经过变换矩阵m后的对应坐标
//src:目标点,如鸟瞰图中的坐标
//m:src到dst的转换矩阵
//dst:src经过m转换后的对应点
在车道线检测代码中作用:将鸟瞰图中的车道线坐标转换到原始视图下的像素作弊码
void perspectiveTransform(InputArray src, OutputArray dst, InputArray m ) //对图像进行透视变换
//src:输入图像
//dst:输出图像
//M:变换矩阵,如getPerspectiveTransform函数得到的矩阵
//dsize:目标图像的大小
//flags:目标图像的插值方法
//borderMode:外推方法
//borderValue:常量边界时使用
//在车道线检测代码中作用:
// 1.将原始图像转换到鸟瞰图中,进行车道线检测;
// 2.将鸟瞰图转换到原始视图下,以进行结果展示等
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
代码
代码示例如下。该代码流程为:
1.通过4对点计算透视变换矩阵T;
2.利用T对图像进行逆透视变换得到鸟瞰图;
3.将鸟瞰图下的车道线坐标转换到正常视图下;
该流程和我项目中的流程一致,但展示的代码比较简单,仅做示例。
如图4所示为鸟瞰图下的车道线,图5位转换到原始视图视角下的车道线。
图4 鸟瞰图及其车道线
图5 原始视图及其车道线
具体代码:
//====================================================================//
// Created by liheng on 19-2-12.
//Program:将逆透视变换后的坐标点转换到原图中
//Data:2019.2.12
//Author:liheng
//Version:V1.0
//====================================================================//#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>int main()
{//首先读入图像cv::Mat srcImage = cv::imread("../pictures/000177.png",cv::IMREAD_GRAYSCALE);//定义源点和目标点,源点为正常读入的图像的点,目标点为转换后的鸟瞰图上的对应点cv::Point2f srcPoints[4],dstPoints[4];srcPoints[0] = cv::Point2f(369,375);srcPoints[1] = cv::Point2f(545,221);srcPoints[2] = cv::Point2f(650,221);srcPoints[3] = cv::Point2f(793,375);dstPoints[0] = cv::Point2f(339,375);dstPoints[1] = cv::Point2f(339,211);dstPoints[2] = cv::Point2f(823,211);dstPoints[3] = cv::Point2f(823,375);//1°求解变换矩阵cv::Mat m_persctiveMat = cv::getPerspectiveTransform(srcPoints,dstPoints);//读入图像转换为鸟瞰图的矩阵cv::Mat m_unPersctiveMat =cv::getPerspectiveTransform(dstPoints,srcPoints);//鸟瞰图到原始图像的转换矩阵//2°求解鸟瞰图cv::Mat birdViewImage;cv::warpPerspective(srcImage,birdViewImage,m_persctiveMat,cv::Size(srcImage.cols,srcImage.rows),cv::INTER_LINEAR);//鸟瞰图车道线上的两点.Note:此处为了简单,仅选择2点进行变换std::vector<cv::Point2f> leftLine,rightLine;leftLine.push_back(cv::Point2f(661,0));leftLine.push_back(cv::Point2f(366,376));rightLine.push_back(cv::Point2f(1097,0));rightLine.push_back(cv::Point2f(883,376));//3°求解其在原始图像上对应的坐标std::vector<cv::Point2f> unWarpedLeftLine,unWarpedRightLine;cv::perspectiveTransform(leftLine,unWarpedLeftLine,m_unPersctiveMat);cv::perspectiveTransform(rightLine,unWarpedRightLine,m_unPersctiveMat);//线段可视化cv::cvtColor(srcImage,srcImage,CV_GRAY2BGR);cv::line(srcImage,unWarpedLeftLine[0],unWarpedLeftLine[1],cv::Scalar(0,255,0),2);cv::line(srcImage,unWarpedRightLine[0],unWarpedRightLine[1],cv::Scalar(0,255,0),2);cv::cvtColor(birdViewImage,birdViewImage,CV_GRAY2BGR);cv::line(birdViewImage,leftLine[0],leftLine[1],cv::Scalar(0,255,0),2);cv::line(birdViewImage,rightLine[0],rightLine[1],cv::Scalar(0,255,0),2);cv::imshow("srcImage",srcImage);cv::imshow("birdViewImage",birdViewImage);cv::waitKey(0);return 0;
}
下面的是我的公众号二维码图片,欢迎关注。
图注:幼儿园的学霸
OpenCV-透视变换及对二维点求透视变换之后的坐标相关推荐
- python做直方图-python OpenCV学习笔记实现二维直方图
本文介绍了python OpenCV学习笔记实现二维直方图,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/dd/d0d/tutorial_py_2d ...
- 【opencv有趣应用】二维码和条形码的检测
今天学习下使用opencv进行条形码和二维码的检测 import cv2 import numpy as np from pyzbar.pyzbar import decodedef cv_show_ ...
- python3 + opencv +pyzbar实时检测二维码 / 定位二维码,并绘制出二维码的框和提取二维码内容
python3 + opencv +pyzbar实时检测二维码 / 定位二维码,并绘制出二维码的框和提取二维码内容 1 pyzbar二维码检测模块 1.1. pyzbar模块介绍 1.2 pyzbar ...
- Java使用opencv调用微信扫描二维码引擎,附带windows和linux需要的动态库文件
前言 最近公司项目有一个需求,要用二维码传递数据.于是使用了zxing生成和解析二维码,但是zxing扫描二维码原图还可以,一旦扫描用户使用手机拍摄的二维码,识别率急剧下降.尝试了对拍摄的照片进行降噪 ...
- 《C#零基础入门之百识百例》(五十二)封装介绍 -- 二维多项式求值
C#零基础入门 面向对象 -- 封装介绍 -- 二维多项式求值 前言 一,封装概念 二,封装属性 三,实例练习 -- 二维多项式求值 3.1 题目描述 3.2 问题分析 3.3 参考代码 前言 本文属 ...
- c语言二维数组对角线输出字符,用C编程一个4*4的矩阵,用二维数组,求对角线元素的和。,c语言如何使二维数组 输出为矩阵的形式...
导航:网站首页 > 用C编程一个4*4的矩阵,用二维数组,求对角线元素的和.,c语言如何使二维数组 输出为矩阵的形式 用C编程一个4*4的矩阵,用二维数组,求对角线元素的和.,c语言如何使二维数 ...
- 树莓派4b + python3 + pyzbar + opencv + 摄像头 扫描识别二维码(寻找最大的二维码)
前言 最近需要做一个扫码乘车的功能,于是使用树莓派的摄像头扫描二维码来做一个demo . 网上有部分人用的是zbar这个库,但是我安装后,发现并不能在Python3上使用,这就有点不太好了.经过我的多 ...
- 二维搜索求函数极值的python程序
二维搜索,也就是优化两个未知变量,通常将二维搜索转化为一维搜索进行求解. 例题 二维搜索转一维--黄金分割 求函数二维函数A在某区间的最大值 A=( 6 - 2×l + l×cos(θ) ) × l× ...
- C语言求二维数组平均数,一道JavaScript的二维数组求平均数的题
JavaScript中只支持一维数组,但是可以在数组中嵌套数组来创建二维以至于多维的数组.今天下午在看书时候,发现一道感觉比较有意思的题,就是js中如何求二维数组的列之和和行之和,现在就给大家分享下, ...
最新文章
- Tensorflow【实战Google深度学习框架】使用 TFLearn 实现逻辑运算符
- java根据日期生成表主键_java 利用时间生成主键
- 思科超融合:主推HyperFlex,押注HCI
- 如何利用CNKI句子检索功能提高研究效率
- matlab高斯滤波跟中值滤波区别,matlab图像滤波处理代码讲解 均值滤波 中值滤波 高斯滤波...
- 数学系鄙视物理系的经典桥段,全部看懂了算我输!
- wepy组件子父传值_【WePY小程序框架实战三】-组件传值
- 将海量文件用split切割清单,并逐一处理
- Redis 发布订阅
- 设计模式笔记十六:解释器模式
- 旷视申请赴港IPO:阿里蚂蚁金服持股近30%
- 面试—每日一题(7)
- 中国体力活动监测器(PAM)市场趋势报告、技术动态创新及市场预测
- 超链接a标签的伪类选择器问题,Link标签与visited标签的失效问题(问题介绍与解决方法)。以下全部内容跟可通过鼠标左键选取后,复制到编辑器中直接运行。
- Python之路-4
- java类的引用使用即String类的toUpperCase的使用
- 【2019秋招】OPPO无线通信协议工程师笔试
- RK px30 配置ap6212 wifi bt流程记录
- Monaco Editor教程(十八):使用api来完成某些键盘操作,格式化,查找,显示右侧菜单等。
- 计算机主机电源接线,七个步骤教你主机电源如何接线