关键词:相机位姿估计 OpenCV::solvePnP labview三维图片

文章类型:应用展示+Demo演示

@Author:VShawn(singlex@foxmail.com)

@Date:2016-12-12

@Lab: CvLab202@CSU

目录

  • 《相机位姿估计0:基本原理之如何解PNP问题》
  • 《相机位姿估计1:根据四个特征点估计相机姿态》
  • 《相机位姿估计1_1:OpenCV:solvePnP二次封装与性能测试》
  • 《相机位姿估计2:[应用]实时位姿估计与三维重建相机姿态》
  • 《相机位姿估计3:根据两幅图像的位姿估计结果求某点的世界坐标》

前言

本文将展示一个实时相机位姿估计的例程,其中的原理在前文中已经说过了,再利用《相机位姿估计1_1:OpenCV、solvePnP二次封装与性能测试》中构建的类,使得程序处理更加简单。本例程利用HSV空间,跟踪红色的特征点,将跟踪到的特征点用于解PNP问题,得到相机位姿(相机的世界坐标与相机的三个旋转角)。最后使用labview中的三维图片控件,对整个系统进行3D重建。

处理流程

  1. 首先初始化工业相机,采集到实时图像,使用imshow显示图片。
  2. 在实时的相机采图中,依次选取P1、P2、P3、P4(在前文《相机位姿估计1:根据共面四点估计相机姿态》中有提及),一定要按顺序点,否则无法获得正确位姿。选取完成后立即对该点进行追踪。
  3. 当跟踪的特征点数量达到4个时,程序开始调用PNPSolver类估计相机位姿。
  4. 将得到的位姿信息写入txt,位于D盘根目录(这就是上一篇文章中为什么要写文件的原因)。
  5. Labview程序运行后不断读取txt,将读到的位姿数据应用到3D中,绘制出正确的三维场景。(这里两个进程通过txt通讯效率很低,但我偷懒了,没有再去编写更好的程序)

用流程图来表示就是:

过程非常简单,C++程序用来计算位姿,labview程序用于显示。

(对于不懂labview的读者:也可以通过OpenGL来实现显示部分)

特征点跟踪方法

为了偷懒省事,这里的特征点跟踪直接使用了最简单的跟踪颜色的方法。我做的标志图是这样的:

每个特征点都是红色马克笔涂出的红点。

在实际操作中用户首先在显示界面中按照顺序(程序中点的世界坐标输入顺序)点击特征点,得到特征点的初始位置。根据初始位置,在其附近选取ROI,将BGR图像转为HSV图像进行颜色分割,针对其H通道进行二值化,将红色区域置为255,得到二值图像。在二值图像中查找连通域,并计算出连通域的重心G的位置,将G的坐标作为本次跟踪结果返回,并作为下一次跟踪的起点。

效果如下图,图中绿色的圈是以重心G为圆心绘制的。

函数如下:

