功能包:~/yahboomcar_ws/src/yahboomcar_visual
本节效果可在安装了我们相对应镜像的主板上演示。
增强现实(Augmented Reality),简称“AR”,技术是一种将虚拟信息与真实世界巧妙融合的技术,广泛运用了多媒体、三维建模、实时跟踪及注册、智能交互、传感等多种技术手段,将计算机生成的文字、图像、三维模型、音乐、视频等虚拟信息模拟仿真后,应用到真实世界中,两种信息互为补充,从而实现对真实世界的“增强”。
AR系统具有三个突出的特点:①真实世界和虚拟世界的信息集成;②具有实时交互性;③是在三维尺度空间中增添定位虚拟物体。
增强现实技术包含了多媒体、三维建模、实时视频显示及控制、多传感器融合、实时跟踪及注册、场景融合等新技术与新手段。
在使用AR案例时,必须得有相机的内参,不然无法运行。内参文件与代码同目录(功能包的AR文件夹下);不同相机对应不同内参。
(我们对应主板镜像里已存放好标定的相机内参文件,无需二次标定)
启动单目相机/树莓派 CSI相机
xxxxxxxxxxroslaunch usb_cam usb_cam-test.launch
启动Jetson CSI相机
xxxxxxxxxxroslaunch yahboomcar_visual yahboom_csi.launch
启动标定节点 (单目相机/树莓派 CSI相机)
xxxxxxxxxxrosrun camera_calibration cameracalibrator.py image:=/usb_cam/image_raw camera:=/usb_cam --size 9x6 --square 0.02
启动标定节点 (jetson CSI相机)
xxxxxxxxxxrosrun camera_calibration cameracalibrator.py image:=/csi_cam_0/image_raw camera:=/csi_cam_0 --size 9x6 --square 0.02
标定完后,将【calibrationdata.tar.gz】文件移动到【home】目录下。
xxxxxxxxxxsudo mv /tmp/calibrationdata.tar.gz ~
解压后,将该文件夹里面的【ost.yaml】打开,找到相机内参矩阵和畸变系数修改到【USB_camera.yaml】或者【csi_camera.yaml】文件对应的位置,只需修改两处【data】的内容即可。例如:以下内容。
xxxxxxxxxxcamera_matrix: !!opencv-matrix rows: 3 cols: 3 dt: d data: [615.50506, 0. , 365.84388, 0. , 623.69024, 238.778 , 0. , 0. , 1. ]distortion_model: plumb_bobdistortion_coefficients: !!opencv-matrix rows: 1 cols: 5 dt: d data: [0.166417, -0.160106, -0.008776, 0.025459, 0.000000]一共12种效果。
xxxxxxxxxx["Triangle", "Rectangle", "Parallelogram","WindMill","TableTennisTable", "Ball", "Arrow", "Knife", "Desk","Bench", "Stickman", "ParallelBars"]启动命令
xxxxxxxxxxroslaunch yahboomcar_visual simple_AR.launch display:=true flip:=false
根据需求设置参数,也可直接修改launch文件,启动时便无需附带参数。不开启画面时,可使用网络监控方式查看
xxxxxxxxxx开启设备的IP:8080
1)在显示画面的情况下(即display为true),【q】键退出,【f】键切换不同效果,也可以使用命令行切换。

使用【f】或【F】键切换不同效果。

2)在不显示画面的情况下(即display为false),只能通过命令行切换效果


使用RANSAC方案从3D-2D点对应中查找对象姿势。
RanSaC算法(随机采样一致)原本是用于数据处理的一种经典算法,其作用是在大量噪声情况下,提取物体中特定的成分。下图是对RanSaC算法效果的说明。图中有一些点显然是满足某条直线的,另外有一团点是纯噪声。目的是在大量噪声的情况下找到直线方程,此时噪声数据量是直线的3倍。

