OpenCV Using Python——基于SURF特征提取和金字塔LK光流法的单目视觉三维重建 (光流、场景流)
https://blog.csdn.net/shadow_guo/article/details/44312691
基于SURF特征提取和金字塔LK光流法的单目视觉三维重建
1. 单目视觉三维重建问题
在前面的文章中,笔者用SIFT提取特征后用radio测试剔除了匹配中异常的特征点,然后根据匹配合格的特征点计算基础矩阵和本征矩阵,对本征矩阵SVD分解来估计和构造透视矩阵,根据透视矩阵和齐次坐标变换后的特征点三角化获得特征点在三维空间中的坐标。
(1)找不到外极线
对于运动范围过大的两幅图像,有可能计算不出外极线。经过试验发现,运动范围过大的两帧图像由于SIFT特征点检测后特征点的个数大幅下降,或句话说,SIFT检测特征点没什么问题,但radio测试踢掉了好多异常特征点,特征点个数的减少造成基础矩阵计算得不准确,所以计算外极线时会出现找不到的情况。
(2)仿射结构变化敏感
SIFT检测特征点是很精确的,但为什么检测出的特征点在估计仿射结构时会出现外极点和外极线跳动大的情况呢?个人认为有以下几个方面原因:
a)SIFT检测过精确:SIFT的精确检测剔除了很多本可以匹配的特征点,特征点过少会造成外极线检测误差大,换句话说,SIFT的精确检测结果有可能造成“过拟合”问题;不过可以试试改改SIFT库函数的输入参数,可能会解决;
b)摄像头标定的参数不准确:径向畸变略大也会导致出现扭曲的图像特征点,SIFT检测时出现误检测;
c)图像噪声未补偿:高速运动中的图像需要适当的运动补偿,如果摄像机和跟踪的对象以不同的速度运动,前景和背景同时运动,必然会产生模糊的图像使SIFT特征点检测不准确。
主要出现的问题在a)。b)多次标定摄像头可以解决;c)肉眼观察得到的图像即可判断是否出现问题。
2. 解决单目视觉三维重建问题
(1)SURF特征提取
(2)金字塔Lucas-Kanade光流法
3. 代码实现和改进
(1)代码改进
(2)代码实现
- import cv2
- import math
- import numpy as np
- from match import *
- ################################################################################
- print 'Load Image'
- img1 = cv2.imread('images/cat_1.bmp') #query image
- img2 = cv2.imread('images/cat_2.bmp') #train image
- rows, cols, channels = img1.shape
- img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
- img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
- imgGray1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
- imgGray2 = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY)
- ################################################################################
- print 'SURF Feature Detection'
- # initialize ORB object with default values
- surf = cv2.SURF(800)
- # find keypoints
- keypoint1, descriptor1 = surf.detectAndCompute(imgGray1, None)
- keypoint2, descriptor2 = surf.detectAndCompute(imgGray2, None)
- ################################################################################
- def keypointToPoint(keypoint):
- '''''
- from keypoints to points
- '''
- point = np.zeros(len(keypoint) * 2, np.float32)
- for i in range(len(keypoint)):
- point[i * 2] = keypoint[i].pt[0]
- point[i * 2 + 1] = keypoint[i].pt[1]
- point = point.reshape(-1,2)
- return point
- point1 = keypointToPoint(keypoint1)
- rightFeatures = keypointToPoint(keypoint2)
- ################################################################################
- print 'Calculate the Optical Flow Field'
- # how each left points moved across the 2 images
- lkParams = dict(winSize=(15,15), maxLevel=2, criteria=(3L,10,0.03))
- point2, status, error = cv2.calcOpticalFlowPyrLK(imgGray1, imgGray2, point1, None, **lkParams)
- # filter out points with high error
- rightLowErrPoints = {}
- for i in range(len(point2)):
- if status[i][0] == 1 and error[i][0] < 12:
- rightLowErrPoints[i] = point2[i]
- else:
- status[i] = 0
- bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
- matches = bf.match(descriptor1, descriptor2)
- print 'matches:', len(matches)
- dist = []
- for m in matches:
- dist.append(m.distance)
- # distance threshold
- thresDist = np.median(dist)
- good = []
- for m in matches:
- if m.distance < thresDist:
- good.append(m)
- print 'Good Matches:', len(good)
- ################################################################################
- # select keypoints from good matches
- points1 = []
- points2 = []
- for m in good:
- points1.append(keypoint1[m.queryIdx].pt)
- points2.append(keypoint2[m.trainIdx].pt)
- points1 = np.float32(points1)
- points2 = np.float32(points2)
- ################################################################################
- # combine two images into one
- view = drawMatches(img1, img2, points1, points2, colors)
- img5, img3 = drawEpilines(img1, img2, points1, points2)
- displayMatchImage(view, img5, img3)
- # camera matrix from calibration
- K = np.array([[517.67386649, 0.0, 268.65952163], [0.0, 519.75461699, 215.58959128], [0.0, 0.0, 1.0]])
- P, P1, E = calcPespectiveMat(K, F)
- pointCloudX, pointCloudY, pointCloudZ, reprojError = triangulatePoints(points1, points2, K, E, P, P1)
- positionX, positionY, positionZ = transformToPosition(pointCloudX, pointCloudY, pointCloudZ, P1, K, scale=10.0)
- plotPointCloud(positionX, positionY, positionZ, colors)
- ################################################################################
- print 'Goodbye!'
4. 实验结果
(1)基于SIFT特征提取的重建结果
(2)基于SURF特征点提取和金字塔LK光流法的重建结果
结语
OpenCV Using Python——基于SURF特征提取和金字塔LK光流法的单目视觉三维重建 (光流、场景流)的更多相关文章
- OpenCV之Python学习笔记
OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...
- OpenCV:Python下OpenCV安装和入门最强详细攻略
一.关于OpenCV简介 OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效— ...
- opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较
opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较 参考: http://wenku.baidu.com/link?url=1aDYAJBCrrK-uk2w3sSNai7h52x_ ...
- 基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一) 一直有计划研究实时图像拼接,但是直到最近拜读西电2013年张亚娟的<基于SURF特征的图像与视频拼接技术的研究和实现>,条 ...
- OpenCV特征点检测------Surf(特征点篇)
Surf(Speed Up Robust Feature) Surf算法的原理 ...
- [PyImageSearch] Ubuntu16.04 使用OpenCV和python识别信用卡 OCR
在今天的博文中,我将演示如何使用模板匹配作为OCR的一种形式来帮助我们创建一个自动识别信用卡并从图像中提取相关信用卡数位的解决方案. 今天的博文分为三部分. 在第一部分中,我们将讨论OCR-A字体,这 ...
- 深度学习 + OpenCV,Python实现实时视频目标检测
使用 OpenCV 和 Python 对实时视频流进行深度学习目标检测是非常简单的,我们只需要组合一些合适的代码,接入实时视频,随后加入原有的目标检测功能. 在本文中我们将学习如何扩展原有的目标检测项 ...
- OpenCV特征点检测——Surf(特征点篇)&flann
学习OpenCV--Surf(特征点篇)&flann 分类: OpenCV特征篇计算机视觉 2012-04-20 21:55 19887人阅读评论(20)收藏举报 检测特征 Surf(Spee ...
- 跟我学Python图像处理丨关于图像金字塔的图像向下取样和向上取样
摘要:本文讲述图像金字塔知识,了解专门用于图像向上采样和向下采样的pyrUp()和pyrDown()函数. 本文分享自华为云社区<[Python图像处理] 二十一.图像金字塔之图像向下取样和向上 ...
随机推荐
- linux下配置Java_web环境
I安装JDK 1下载jdk*.bin/jdk*.rpm文件 2把安装包copy到安装目录 cp jdk*.bin /www/java 3安装JDK 如果是.bin文件,直接在复制的当前目录执行即可 . ...
- MySQL NDB集群安装配置(mysql cluster 9.4.13 installation)
一.安装前规划 1.安装软件版本:mysql-cluster-gpl-7.4.13-linux-glibc2.5-x86_64.tar.gz 2.安装规划: 主机名 Ip地址 角色 db01 192. ...
- Implicit declaration of function 'BMKCoordinateForMapPoint' is invalid in C99
少一个头文件 #import <BaiduMapAPI_Utils/BMKGeometry.h> 加上这个就好了 <HPHalfScreenTopBar: 0x103570bb0; ...
- hmm用于speech和image
隐马尔科夫模型用于speech和image的原因是,因为hmm模型主要是适用于前后特征有关联性(参考骰子案例)的数据,有三种模式, 其中一种模式就是通过数据输出判断来源分类,而speech和image ...
- php 中date显示时间不对与Linux文件乱码问题
php 中date显示时间不对解决办法如下1.修改/etc/php.ini文件 在里头中找到data.timezone =去掉它前面的分号';' 然后设置data.timezone = “Asia/S ...
- 聊一聊Linux中的工作队列
2018-01-18 工作队列是Linux内核中把工作延迟执行的一种手段,其目的不同于软中断,软中断是提高CPU的响应,尽可能的缩短关中断的时间:而工作队列主要目的是节省资源,其比较适合很微小的任务, ...
- 【JS】自学
JS自学网址: http://www.runoob.com/js/js-tutorial.html
- SQL SERVER深入学习学习资料参考
SQL SERVER深入学习学习资料参考 1.微软Webcast<sql server 2000完结篇>. 尽管微软Webcast出了很多关于Sql Server的系列课程,但是最为深入讲 ...
- 虚拟机中实现Linux与Windows之间的文件传输
虚拟机中实现Linux与Windows之间的文件传输 标签: linux 2016年06月28日 11:17:37 2092人阅读 评论(0) 收藏 举报 分类: linux(2) 一.配置环 ...
- idea 连接数据库
1:如果没有数据库连接插件,下载database插件 settings>plugin>Database Navigator 下载. 2:重启 3:进入 view>tool windo ...