//跟踪特征点
//在输入点附近查找红色区域,求出重心,作为特征点新的位置
//输入为,1当前图像,2被跟踪特征点上一轮的位置
//返回本次跟踪结果
cv::Point2f tracking(cv::Mat image, const cv::Point2f lastcenter)
{//cv::GaussianBlur(image, image, cv::Size(11, 11), 0);/***********初始化ROI**********/const int r = 100;//检测半径const int r2 = r * 2;int startx = lastcenter.x - r;int starty = lastcenter.y - r;if (startx < 0)startx = 0;if (starty < 0)starty = 0;int width = r2;int height = r2;if (startx + width >= image.size().width)startx = image.size().width - 1 - width;if (starty + height >= image.size().height)starty = image.size().height - 1 - height;cv::Mat roi = image(cv::Rect(startx, starty, width, height));cv::Mat roiHSV;cv::cvtColor(roi, roiHSV, CV_BGR2HSV);//将BGR图像转为HSV图像vector<cv::Mat> hsv;cv::split(roiHSV, hsv);//将hsv三个通道分离cv::Mat h = hsv[0];cv::Mat s = hsv[1];cv::Mat v = hsv[2];cv::Mat roiBinary = cv::Mat::zeros(roi.size(), CV_8U);//二值图像,255的地方表示判断为红色/*************判断颜色****************/const double ts = 0.5 * 255;//s阈值,小于该值不判断const double tv = 0.1 * 255;//v阈值,小于该值不判断const double th = 0 * 180 / 360;//h中心const double thadd = 30 * 180 / 360;//h范围在th±thadd内的才被算作是红色//通过特定阈值,对HSV图像进行二值化for (int i = 0; i < roi.size().height; i++){uchar *ptrh = h.ptr<uchar>(i);uchar *ptrs = s.ptr<uchar>(i);uchar *ptrv = v.ptr<uchar>(i);uchar *ptrbin = roiBinary.ptr<uchar>(i);for (int j = 0; j < roi.size().width; j++){if (ptrs[j] < ts || ptrv[j] < tv)continue;if (th + thadd > 180)if (ptrh[j] < th - thadd && ptrh[j] > th + thadd - 180)continue;if (th - thadd < 0)if (ptrh[j] < th - thadd + 180 && ptrh[j] > th + thadd)continue;ptrbin[j] = 255;//找出红色的像素点,在对应位置标记255}}/*****************对二值化图像求出连通域 重心****************/std::vector<std::vector<cv::Point>> contours;cv::findContours(roiBinary.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//可能会有多个连通域,分别计算出他们的重心std::vector<cv::Point2f> gravityCenters;//重心点集for (int i = 0; i < contours.size(); i++){if (contours[i].size() < 10)//连通域太小continue;int xsum = 0;int ysum = 0;for (int j = 0; j < contours[i].size(); j++){xsum += contours[i][j].x;ysum += contours[i][j].y;}double gpx = xsum / contours[i].size();double gpy = ysum / contours[i].size();gravityCenters.push_back(cv::Point2f(gpx + startx, gpy + starty));}/*********************返回最优点******************///找到重心跟上一轮位置最接近的那个cv::Point ret = lastcenter;double dist = 1000000000;double distX = 1000000000;double distY = 1000000000;for (int i = 0; i < gravityCenters.size(); i++){if (distX > abs(lastcenter.x - gravityCenters[i].x) && distY > abs(lastcenter.y - gravityCenters[i].y)){double newdist = sqrt((lastcenter.x - gravityCenters[i].x)*(lastcenter.x - gravityCenters[i].x) + (lastcenter.y - gravityCenters[i].y)*(lastcenter.y - gravityCenters[i].y));if (dist > newdist){distX = abs(lastcenter.x - gravityCenters[i].x);distY = abs(lastcenter.y - gravityCenters[i].y);dist = newdist;ret = gravityCenters[i];}}}return ret;
}

位姿估计

当用户点击了四个特征点后,程序开始运行位姿估计部分。位姿具体的过程不再叙述,请参考前面的博文:

《相机位姿估计1:根据四个特征点估计相机姿态》

《相机位姿估计1_1:OpenCV:solvePnP二次封装与性能测试》

三维显示

位姿估计完成后,会输出两个txt用于记录相机当前的位姿。

Labview程序就是读取这两个txt的信息,进而显示出三维空间。labview程序的编程过程比较难叙述,思路便是首先建立世界坐标系,然后在世界坐标系中创建一个三维物体作为相机的三维模型。然后根据txt中的信息,设置这个模型所在的位置(也就是三维坐标),再设置该模型的三个自旋角,完成三维绘制。

上述流程可以运行项目文件夹中的:

~\用LabView重建相机位置\世界-手动调整参数设置相机位姿.vi

来手动设置参数,体验绘图的流程。

对该部分感兴趣的人可以参考文档:

http://zone.ni.com/reference/zhs-XX/help/371361J-0118/lvhowto/create_3d_scene/

效果演示

这演示以前也有放出来过,就是实时跟踪特征点,再在右边重建相机姿态。

程序下载

最后给出例程,例程C++部分基于VS2013开发,使用的是OpenCV2.4.X,三维重建部分使用Labview2012开发。OpenCV配置参考我的博客《OpenCV2+入门系列(一):OpenCV2.4.9的安装与测试》,Labview则是直接安装好就行。

例程下载后,需要将图像采集部分修改为你的相机驱动,然后修改相机参数、畸变参数就能够使用了。

地址:

C++程序:Github

LabView程序:Github

转载于:https://www.cnblogs.com/singlex/p/pose_estimation_2.html

