精华内容
下载资源
问答
  • 机器人抓取中物体定位算法概述

    千次阅读 多人点赞 2020-05-05 19:10:29
    这个过程可以分为三个层次,分别为物体定位但不识别、物体检测、物体实例分割。物体定位但不识别是指获得目标物体的2D/3D范围但是不知道物体的类别;目标检测是指得到目标物体的2D/3D包围盒,同时识别目标物体的类别...

    本文同步于微信公众号:3D视觉前沿,欢迎大家关注。

    1. 引言

    机器人抓取的首要任务,是确定要抓什么,也就是需要定位目标物体在输入数据中的位置。这个过程可以分为三个层次,分别为物体定位但不识别、物体检测、物体实例分割。物体定位但不识别是指获得目标物体的2D/3D范围但是不知道物体的类别;目标检测是指得到目标物体的2D/3D包围盒,同时识别目标物体的类别;目标实例分割提供目标物体所占有的像素或者点级别的区域信息,同时识别目标物体的类别。本文来自论文https://arxiv.org/abs/1905.06658,涉及的论文也都可以在论文中找到,也包含于https://github.com/GeorgeDu/vision-based-robotic-grasping,本文就不引用了。

    2. 定位但不识别

    当不知道目标物体的类别时,仍然可以采用一些方法获得目标物体的2D/3D区域,进而支撑机器人抓取。当我们知道物体的外轮廓形状时,可以采用拟合形状基元的方法。当我们什么信息都没有时,可以采用显著性物体检测方法,获得潜在可能的待抓取物体区域。

    2.1 基于2D RGB图像的方法

    在这里插入图片描述
    图1 基于2D图像的定位但不识别方法

    a.拟合形状基元: 目标物体的形状可以是一个椭圆、一个多边形或者一个四边形,这些2D形状可以看作是形状基元,通过拟合方法,可以定位到目标物体。该方法的一般步骤为先提取出图像的所有封闭轮廓,其次再用拟合方法得到潜在的可能目标物体,如果存在多个候选,可以使用模板匹配去除干扰。在OpenCV中已经集成了例如拟合椭圆、拟合多边形这样的函数。

    b.显著性区域检测: 和特定形状基元相比,显著性区域可以是任意形状。2D显著性区域检测的目的是定位和分割出给定图像中,最符合视觉显著性的区域,这更像一个分割任务。非深度学习的方法主要挖掘低层次的特征表示,或者依据一些经验例如颜色对比、形状先验来得到显著性区域。基于深度学习的方法主要包括基于多层感知机(MLP)的方法,基于全卷积网络(FCN)的方法和基于胶囊网络的方法。

    在目前的机器人抓取任务中,该方法仍处在初级阶段。在工业领域,如果待抓取物体形状固定且轮廓清晰,可以采用拟合形状基元的方法。在另外一些机器人抓取任务中,如果背景的颜色信息和目标物体的颜色信息差别较大,也可以去除背景得到目标物体。在Dex-Net2.0中,目标物体放置在绿色背景的桌面上,通过背景颜色分离,可以得到目标物体。

    2.2 基于3D点云的方法

    在这里插入图片描述
    图2 基于3D点云的定位但不识别方法

    a.拟合3D形状基元: 目标物体的形状可以是一个球体、圆柱体或者长方体,这些3D形状可以看作是3D形状基元。存在很多方法能够拟合,包括随机采样点一致(RANSAC)算法,基于霍夫投票(Hough Voting)的方法以及一些其他的聚类算法。针对机器人抓取任务,输入数据是单个视角下不完整的点云,目标是找到一部分点云,使得这些点云能够组合成某一个3D形状基元。一些方法针对输入的点云拟合平面并进行装配组合;一些方法使用长方体拟合室内场景数据;一些方法通过霍夫变换提取点云中的圆柱体,还有一些方法先把背景分割掉,然后对剩下的多个目标物体再拟合形状。

    b.3D显著性区域检测: 这类包括基元RGB-D数据的方法和基元3D点云的方法。RGB-D显著性检测方法通过人工设计的或者基于深度学习的方法提取特征并进行融合。基于3D点云的方法主要是提取一个完整物体点云的显著性图谱,而针对机器人抓取任务中是要从3D输入中得到目标物体的3D点区域。一些方法首先去除背景3D点,之后依赖3D特征如曲率等对显著性进行评分,得到显著性区域。

    在目前的抓取任务中,该方法被广泛使用,但仍处在初级阶段。通常都在结构化的场景中,利用先验去除背景包含点云(可以利用高度信息,也可以将当前输入和已有的背景3D模型配准去除背景),之后对于多个目标物体包含的点云进行聚类或者拟合,得到目标物体包含的3D点云。

    3. 目标检测

    当我们知道要抓取的目标物体的类别时,可以使用2D/3D目标检测以及实例分割算法,获得目标物体的2D/3D包围盒区域或者Mask区域。这里先介绍物体检测算法。目标物体检测是指不仅要定位出目标物体的位置,还要识别出物体的类别,位置通常用2D/3D最小包围盒表示。根据是否生成区域候选,目标检测的方法可以分为两阶段法(Two-stage Method)和单阶段法(One-stage Method)。

    3.1 2D目标检测

    在这里插入图片描述
    图3 基于2D图像的目标检测方法

    a.两阶段法: 这类方法也称为基于区域候选(Region proposal-based)的方法。大多数传统方法使用滑动窗口策略获得候选包围盒,然后使用包围盒内的特征描述进行识别。大量人工设计的2D描述符,例如SIFT, FAST, SURF, ORB等,常被使用来训练分类器,例如使用神经网络,SVM,Adaboost等。传统方法的缺陷在于需要根据特定物体设定滑动窗口的大小,而且人工设计的特征表征能力不强,不足够支撑一个很强的分类器。

    随着深度学习的发展,深度神经网络能够用于计算候选区域,而且能够提取表征能力更强的特征描述符,训练的分类器能力更强(R-CNN)。不仅如此,深度神经网络基于候选区域学习到的特征向量可以直接回归物体的类别,比训练分类器得到了更好的识别效果(Fast R-CNN)。Faster R-CNN进一步提出了候选区域生成网络,允许端到端训练整个目标检测网络。一般而言,两阶段法得到的精度相对较高,但是需要更多的计算资源和计算时间。

    b.单阶段法: 这类方法也称为基于回归(Regression-based)的方法。这类方法跳过了候选区域生成步骤,直接在一次估计中预测包围盒以及类别得分。YOLO是代表性单阶段方法,划分网格并同时预测多个包围盒和类别概率。不过由于每个网格只回归两个包围盒,算法不适合小物体。SSD能够为固定集合的锚点包围盒(anchor boxes)预测类别得分和包围盒偏移,比YOLO效果要好。YOLOv2也使用了锚点滑动窗口,效果比YOLO提升。RetinaNet提出了focal loss损失函数用于训练,达到了和两阶段算法相当的精度但速度更快。YOLOv3基于YOLOv2进行了一些优化,达到了更好的效果。此外,存在不使用锚点的单阶段方法,例如FCOS、CornerNet、ExtremetNet、CenterNet等,直接预测单个点处潜在物体的类别概率,以及距离完整包围盒的相对位置。

    3.2 3D目标检测

    2D目标检测预测的包围盒,能够将物体在2D空间占据的区域完全包含。而3D目标检测旨在寻找到目标物体在3D空间中的完整(amodel)3D包围盒,也即完整的3D物体的最小外接长方体。通常获取的数据是单个视角下的RGB-D数据,通用的3D检测算法都可以使用。但由于目前仅基于RGB进行3D检测与基于3D点云进行3D检测的效果差别较大,本文主要面向机器人抓取领域,因此这里只介绍基于点云的3D检测方法。
    在这里插入图片描述
    图4 基于3D点云的目标检测方法

    a.两阶段法: 这类方法也称为基于区域候选(Region proposal-based)的方法。传统的3D检测方法主要针对已知形状的物体,3D检测问题就转化为了物体的6D位姿估计问题。此时,可以寻找3D特征点之间的对应,将已有物体和观测数据进行配准,也可以进行基于RANSAC的对齐完成全局配准。然而这些方法要求观测的实例和已有物体模型几何结构一致,不适用于通用物体3D检测。通用的3D检测任务和2D检测任务类似,也广泛使用3D区域候选。传统方法使用人工设计的3D特征,例如Spin Images, 3D Shape Context, FPFH, CVFH, SHOT等,训练诸如SVM之类的分类器完成3D检测任务,代表方法为Sliding Shapes。

    随着深度学习的发展,3D区域候选可以被有效地生成,而且3D包围盒可以被直接回归得到,而不必训练分类器。生成3D区域候选的方法,大致可以分为三类:基于截锥体(frustum-based)的方法,基于全局回归(global regression-based)的方法和基于局部回归(local regression-based)的方法。基于截锥体的方法是指使用成熟的2D目标检测算法来获取物体的3D候选区域,方法最为直接。Frustum PointNets使用2D检测器获得物体的2D区域,对应3D空间是一个截锥体,对里面的点云基于PointeNet进行语义分割,再用MLP回归得到最终的3D包围盒信息;FrustumConvNet对由2D区域得到的3D截锥体进一步划分成多个3D候选区域。基于全局回归的方法根据基于单源或多源输入学习到的特征描述,直接回归得到3D区域候选。Deep Sliding Shapes提出了第一个3D候选区域生成网络,并且结合物体识别网络来回归3D包围盒;MV3D融合多源信息预测3D候选;MMF进行多特征多传感器融合,完成3D检测任务;PartA2使用encoder-decoder网络,对输入的点云预测物体部位的相对位置,预测3D候选包围盒。基于局部回归的方法是指产生逐点的3D区域候选。PointRCNN从输入点云中提取逐点的特征向量,对分割得到每一个前景点,生成3D候选。这些候选经过池化以及正则优化得到最终结果。STD设计了球形锚点生成基于点的候选,并进一步生成稠密的候选包围盒的特征描述,预测最终的包围盒。VoteNet提出深度霍夫投票策略,对采样的每个3D种子点,生成对应的3D投票点,并进一步聚类得到候选包围盒。IMVoteNet结合2D图像,进一步提升了VoteNet的精度。

    b.单阶段法: 这类方法也称为基于回归(Regression-based)的方法,通过单个网络直接预测3D包围盒及其类别概率,不需要生成候选3D包围盒以及后处理。VoxelNet将输入点云划分成3D voxels,并且将每个voxel内的点云学习一个统一的特征表示,再用卷积层和候选生成层得到最终的3D包围盒。SECOND相比于VoxelNet,使用稀疏卷积层来划分紧致的体素特征。PointPillars将点云转换成一个稀疏的伪图像,再结合2D卷积网络和检测头预测3D包围盒。以上主要是基于体素的单阶段3D检测器,3DSSD是基于点云的3D检测器,使用了一种融合采样策略,一个候选生成层和一个锚点无关的回归层,实现了精度和速度的平衡。

    3D检测能够提供目标物体的大致位置,主要应用在无人车领域,但不足够支撑复杂的抓取。目前的通用3D检测只预测一个平面上的3D包围盒的1个旋转角度,范围在0度-180度(原地旋转180度,包围盒位置朝向不变),假定物体结构复杂,例如带柄水杯,只给一个中心加旋转角度是不知道如何去抓的。但是3D包围盒能够提供大致的物体抓取位置,而且能够用于机械臂移动避障。

    4. 物体实例分割

    进行目标检测只能得到矩形框区域,而一些任务需要只属于目标物体的区域,这就需要进行实例分割。物体实例分割是指检测到特定类别物体的逐像素或者逐点的实例,这项任务与目标检测和语义分割极其相关。实例分割算法也分为两阶段法和单阶段法,两阶段法先生成区域候选,单阶段法直接回归。

    4.1 2D实例分割

    在这里插入图片描述
    图5 基于2D图像的实例分割方法

    a.两阶段法: 这类方法也称为基于区域候选(Region proposal-based)的方法。成熟的2D检测器常被用来生成包围盒或者区域候选,在他们内部可以进一步计算物体的mask区域。许多方法都基于CNN。SDS使用CNN来识别类别无关的区域候选;MNC通过三个网络进行实例分割;PANet提出路径增强网络提升实例分割效果 ;Mask R-CNN通过增加额外的分支预测物体的mask扩展了Faster R-CNN;HTC对目标检测结果和分割结果进行层叠式优化;PointRend通过迭代细分策略进一步增强了细节的分割效果。

    b.单阶段法: 这类方法也称为基于回归(Regression-based)的方法,同时预测分割的mask和存在物体的得分。DeepMask, SharpMask和InstanceFCN为位于中心的物体预测mask;FCIS进行实例级语义分割,能够预测位置敏感的得分进行物体分割和检测;TensorMask在空间域使用结构化的4D张量代表masks,能够预测稠密的masks;YOLACT将实例分割分成两个平行的子任务,即生成一些列原型masks并且预测每个实例mask的系数;YOLACT是第一个实时的单阶段实例分割算法,后续有改进版YOLACT++;PolarMask利用极坐标系,预测实例物体的中心和稠密距离,得到实例物体的轮廓;SOLO引入实例类别的概念,依据每个实例的位置和大小,赋予属于实例物体的每个像素一个类别,将实例分割问题转换成分类问题;CenterMask在目标检测算法FCOS的基础上增加了SAG-Mask分支;BlendMask也基于FCSO,使用了一个渲染模块来预测位置敏感的特征,并且学习每个实例物体的注意力图。

    2D实例分割在机器人抓取应用中被广泛使用,如果场景中同一个类别的物体只有一个实例,语义分割也可以。由于输入是RGB-D图像,有了RGB分割结果,可以快速得到对应Depth图像,得到目标物体的3D点云。例如,SegICP使用基于RGB的2D目标分割算法获得只属于目标物体的点,再使用配准方法得到目标物体的6D位姿。很多方法也结合Depth输入共同完成目标分割任务。

    4.2 3D实例分割

    在这里插入图片描述
    图6 基于3D点云的实例分割方法

    a.两阶段法: 这类方法也称为基于区域候选(Region proposal-based)的方法。一般的方法借助2D/3D检测结果,再对对应3D截锥体或者包围盒区域进行前后景分割得到目标物体的点云。GSPN提出通用形状候选网络生成3D物体的候选区域,进一步使用区域PointNet进行3D物体的实例分割;3D-SIS使用2D和3D融合特征进行3D物体包围盒检测以及语义实例分割。

    b.单阶段法: 这类方法也称为基于回归(Regression-based)的方法。很多方法学习如何归类逐点的特征来完成3D实例分割。SGPN提出了相似群候选网络来预测合并后的候选,并给每个候选一个对应的语义类别,也就完成了3D实例分割;MASC使用子空间稀疏卷积预测每个点的语义得分以及邻近点在不同尺度下的紧密关系得分,基于此可以合并得到实例分割结果;ASIS学习具有语义的逐点级别的实例嵌入,之后属于同一个实例的语义特征再进行融合;JSIS3D提出了一个多任务的逐点的网络结构,能够同时预测3D点属于的物体类别,并且将3D点嵌入为更高维的特征向量,进一步聚类得到物体实例;3D-BoNet能够回归所有实例的3D包围盒,同时预测每个实例的逐点的mask;LiDARSeg提出了一种稠密的特征编码框架以及有效的策略解决类别不平衡问题。

    3D实例分割在机器人抓取应用中非常重要,如果场景中同一个类别的物体只有一个实例,语义分割也可以。当前常用的做法仍然是利用成熟的2D分割算法,对应到深度图获取3D点云,但是在其分割效果不如直接在3D点云上进行实例分割。随着算法效果和性能的提升,3D实例分割会在未来广泛使用。

    5. 总结

    给定机器人抓取场景,目前总能找到合适的技术方案来定位目标物体的位置,进而执行后续的物体位姿估计以及机器人抓取位姿估计等任务,但仍存在一些问题。定位但不识别的算法,要求物体在结构化的场景中或者物体与背景具有显著性差异,这些都有益于算法提取出目标物体,这就限制了应用场景;实例级目标检测算法,需要实例级目标物体的大量训练集,而且训练好的检测算法只在训练集上检测精度高;如果需要对新物体进行检测,需要再采集大量的数据进行重新训练,这个过程非常耗时耗力;通用的目标检测算法,泛化能力强,但其精度达不到实例级目标检测算法。实例分割算法也面临同样的问题。对大量训练数据集的需求以及泛化性能差,也是深度学习算法的通用性问题。不过针对限定场景下特定的一些物体,当前算法已经能够得到非常好的满足落地需求的结果。

    展开全文
  • 基于opencv的物体定位

    万次阅读 多人点赞 2016-08-17 20:44:32
    近日,我在研究一个图中物体定位系统。本程序用的是OpenCV2.4.9,附带OpenCV3.0。 程序中的原图为我随手拍的一张图片 图中有三个物体,都是蓝色的,我首先取原图的蓝色通道变为灰度图 灰度图经过中值滤波后可以...

    opencv是一个很强大的机器视觉库,利用它我们可以开发出丰富多彩的使用项目。近日,我在研究一个图中物体定位系统。本程序用的是OpenCV2.4.9,附带OpenCV3.0。

    程序中的原图为我随手拍的一张图片


    图中有三个物体,都是蓝色的,我首先取原图的蓝色通道变为灰度图


    灰度图经过中值滤波后可以得到去噪后的图片


    根据原图的蓝色通道和红色通道的大概取值范围,我们可得到比较满意的二值图


    为了去掉物体中少量的黑色部分,我用闭运算


    然而,图中最上面的那个物体里面还有一块很大的黑色(目前我也不知道怎么去掉,如果有大神知道望告知~~)

    接下来就是找出物体的轮廓


    最后找到能包围轮廓的最小矩形


    好了,占时就这么多了

    下面是配套的程序

    OpenCV2.4.9半根

    #include<opencv2\opencv.hpp>
    #include<iostream>
    #define BIN_DIV 110
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat srcImg, midImg, dstImg;
    	srcImg = imread("hehe.jpg");
    	Mat xianshi = srcImg.clone();
    	Mat redChannel;
    	namedWindow("【原图】", WINDOW_NORMAL);
    	imshow("【原图】", srcImg);
    	Mat grayImg;
    	vector<Mat> channels;
    	split(srcImg, channels);
    	//cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
    	grayImg = channels.at(0);
    	redChannel = channels.at(2);
    	namedWindow("【灰度图】", WINDOW_NORMAL);
    	imshow("【灰度图】", grayImg);
    	//均值滤波
    	blur(grayImg, grayImg, Size(20, 20), Point(-1, -1));
    	namedWindow("【均值滤波后】", WINDOW_NORMAL);
    	imshow("【均值滤波后】", grayImg);
    	//转化为二值图
    	Mat midImg1 = grayImg.clone();
    	int rowNumber = midImg1.rows;
    	int colNumber = midImg1.cols;
    
    	for (int i = 0; i<rowNumber; i++)
    	{
    		uchar* data = midImg1.ptr<uchar>(i);  //取第i行的首地址
    		uchar* redData = redChannel.ptr<uchar>(i);
    		for (int j = 0; j<colNumber; j++)
    		{
    			if (data[j]>BIN_DIV&&redData[j]<BIN_DIV *2/ 3)
    				data[j] = 255;
    			else
    				data[j] = 0;
    		}
    	}
    	namedWindow("【二值图】", WINDOW_NORMAL);
    	imshow("【二值图】", midImg1);
    	Mat midImg2 = midImg1.clone();
    	Mat element = getStructuringElement(MORPH_RECT, Size(40, 40));
    	morphologyEx(midImg1, midImg2, MORPH_CLOSE, element);
    	namedWindow("【闭运算后】", WINDOW_NORMAL);
    	imshow("【闭运算后】", midImg2);
    	cout << "midImg1.channel=" << midImg1.channels() << endl;
    	cout << "mdiImg1.depth" << midImg1.depth() << endl;
    	//查找图像轮廓
    	Mat midImg3 = Mat::zeros(midImg2.rows, midImg2.cols, CV_8UC3);
    	vector<vector<Point>> contours;
    	vector<Vec4i> hierarchy;
    	findContours(midImg2, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
    	int index = 0;
    	for (; index >= 0; index = hierarchy[index][0])
    	{
    		Scalar color(255, 255, 255);
    		drawContours(midImg3, contours, index, color, NULL, 8, hierarchy);
    	}
    	namedWindow("【轮廓图】", WINDOW_NORMAL);
    	imshow("【轮廓图】", midImg3);
    	Mat midImg4 = midImg3.clone();
    	//创建包围轮廓的矩形边界
    	for (int i = 0; i<contours.size(); i++)
    	{
    		//每个轮廓
    		vector<Point> points = contours[i];
    		//对给定的2D点集,寻找最小面积的包围矩形
    		RotatedRect box = minAreaRect(Mat(points));
    		Point2f vertex[4];
    		box.points(vertex);
    		//绘制出最小面积的包围矩形
    		line(xianshi, vertex[0], vertex[1], Scalar(100, 200, 211), 6, CV_AA);
    		line(xianshi, vertex[1], vertex[2], Scalar(100, 200, 211), 6, CV_AA);
    		line(xianshi, vertex[2], vertex[3], Scalar(100, 200, 211), 6, CV_AA);
    		line(xianshi, vertex[3], vertex[0], Scalar(100, 200, 211), 6, CV_AA);
    		//绘制中心的光标
    		Point s1, l, r, u, d;
    		s1.x = (vertex[0].x + vertex[2].x) / 2.0;
    		s1.y = (vertex[0].y + vertex[2].y) / 2.0;
    		l.x = s1.x - 10;
    		l.y = s1.y;
    
    		r.x = s1.x + 10;
    		r.y = s1.y;
    
    		u.x = s1.x;
    		u.y = s1.y - 10;
    
    		d.x = s1.x;
    		d.y = s1.y + 10;
    		line(xianshi, l, r, Scalar(100, 200, 211), 2, CV_AA);
    		line(xianshi, u, d, Scalar(100, 200, 211), 2, CV_AA);
    	}
    	namedWindow("【绘制的最小面积矩形】", WINDOW_NORMAL);
    	imshow("【绘制的最小面积矩形】", xianshi);
    	waitKey(0);
    	return 0;
    }

    OpenCV3.0版本

    #include<opencv2\opencv.hpp>
    #include<iostream>
    #define BIN_DIV 120
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat srcImg=imread("haha.jpg");
    	Mat xianshi=srcImg.clone();
    	Mat redChannel;
    	namedWindow("【原图】",WINDOW_NORMAL);
    	imshow("【原图】",srcImg);
    	Mat grayImg;
    	vector<Mat> channels;
    	split(srcImg,channels);
    	//cvtColor(srcImg,grayImg,COLOR_BGR2GRAY);
    	grayImg=channels.at(0);
    	redChannel=channels.at(2);
    	namedWindow("【灰度图】",WINDOW_NORMAL);
    	imshow("【灰度图】",grayImg);	
    	//均值滤波
    	blur(grayImg,grayImg,Size(20,20),Point(-1,-1));
    	namedWindow("【均值滤波后】",WINDOW_NORMAL);
    	imshow("【均值滤波后】",grayImg);
    	//转化为二值图
    	Mat midImg1=grayImg.clone();
    	int rowNumber=midImg1.rows;
    	int colNumber=midImg1.cols;
    
    	for(int i=0;i<rowNumber;i++)
    	{
    		uchar* data=midImg1.ptr<uchar>(i);  //取第i行的首地址
    		uchar* redData=redChannel.ptr<uchar>(i);
    		for(int j=0;j<colNumber;j++)
    		{
    			if(data[j]>BIN_DIV&&redData[j]<BIN_DIV/2)
    				data[j]=0;
    			else
    				data[j]=255;
    		}
    	}
    	namedWindow("【二值图】",WINDOW_NORMAL);
    	imshow("【二值图】",midImg1);
    	Mat midImg2=midImg1.clone();
    	Mat element=getStructuringElement(MORPH_RECT,Size(20,20));
    	morphologyEx(midImg1,midImg2,MORPH_OPEN,element);
    	namedWindow("【开运算后】",WINDOW_NORMAL);
    	imshow("【开运算后】",midImg2);
    	cout<<"midImg1.channel="<<midImg1.channels()<<endl;
    	cout<<"mdiImg1.depth"<<midImg1.depth()<<endl;
    	//查找图像轮廓
    	Mat midImg3=Mat::zeros(midImg2.rows,midImg2.cols,CV_8UC3);
    	vector<vector<Point>> contours;
    	vector<Vec4i> hierarchy;
    	findContours(midImg2,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE);
    	int index=0;
    	for(;index>=0;index=hierarchy[index][0])
    	{
    		Scalar color(255,255,255);
    		drawContours(midImg3,contours,index,color,NULL,8,hierarchy);
    	}
    	namedWindow("【轮廓图】",WINDOW_NORMAL);
    	imshow("【轮廓图】",midImg3);
    	Mat midImg4=midImg3.clone();
    	//创建包围轮廓的矩形边界
    	for(int i=0;i<contours.size();i++)
    	{
    		//每个轮廓
    		vector<Point> points=contours[i];
    		//对给定的2D点集,寻找最小面积的包围矩形
    		RotatedRect box=minAreaRect(Mat(points));
    		Point2f vertex[4];
    		box.points(vertex);
    		//绘制出最小面积的包围矩形
    		line(xianshi,vertex[0],vertex[1],Scalar(100,200,211),6,LINE_AA);
    		line(xianshi,vertex[1],vertex[2],Scalar(100,200,211),6,LINE_AA);
    		line(xianshi,vertex[2],vertex[3],Scalar(100,200,211),6,LINE_AA);
    		line(xianshi,vertex[3],vertex[0],Scalar(100,200,211),6,LINE_AA);
    		//绘制中心的光标
    		Point s1,l,r,u,d;
    		s1.x=(vertex[0].x+vertex[2].x)/2.0;
    		s1.y=(vertex[0].y+vertex[2].y)/2.0;
    		l.x=s1.x-10;
    		l.y=s1.y;
    
    		r.x=s1.x+10;
    		r.y=s1.y;
    
    		u.x=s1.x;
    		u.y=s1.y-10;
    
    		d.x=s1.x;
    		d.y=s1.y+10;
    		line(xianshi,l,r,Scalar(100,200,211),2,LINE_AA);
    		line(xianshi,u,d,Scalar(100,200,211),2,LINE_AA);
    	}
    	namedWindow("【绘制的最小面积矩形】",WINDOW_NORMAL);
    	imshow("【绘制的最小面积矩形】",xianshi);
    	waitKey(0);
    	return 0;
    }


    展开全文
  • 机器视觉检测物体定位

    千次阅读 2015-08-21 16:39:22
    机器视觉检测物体定位  典型的机器视觉应用中,是从关注区中提取测量指标而不是从整个图像中。要使用这种技术,关注物体的各个部分都要出现在所定义的关注区中。 如果需要处理的图像中被测物体始终保持在相同的...

    机器视觉检测物体定位

     典型的机器视觉应用中,是从关注区中提取测量指标而不是从整个图像中。要使用这种技术,关注物体的各个部分都要出现在所定义的关注区中。 如果需要处理的图像中被测物体始终保持在相同的位置和方向,那么直接定义关注区就可以了。 通常,被测物体会在需要处理的图像中发生相对位移或旋转。 发生这种情况时,那么关注区就需要跟所关注的物体的所有部分一起移动或旋转。对于要随物体一起移动的关注区,需要定义一个相对于参考图像中物体的参考坐标系统。在测量处理期间,当需要处理的图像中的物体出现移动和旋转时,坐标系统也随物体一起移动。这个坐标系统称为测量坐标系统。测量模块利用相对于参考坐标系统的测量位置自动地将关注区移动到正确的位置。 可以利用边缘检测或模式匹配建立一个坐标变换。建立坐标变换的边缘检测和模式匹配模块的输出结果是原点、角度,和坐标系统的轴向。某些 机器视觉模块采用这一输出结果并自动调整检测区域。也可以通过编程利用这些输出结果来移动做相对于物体的检测区域。机器视觉系统(检测、测量、识别、定位)、工业镜头、工业相机、LED光源、光源控制器、传感器 有需要的可加QQ249412661

    展开全文
  • python实现物体定位

    万次阅读 2016-07-01 13:40:02
    实验的内容是:使用卫星定位信息接收器,接收物体的位置信息(包括经度纬度等等),然后解析这些数据,然后根据经度纬度等信息通关百度地图API获取物体的具体位置信息,实现对物体定位!  我使用的开发语言重要是...

        前段时间利用实验室的器材写了一个小小的项目,简单的整理了一下(并不完善),现在分享一下。实验的内容是:使用卫星定位信息接收器,接收物体的位置信息(包括经度纬度等等),然后解析这些数据,然后根据经度纬度等信息通关百度地图API获取物体的具体位置信息,实现对物体的定位!

        我使用的开发语言重要是python,主要的有:serial串口通信,MySQLdb库,urllib2库,httplib库等等。下面就开始简单的说说实验中的问题。

    1.首先使用的串口通信接收卫星接收器传出来的信息,我使用串口助手看了一下接收到的信息的样式,大概如下:


    上图就是实验过程中的数据部分,我主要提取出来的是时间,海拔,经度,维度等信息。可以看出这些数据并不是单独成行的所以我需要将他们一个一个的提取出来(这并不是很难),然后利用经度纬度信息,使用百度地图API提供的地址解析服务获取物体的具体位置的描述,我使用的是一个HTTP服务,返回的是一个json的格式的位置信息,我事先测试库一下,返回的json格式的位置信息大概如下所示:


    然后我从中获取具体位置描述信息,然后将它保存到数据库中。另外在试验中我使用了两张表,一张记录从从串口提取出来的信息,一张保存解析后的位置信息,而这两张表有相同的一项,就是时间,表的内容后面我会以图片的形式放出来。下面就附上我的代码,然后给出实验的结果。

    # coding:utf8
    '''
    Created on 2016年6月14日
    @author: zou
    '''
    import serial
    import MySQLdb
    import urllib2
    import urllib
    import httplib
    import json
    import time
    
    ser = serial.Serial('COM4',9600)
    ######################################################
    def recv(serial):
        data=''
        while True:
            tmp = serial.read(1)
            if tmp == '\n':
                break
            else:
                data += tmp
    
        return data
    ######################################################
    def GetInfo(Str):
        info = []
        tmp = Str[7:]
        strs=''
        for ch in tmp:
            if ch == '\n':
                return
            else:
                if ch == ',':
                    info.append(strs)
                    strs = ''
                else:
                    strs = strs+ch
                          
        return info    
    ######################################################
    		
    def getYear(data):
        retdata = ''
        ret = ''
        tail = data
        #print tail
        tail = tail[::-1]
        #print tail
        count = 0
        for ch in tail:
            if count == 3:  #616022
                if ch == ',':
                    break
                else:
                    ret += ch				
            elif ch == ',':
                count=count+1
        
        #print ret
        retdata+=ret[1]
        retdata+=ret[0]
        retdata+=ret[3]
        retdata+=ret[2]
        retdata+=ret[5]
        retdata+=ret[4]
        #print retdata
        return retdata	
    ######################################################
    def rightNum(strs,flag):
        ret=''
        if cmp(flag,'t')==0:
            #times      024335.00
            ret=strs[0:2]
            ret+=':'
            ret+=strs[2:4]
            ret+=':'
            ret+=strs[4:6]
        elif cmp(flag,'l')==0:#latitude   3422.99947N
            if int(strs[0:3]) < 180:
                ret=strs[0:3]
                ret+='.'
                ret+=strs[3:5]
                ret+=strs[6:10]
            else:
                ret=strs[0:2]
                ret+='.'
                ret+=strs[2:4]
                ret+=strs[5:9]
        elif cmp(flag,'L')==0:#longitude  10858.95306E
            if int(strs[0:3]) < 180:
                ret=strs[0:3]
                ret+='.'
                ret+=strs[3:5]
                ret+=strs[6:10]
            else:
                ret=strs[0:2]
                ret+='.'
                ret+=strs[2:4]
                ret+=strs[5:9]  
        else:
            return None
    
        return ret         
    #########################################################
    def Getlocation(db,ti,la,lo):
        #发送http请求获取具体位置信息
        #import urllib
        url = 'http://api.map.baidu.com/geocoder/v2/'
        ak = 'ak=1aZ2PQG7OXlk9E41QPvB9WjEgq5WO8Do'
        #back='&callback=renderReverse&location='
        back='&location='
        location='34.992654,108.589507'
        output = '&output=json&pois=0'
        url = url + '?' + ak + back + location + output
    
        temp = urllib2.urlopen(url)
        hjson = json.loads(temp.read())
        locate = hjson["result"]["formatted_address"] #省,市,县
        #print locate
        mapinfo = hjson["result"]["sematic_description"]  #详细描述
        #print mapinfo
        #插入数据库
        cur = db.cursor()
        sql="set names utf8"
        cur.execute(sql)
        info=[]
        info.append(ti.encode('utf8'))
        info.append(locate.encode('utf8'))
        info.append(mapinfo.encode('utf8'))
    
        for val in info:
            print val
    
        sql = "insert into mapinfo values(%s,%s,%s)"
        try:
            cur.execute(sql,info)
        except:
            print 'Insert mapinfo failed'
    	
    
    #########################################################
    #mysql , 经度,维度
    db = MySQLdb.connect('localhost','root','',"zou",3306,'utf8')
    cursor = db.cursor()
    cursor.execute("DROP TABLE IF EXISTS Location")
    cursor.execute("DROP TABLE IF EXISTS mapinfo")
    
    sql="""CREATE TABLE Location(
            Time CHAR(20),
            Latitude CHAR(15),
            Longitude CHAR(15),
            Altitude CHAR(10))"""
    cursor.execute(sql)
    sql = """CREATE TABLE mapinfo(
            time CHAR(20),
            local CHAR(100),
            info CHAR(100))"""
    cursor.execute(sql)
    
    '''
    #mysql , 位置描述信息
    #database = MySQLdb.connect('localhost','root','',"zou",3306)
    #curkey = database.cursor()
    #curkey.execute("DROP TABLE IF EXISTS mapinfo")
    
    msql = """CREATE TABLE mapinfo(
            time CHAR(20),
            local CHAR(100),
            info CHAR(100))"""
    curkey.execute(msql)
    '''
    
    ##################################################################
    Locat = []  ####
    #提取20项数据
    count=0
    while count<10:
        Info=[]
        year=''
        #如果输出为 $GPGGA 开头,则这一行表示的是位置信息
        for val in range(0,8):
            data = recv(ser)
            tmp = data[0:6] #截取前6个字符
            if cmp(tmp,'$GPRMC') == 0:
                #print data
                tmpyear = data[50:]
                year = getYear(tmpyear)
                #print year
            elif cmp(tmp,'$GPGGA') == 0:  #条件满足的话就截取
                #print data
                Info = GetInfo(data)
    
        if Info == []:
            break
        value=[]
        ti = year
        ti += '-'
        t = rightNum(Info[0],'t')
        ti += t
        #print ti
        value.append(ti)
        la = rightNum(Info[1],'l')
        value.append(la)
        lo = rightNum(Info[3],'L')
        value.append(lo)
        al = Info[8]
        value.append(al)
        #print value
    
        sql = "insert into Location values (%s,%s,%s,%s)"
    
        try:
            cursor.execute(sql,value)
            Getlocation(db,ti,la,lo)
            db.commit()
        except:
            print 'insert error'
    
        count=count+1
        #print count
    
    	
    db.close()
    ############################################################
                            
    #关闭端口
    ser.close()
    实验的结果如下:


    相应的两张表的内容如下:

    到这里这个实验的内容说完了,大家若是有什么问题的话欢迎给我留言。

    展开全文
  • 物体定位与检测

    万次阅读 2017-07-28 14:13:17
    一、任务描述 ...如果想要对物体定位和检测理解的更深的话,大家需要查阅更多的资料。 【1】 http://blog.csdn.net/zchang81/article/details/69383950 (深度学习物体检测——常用资源简述) 【2】 ...
  • 基于视觉的机器人抓取--物体定位,位姿估计到抓取估计课堂笔记 杜国光博士在智东西公开课上讲了《基于视觉的机器人抓取--物体定位,位姿估计到抓取估计》的精彩课程 满满的干货,记下来,后面慢慢消化 2020.11.06...
  • 目标检测——物体定位和检测

    万次阅读 2018-08-14 14:15:48
    此篇是看CS231n的课后笔记,方便以后查阅,因为刚开始接触,如果有错误,欢迎指正~ 更多内容关注微信公众号:ML_Study ...定位一般是指一张图有一个类别,有单个物体需要去定位 常用数据库:ImageN...
  • 深度学习小白——物体定位和检测

    万次阅读 2017-05-17 17:52:36
    定位一般是指一张图有一个类别,有单个物体需要去定位 常用数据库:ImageNet localization数据库 对于分类任务: 目标:分出类别输入:图像输出:图像类别评价指标:准确度 对于定位任务: 目标
  • 本章节是第三章和第四章的结合,旨在实现实时物体定位+检测。 直接上代码: # -*- coding: utf-8 -*- """ Created on Mon Jul 16 17:28:57 2018 @author: bjw """ import os ...
  • 物体定位的map的概念是从多分类评价标准中自然引进的,因此弄懂物体定位的map也就可以拆分成两个问题: 1. 什么是map :map全称为 mean average precision,需要计算出每一类的ap,然后计算所有类别ap的平均值即可...
  • 说到计算机视觉,就不得不提卷积神经网络(CNN)了,图像分割、定位、识别他都及其擅长。由于最近才接触CNN,还不得要领,今天还是分享一下自己一个瞎捉摸的魔方机器人中的魔方定位的方法。 魔方机器人项目来源于...
  • 机器人抓取中物体3D定位算法介绍

    千次阅读 2019-07-23 23:26:53
    针对纹理丰富的物体,可以使用SIFT等特征点与模板图像匹配进行定位;对于弱纹理或无纹理物体,可以使用稳定的梯度或者深度图法向进行匹配,进而恢复位姿;一些基于parts进行投票的方法也取得了很好的效果;然而,...
  • 我想设计一个硬件,百米内通过一个或多个硬件组合的方式,精确的定为一个物体的活动轨迹。 如果有相关的技术或是产品告诉我即可 在这里,谢谢了
  • 问题: 如果Unity的Scene场景选中某个gameObject,Hierarchy窗口无法锁定选中的物体 解决: 切换一下unity的Layout即可恢复正常
  • Cesium定位到加载的物体

    千次阅读 2020-06-24 16:34:45
    Cesium定位到加载的物体上 1.设置destination位置,定位到primitive可使用这种方式 viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(100, 39., 10000), orientation: {//设置相机的Heading,...
  • python+opencv识别出物体颜色(红白黑蓝绿...)并二维定位出颜色物体坐标.
  • Unity8.物体空间定位(VuforiaAR)日志

    千次阅读 2019-05-07 18:00:08
    实现主要参考:VuforiaAR物体空间定位(设备跟踪):http://blog.sina.com.cn/s/blog_8082aa610102x83i.html 高通 Vuforia SDK + Unity3D制作简易Android AR app : ...traceid=...
  • 程序目的是对传送带上物件的定位,需要提取物件坐标。主要运用Opencv中的寻找轮廓函数findContours()作为程序核心,为了杂质的干扰,处理高斯滤波,做了一个轮廓面积的计算,来去除杂质
  • 项目实战——基于计算机视觉的物体位姿定位及机械臂矫正 写在开头的话: 不得不说大学这三年过的真的快,一年后就要读研了。读研选择了增强现实——计算机视觉与人工智能这个方向(当然也需要很多机械的东西),...
  • 追踪贵重物体-NB基站定位

    千次阅读 2020-06-17 16:32:03
    首先,我们要确定NB-IoT支持基站定位吗? 答案是:R13不支持基站定位,但运营商网络可以做私有方案,比如基于小区ID的定位,不会影响终端,只需要网络增加定位服务器以及与基站的联系即可。 R14计划做定位增强,...
  • 机器人抓取 机器人物体三维定位 三维匹配

    万次阅读 热门讨论 2016-11-30 16:08:17
    最近在看“机器人物体抓取”的解决方案,很多机器视觉库都提供类似的解决方案,大多采用的是在二维图像上的匹配。但是这种方法对光照和物体的摆放很...第一步:使用基于结构光的方法获取到物体的被定位物体的三维点云
  • 本文介绍了物体检测的相关概念,包括物体定位,物体检测,YOLO算法和基于Region proposals的方法。
  • Unity物体空间定位(VuforiaAR)日志

    千次阅读 2019-06-13 14:52:45
    发现电脑中无法实现物体空间定位(可能是因为没有陀螺仪)但手机可以 注意需要定位物体与ARCamera平级 识别(最后不需要) 参考高通文档:...
  • 我的需求是这样的,场景中有三个物体,一个圆柱体,一个正方体,一个球体,需要借助魔镜的凝视功能来定位一个物体,然后按下手柄控制器的OK键,显示该定位物体的名字 最后的画面: 因为我们只借助凝视的定位功能,...
  • 一般Unity中自建的Gameobject 坐标归零, 双击物体, 直接聚焦到物体中心点. 但是 在网上下载的模型, 有些模型不规范, 直接双击, 聚焦的点离物体特别远, 或者小的都看不见了 看这个物体的子元素, 是不是有 相机/灯光...
  • 手机拍照中待测物体的体积计算。1、2、3、4为定位圆,圆心的距离为已知量。有此计算待测物体高度a(cm)和宽度b(cm)。求后台处理的算法代码。
  • 在上一篇中已经通过opencv获得到了各种图像,在这一篇中,将通过深度特性来进行物体的识别定位。 1,深度图像处理 1,运用opencv函数inRange来获取一定深度范围内的物体,进行二值化操作,并在此函数中设置两个阈值...
  • 项目实战——基于计算机视觉的物体位姿定位及机械臂矫正(二) 为什么进行相机标定 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像...
  • 项目实战——基于计算机视觉的物体位姿定位及机械臂矫正(基本原理)         首先让各位关注我的朋友们久等了,这个项目是我本科的毕业设计,写到四之后,我就一直忙于...
  • 项目实战——基于计算机视觉的物体位姿定位及机械臂矫正(一) 思路 经过这几天的资料查找,我逐步有了思路,现整理如下: 抓取物品定为牛奶盒,主要优势在于,质量轻、体积小、棱角分明,便于识别抓取; 工作...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,188
精华内容 18,875
关键字:

物体定位