如果用最小二乘法是无法得到这样的效果的,直线大约会在图中直线偏上一点。
RANSAC的基本假设是: (1)数据由“局内点”组成,例如:数据的分布可以用一些模型参数来解释; (2)“局外点”是不能适应该模型的数据; (3)除此之外的数据属于噪声。 局外点产生的原因有:噪声的极值;错误的测量方法;对数据的错误假设。 RANSAC也做了以下假设:给定一组(通常很小的)局内点,存在一个可以估计模型参数的过程;而该模型能够解释或者适用于局内点。
设计流程:
launch文件
xxxxxxxxxx<launch> <arg name="flip" default="False"/> <arg name="display" default="False"/> <node name="simple_AR" pkg="yahboomcar_visual" type="simple_AR.py" output="screen" args="$(arg display)"> <param name="flip" type="bool" value="$(arg flip)"/> <remap from="/simpleAR/camera" to="/simpleAR/camera"/> </node> <!-- web_video_server --> <node pkg="web_video_server" type="web_video_server" name="web_video_server" output="screen"/></launch>python主函数
xxxxxxxxxx def process(self, img): if self.flip == 'True': img = cv.flip(img, 1) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 查找每个图片的角点 retval, corners = cv.findChessboardCorners( gray, self.patternSize, None, flags=cv.CALIB_CB_ADAPTIVE_THRESH + cv.CALIB_CB_NORMALIZE_IMAGE + cv.CALIB_CB_FAST_CHECK) # 查找角点亚像素 if retval: corners = cv.cornerSubPix( gray, corners, (11, 11), (-1, -1), (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)) # 计算对象姿态solvePnPRansac retval, rvec, tvec, inliers = cv.solvePnPRansac( self.objectPoints, corners, self.cameraMatrix, self.distCoeffs) # 输出图像点和雅可比矩阵 image_Points, jacobian = cv.projectPoints( self.__axis, rvec, tvec, self.cameraMatrix, self.distCoeffs, ) # 绘制图像 img = self.draw(img, corners, image_Points) return img关键函数
https://docs.opencv.org/3.0-alpha/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
xxxxxxxxxxdef findChessboardCorners(image, patternSize, corners=None, flags=None): ''' 查找图片角点 :param image: 输入原始的棋盘板图像。该图像必须是一张8位的灰度图或色彩图。 :param patternSize: (w,h),棋盘上每一排和每一列的内角数。w=棋盘板一行上黑白块的数量-1,h=棋盘板一列上黑白块的数量-1。 例如:10x6的棋盘板,则(w,h)=(9,5) :param corners: array,检测到的角点的输出数组。 :param flags: int,不同的操作标记,能够为0或者下述值的组合: CALIB_CB_ADAPTIVE_THRESH 使用自适应阈值法把图像转换为黑白图,而不是使用一个固定的阈值。 CALIB_CB_NORMALIZE_IMAGE 在利用固定阈值或自适应阈值法二值化图像之前,利用直方图均衡化图像。 CALIB_CB_FILTER_QUADS 使用额外的标准(如轮廓面积,周长,正方形形状)来过滤掉在轮廓检索阶段提取的假四边形。 CALIB_CB_FAST_CHECK 对图像运行一个快速检查机制以查找棋盘板的角点,如果没有找到角点则返回一个快捷提醒。 当没有观察到棋盘时,可以极大地加快在退化条件下的调用。 :return: retval, corners ''' pass我们需要使用cornerSubPix()对检测到的角点作进一步的优化计算,可使角点的精度达到亚像素级别。
xxxxxxxxxxdef cornerSubPix(image, corners, winSize, zeroZone, criteria): ''' 亚像素角点检测函数 :param image: 输入图像 :param corners: 像素角点(既作为输入也作为输出) :param winSize: 区域大小为 NXN; N=(winSize*2+1) :param zeroZone: 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略 :param criteria: 停止优化的标准 :return: 亚像素角点 ''' passxxxxxxxxxxdef solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec=None, tvec=None, useExtrinsicGuess=None, iterationsCount=None, reprojectionError=None, confidence=None, inliers=None, flags=None): ''' 计算对象姿态 :param objectPoints: 对象点列表 :param imagePoints: 角点列表 :param cameraMatrix: 相机矩阵 :param distCoeffs: 畸变系数 :param rvec: :param tvec: :param useExtrinsicGuess: :param iterationsCount: :param reprojectionError: :param confidence: :param inliers: :param flags: :return: retval, rvec, tvec, inliers ''' pass使用RANSAC方案从3D-2D点对应关系中查找对象姿态。该函数在给定一组对象点、它们对应的图像投影以及相机矩阵和失真系数的情况下,估计对象姿势。此函数找到一个使重新投影误差最小的姿势,即重新观察误差,即观察到的像素点投影imagePoints与物体投影(projectPoints())objectPoints之间的平方距离之和。 RANSAC的使用可以避免异常值对结果的影响。
def projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints=None, jacobian=None, aspectRatio=None): ''' 输出图像点和雅可比矩阵 :param objectPoints: :param rvec: 旋转向量 :param tvec: 平移向量 :param cameraMatrix: 摄影机矩阵 :param distCoeffs: 失真系数 :param imagePoints: :param jacobian: :param aspectRatio: :return: imagePoints, jacobian ''' pass