相机位姿估计2:[应用]实时位姿估计与三维重建相机姿态相关推荐

  1. 相机矫正_实战 | 我用位姿解算实现单目相机测距

    在项目过程中,总遇到需要单目视觉给出目标测距信息的情况,其实单目相机本不适合测距,即使能给出,精度也有限,只能在有限制的条件下或者对精度要求很不高的情况下进行应用.该文结合SLAM方法,通过3D-2D ...

  2. 无需人脸检测,实时6自由度3维人脸姿态估计img2pose

    效果图: 提出了一种实时的6自由度3D人脸姿态估计方法,其不依赖于人脸检测和关键点对齐.我们观察到直接估计6自由度刚体变换是一个比在3D人脸对齐中广泛使用的关键点检测更简单的问题.基于此我们做出了一下 ...

  3. ECCV 2022 | 视频插帧中的实时中间流估计

    概述 视频插帧算法旨在视频的相邻帧之间生成若干个中间帧.它被广泛用于视频处理,多媒体播放器和显示设备上. 本文提出了一种基于实时中间流估计的视频插帧算法 RIFE,包括一个端到端的高效的中间流估计网络 ...

  4. 动作分析 姿态估计_关于大片人物特效少不了的人体姿态估计,这里有一份综述文章...

    大片中的人物特效如何实现,少不了应用人体姿态估计.这篇博客简介了使用深度学习技术的多人姿态估计方法,及其应用. 人体姿态骨架图 (skeleton) 用图形格式表示人的动作.本质上,它是一组坐标,连接 ...

  5. 【数字信号处理】相关函数应用 ( 时差估计 | TOA 时差估计使用场景 | TDOA 时差估计使用场景 )

    文章目录 一.时差估计 二.TOA 时差估计使用场景 三.TDOA 时差估计使用场景 一.时差估计 时差估计 : 时差估计 主要用于 确定 某个发射信号 的位置 , 是 目标定位 跟踪 的 关键技术 ...

  6. 2020-4-12 深度学习笔记18 - 直面配分函数 5 ( 去噪得分匹配,噪声对比估计NCE--绕开配分函数,估计配分函数)

    第十八章 直面配分函数 Confronting the Partition Function 中文 英文 2020-4-8 深度学习笔记18 - 直面配分函数 1 ( 配分函数概念,对数似然梯度) 2 ...

  7. Halcon单相机标定—标定板标定和自标定 线扫相机标定

    一.标定板标定 13.0 ************************************************************************************* * ...

  8. basler相机的触发线是那两脚_机器视觉相机类型以及接口标准详解

    随着成像技术的进步,相机及其接口的类型不断演变,以满足大量应用的需求.对于检测和分析至关重要的半导体,电子,生物技术,装配和制造行业中的机器视觉应用而言,使用最好的相机系统来完成手头的任务对于获得最佳 ...

  9. Baumer相机baumer相机USB相机使用时出现USB驱动安装失败,导致相机无法使用

    Baumer相机baumer相机USB相机使用时出现USB驱动安装失败,导致相机无法使用 项目场景 Baumer工业相机堡盟相机是一种高性能.高质量的工业相机,可用于各种应用场景,如物体检测.计数和识 ...

最新文章

  1. 分布式链路追踪zipkin
  2. 只有程序员才懂的手势 | 每日趣闻
  3. AI高分通过美国8年级科学考试:常识题推理题都能行,不服可同台对战
  4. springboot2稳定版本_Spring Boot 2.4 正式发布,重大调整
  5. 3-12形参和实参 局部变量
  6. 单调栈之Next Greater Number
  7. 关于硬件信息和体系信息
  8. 使用高级程序设计语言实现集合的交并差运算
  9. gen_caltab生成标定文件
  10. eclipse编辑js卡死解决方案
  11. Pro Silverlight 5 in C# 分享
  12. 智能城市技术能够更好地改善日常生活
  13. 95-40-025-java.util.concurrent-并发容器
  14. Python 爬取 11 万 Java 程序员信息竟有这些重大发现!
  15. BeanFactoryPostProcessor接口(容器后处理器)
  16. mysql之配置使其可用python远程控制
  17. 论文赏析[ICLR18]联合句法和词汇学习的神经语言模型
  18. 操作系统中高响应比优先调度算法例子
  19. 二进制十六进制转换表
  20. VRP基础,命令行基础,文件系统基础,系统管理(2017年12月13日 09:51:51)

热门文章

  1. 《皇帝:中国的崛起》从入门到精通
  2. redis延迟队列 实现_灵感来袭,基于Redis的分布式延迟队列(续)
  3. listview 打开文件 c#_.NET CORE(C#) WPF简单菜单MVVM绑定
  4. 浙江财经大学java试卷_2020年浙江财经大学社会保障考研真题试卷及试题答案,管理学考研试题下载...
  5. linux集群无密码访问,Linux服务器集群通过SSH无密码登录
  6. queueing 优化_简单聊聊网页的资源加载优化
  7. C++知识点5——迭代器简述
  8. php制作本地程序,PHP安装程序制作
  9. matlab 电磁兼容仿真软件,EMC Studio免费版
  10. 研发团队资源成本优化实践