OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
表面匹配

详细描述

关于许可和专利的注意事项

本软件中体现的方法已获得以下专利:“使用几何点对描述符和广义霍夫变换进行三维场景中三维物体的识别和姿态确定”,Bertram Heinrich Drost, Markus Ulrich, 欧洲专利 2385483 (2012年11月21日),受让人:MVTec Software GmbH, 81675 慕尼黑 (德国);“三维场景中三维物体的识别和姿态确定”,Bertram Heinrich Drost, Markus Ulrich, 美国专利 8830229 (2014年9月9日),受让人:MVTec Software GmbH, 81675 慕尼黑 (德国)。其他专利正在申请中。欲了解更多详情,请联系 MVTec Software GmbH (info@.nosp@m.mvte.nosp@m.c.com)。

请注意,这些专利(以及可能存在的其他专利)所施加的限制独立于本许可授予的自由,并可能与之冲突;本许可指的是程序的著作权,而非其所实现方法的专利。合法使用和再分发本程序必须遵守著作权法和专利法,本许可的目的并非诱导您侵犯任何专利或其他财产权主张,或质疑任何此类主张的有效性。如果您再分发或使用本程序,本许可仅保护您免受著作权侵权。它不保护您免受专利侵权。因此,在对本程序进行任何操作之前,请确保您不仅获得了著作权方面的许可,还获得了专利法方面的许可。

请注意,本许可也不应被理解为一种担保。如果您依据本许可使用本程序,但其使用与专利法冲突,并不意味着如果您因专利侵权而被起诉,许可方会赔偿您所遭受的任何损失。

表面匹配简介

具有三维结构感知能力的相机及类似设备正变得越来越普遍。因此,利用深度和强度信息进行三维物体(或部分)匹配对于计算机视觉至关重要。应用范围从工业控制到指导视障人士的日常行动。在距离图像中进行识别和姿态估计的任务旨在通过将其与获取的数据库进行匹配来识别和定位查询的三维自由曲面物体。

从工业角度来看,使机器人能够自动定位并从料箱中拾取随机放置和定向的物体,是工厂自动化中的一个重要挑战,它取代了繁琐而繁重的体力劳动。一个系统应该能够识别和定位具有预定义形状的物体,并以抓取机器人拾取所需的精度估计位置。这就是视觉引导机器人技术发挥作用的地方。类似的工具还能够引导机器人(甚至人类)穿越非结构化环境,从而实现自动化导航。这些特性使得从点云进行三维匹配成为一项普遍需求。在此背景下,我将介绍 OpenCV 中使用三维特征的三维物体识别和姿态估计算法的实现。

基于三维特征的表面匹配算法

实现三维匹配任务的算法现状主要基于 [74],这是该领域最早和主要实用的方法之一。该方法包括从深度图像或通用点云中随机提取三维特征点,对其进行索引,然后在运行时高效地查询它们。只考虑三维结构,并使用一个简单的哈希表进行特征查询。

尽管我充分意识到利用良好的 CAD 模型结构可以实现智能点采样,但我现在将暂不讨论这一点,以尊重方法的通用性(通常对于此类算法,不需要在 CAD 模型上进行训练,点云就足够了)。下面是整个算法的概述

算法概述

如前所述,该算法依赖于点对特征的提取和索引,其定义如下

\[\bf{{F}}(\bf{{m1}}, \bf{{m2}}) = (||\bf{{d}}||_2, <(\bf{{n1}},\bf{{d}}), <(\bf{{n2}},\bf{{d}}), <(\bf{{n1}},\bf{{n2}}))\]

其中 \(\bf{{m1}}\) 和 \(\bf{{m2}}\) 是模型(或场景)上选定的两个特征点,\(\bf{{d}}\) 是差向量,\(\bf{{n1}}\) 和 \(\bf{{n2}}\) 是 \(\bf{{m1}}\) 和 \(\bf{m2}\) 处的法线。在训练阶段,此向量被量化并索引。在测试阶段,从场景中提取相同的特征并与数据库进行比较。通过一些技巧,例如分离旋转分量,姿态估计部分也可以变得高效(详情请查阅参考文献)。采用类似霍夫变换的投票和聚类方法来估计物体姿态。为了对姿态进行聚类,原始姿态假设按投票数降序排列。从投票数最高的假设开始,创建一个新簇。如果下一个姿态假设接近现有簇之一,则将其添加到该簇中,并更新簇中心,使其成为簇内姿态假设的平均值。如果下一个假设不接近任何现有簇,则创建一个新簇。邻近性测试使用平移和旋转的固定阈值进行。平移的距离计算和平均在三维欧几里得空间中进行,而旋转的距离计算和平均则使用四元数表示进行。聚类后,簇按总投票数降序排列,这决定了估计姿态的置信度。

该姿态将使用 \(ICP\) 进一步细化,以获得最终姿态。

上面介绍的 PPF 主要依赖于三维向量之间角度的鲁棒计算。尽管论文中未提及,但这种计算的朴素方法( \(\theta = cos^{-1}({\bf{a}}\cdot{\bf{b}})\) )在数值上仍然不稳定。更好的方法是使用反正切,例如

\[<(\bf{n1},\bf{n2})=tan^{-1}(||{\bf{n1} \wedge \bf{n2}}||_2, \bf{n1} \cdot \bf{n2})\]

给定 PPF 的物体姿态粗略计算

我将总结以下符号

点对特征中的变换是通过首先找到从第一个点到 \(T_{m\rightarrow g}\) 的变换,然后将相同的变换应用于第二个点来计算的。将每个点及其法线变换到地面,在与新点对进行比较时,我们还需要找出其角度。

现在我们可以简单地开始写

\[(p^i_m)^{'} = T_{m\rightarrow g} p^i_m\]

其中

\[T_{m\rightarrow g} = -t_{m\rightarrow g}R_{m\rightarrow g}\]

请注意,这不过是一个堆叠变换。平移分量 \(t_{m\rightarrow g}\) 为

\[t_{m\rightarrow g} = -R_{m\rightarrow g}p^i_m\]

旋转分量为

\[\theta_{m\rightarrow g} = \cos^{-1}(n^i_m \cdot {\bf{x}})\\ {\bf{R_{m\rightarrow g}}} = n^i_m \wedge {\bf{x}}\]

以轴角格式表示。请注意,粗体表示向量形式。经过此变换后,模型的特征向量被注册到地平面 X 上,相对于 \(x=0\) 的角度称为 \(\alpha_m\) 。类似地,对于场景,其角度称为 \(\alpha_s\) 。

类似霍夫变换的投票方案

如概述所示,在训练阶段,PPF(点对特征)从模型中提取、量化、存储在哈希表中并进行索引。然而,在运行时,对输入场景执行类似的操作,不同之处在于此时执行的是哈希表上的相似性查找,而不是插入。这种查找还允许我们为场景点对计算到地面的变换。此后,姿态的旋转分量计算简化为计算差值 \(\alpha=\alpha_m-\alpha_s\) 。这个分量携带着关于物体姿态的线索。在局部模型坐标向量和 \(\alpha\) 上执行类似霍夫变换的投票方案。每个场景点获得的最高姿态使我们能够恢复物体姿态。

PPF 匹配的源代码

// pc 是模型的已加载点云 (Nx6),pcTest 是场景的已加载点云 (Mx6)
ppf_match_3d::PPF3DDetector detector(0.03, 0.05);
detector.trainModel(pc);
vector<Pose3DPtr> results;
detector.match(pcTest, results, 1.0/10.0, 0.05);
cout << "Poses: " << endl;
// 打印姿态
for (size_t i=0; i<results.size(); i++)
Pose3DPtr pose = results[i];
cout << "Pose Result " << i << endl;
{
pose->printPose();
cv::ppf_match_3d::Pose3DPtr
Ptr< Pose3D > Pose3DPtr
}
通过 ICP 进行姿态配准
匹配过程以姿态的获得而结束。然而,由于多个匹配点、错误假设、姿态平均等因素,这样的姿态非常容易受到噪声影响,并且很多时候远非完美。尽管在该阶段获得的视觉结果令人满意,但定量评估显示存在约 \(10\) 度的变化(误差),这是一个可接受的匹配水平。很多时候,要求可能会远远超出这个范围,因此需要对计算出的姿态进行细化。

此外,在典型的 RGBD 场景和点云中,由于场景中的可见性,三维结构只能捕获不到模型一半的信息。因此,一种能够快速准确地配准被遮挡和部分可见形状的鲁棒姿态细化算法并非不切实际的愿望。

在这一点上,一个简单的选择是使用众所周知的迭代最近点算法。然而,使用基本的 ICP 会导致收敛速度慢、配准效果差、对异常值敏感以及无法配准部分形状。因此,它肯定不适合这个问题。因此,已经提出了许多变体。不同的变体对姿态估计过程的不同阶段有所贡献。

ICP 由 \(6\) 个阶段组成,我为每个阶段提出的改进总结如下。

采样

为了提高收敛速度和计算时间,通常使用的点数少于模型实际拥有的点数。然而,采样正确的点进行配准本身就是一个问题。朴素的方法是均匀采样并希望获得一个合理的子集。更智能的方法试图识别关键点,这些点被发现对配准过程有很大贡献。Gelfand 等人利用协方差矩阵来约束特征空间,从而使用一组同时影响平移和旋转的点。这是一种巧妙的二次采样方法,我将选择性地在实现中使用。

对应点搜索

顾名思义,这一步实际上是按照最近点的方式将数据中的点与模型中的点进行对应。正确的对应将导致正确的姿态,而错误的对应会严重降低结果。通常,KD 树用于最近邻搜索,以提高速度。然而,这并不能保证最优性,并且许多时候会导致错误的点被匹配。幸运的是,对应关系会随着迭代而得到纠正。

为了克服一些限制,挑剔型 ICP [324] 和 BC-ICP(使用双唯一对应关系的 ICP)是两种众所周知的方法。挑剔型 ICP 首先以传统方式找到对应关系,然后在结果对应对中,如果有多个场景点 \(p_i\) 被分配到同一个模型点 \(m_j\),它会选择与最小距离对应的 \(p_i\) 。另一方面,BC-ICP 首先允许多个对应关系,然后通过建立双唯一对应关系来解决分配。它还定义了一种新颖的无对应异常值,这本身就简化了识别异常值的过程。

作为参考,两种方法都使用了。由于 P-ICP 稍快一些,且性能劣势不那么显著,它将是对应关系细化的首选方法。

点对加权

在我的实现中,目前没有使用加权方案。但常见的方法包括法线兼容性*( \(w_i=n^1_i\cdot n^2_j\) )或对距离较大的点对分配较低的权重( \(w=1-\frac{||dist(m_i,s_i)||_2}{dist_{max}}\) )。

点对剔除

剔除是使用基于标准差的鲁棒估计的动态阈值进行的。换句话说,在每次迭代中,我都会找到标准差的 MAD 估计值。我将其表示为 \(mad_i\) 。我剔除距离 \(d_i>\tau mad_i\) 的点对。这里 \(\tau\) 是剔除阈值,默认设置为 \(3\) 。加权在挑剔型细化之前应用,这在上一阶段已经解释过。

误差度量

如 [175] 中所述,使用了点到平面误差度量的线性化方法。这既加快了配准过程,又提高了收敛性。

最小化

尽管提出了许多非线性优化器(如 Levenberg-Marquardt),但由于上一步的线性化,姿态估计简化为求解线性方程组。我正是使用 cv::solve 并选择 `DECOMP_SVD` 选项来完成此操作。

ICP 算法

在介绍了上述步骤之后,我在此总结 ICP 算法的布局。

通过点云金字塔实现高效 ICP

虽然迄今为止提出的变体能很好地处理一些异常值和不良初始化,但它们需要大量的迭代次数。然而,多分辨率方案可以通过允许配准从粗略级别开始并传播到更低和更精细的级别来帮助减少迭代次数。这种方法既提高了性能又增强了运行时效率。

搜索以分层方式通过多个级别进行。配准从模型的非常粗略的样本集开始。点被迭代地加密和搜索。每次迭代后,将先前估计的姿态用作初始姿态,并使用 ICP 进行细化。

视觉结果

合成数据上的结果

在所有结果中,姿态都由 PPF 初始化,其余部分保留为: \([\theta_x, \theta_y, \theta_z, t_x, t_y, t_z]=[0]\)

使用 ICP 进行姿态细化的源代码

ICP icp(200, 0.001f, 2.5f, 8);

// 使用前面声明的 pc 和 pcTest

// 这将对 results 中包含的每个姿态执行配准
icp.registerModelToScene(pc, pcTest, results);
// results 现在包含细化后的姿态
结果
本节专门介绍表面匹配(点对特征匹配和随后的 ICP 细化)的结果
使用 ppf + icp 对单个青蛙模型进行多次匹配

Mian 数据集不同模型的匹配结果如下所示

Mian 数据集不同模型的匹配

您可以在 YouTube 上观看视频

完整示例

参数调优

表面匹配模块在可能的情况下,将其参数相对于模型直径(轴平行包围盒的直径)进行处理。这使得参数独立于模型大小。这就是为什么模型和场景点云都进行了二次采样,使得所有点之间的最小距离为 \(RelativeSamplingStep*DimensionRange\),其中 \(DimensionRange\) 是给定维度上的距离。所有三个维度都以类似的方式进行采样。例如,如果 \(RelativeSamplingStep\) 设置为 0.05,模型直径为 1 米(1000 毫米),那么从物体表面采样的点将大约相距 50 毫米。从另一个角度看,如果采样 \(RelativeSamplingStep\) 设置为 0.05,最多将生成 \(20x20x20 = 8000\) 个模型点(取决于模型如何填充体积)。因此,这导致最多 8000x8000 对。实际上,由于模型并非均匀分布在矩形棱柱上,因此预计点数会少得多。减小此值会导致更多的模型点,从而获得更准确的表示。然而,请注意,要计算的点对特征的数量现在呈二次方增长,因为复杂度是 O(N\^2)。这对于 32 位系统来说尤其值得关注,因为大型模型很容易超出可用内存。通常,0.025 - 0.05 范围内的值对于大多数应用来说似乎是足够的,其中默认值为 0.03。(请注意,此参数与 [74] 中介绍的参数存在差异。在 [74] 中,使用均匀立方体进行量化,并使用模型直径作为采样的参考。在我的实现中,立方体是一个矩形棱柱,每个维度都独立量化。我不是以直径为参考,而是沿着各个维度进行参考。

最初从模型中移除异常值并准备一个理想模型将是非常明智的。这是因为,异常值直接影响相对计算并降低匹配精度。

在运行时阶段,场景再次按照上面描述的 \(RelativeSamplingStep\) 进行采样。然而这次,只有一部分场景点被用作参考。这部分由参数 \(RelativeSceneSampleStep\) 控制,其中 \(SceneSampleStep = (int)(1.0/RelativeSceneSampleStep)\) 。换句话说,如果 \(RelativeSceneSampleStep = 1.0/5.0\),二次采样后的场景将再次均匀采样到原始点数的 1/5。此参数的最大值为 1,增加此参数也会增加稳定性,但会降低速度。再次强调,由于初始的场景无关相对采样,微调此参数不是一个大问题。这只会在模型形状均匀占据一个体积,或者模型形状在量化体积中凝聚在一个很小的位置时(例如,八叉树表示会有太多空单元格)才成为问题。

\(RelativeDistanceStep\) 作为哈希表上的离散化步长。点对特征被量化以映射到哈希表的桶中。这种离散化涉及乘法和向整数的类型转换。理论上,调整 \(RelativeDistanceStep\) 控制碰撞率。请注意,哈希表上的更多碰撞会导致更不准确的估计。减小此参数会增加量化的影响,但会开始将不相似的点对分配到相同的桶中。然而,增加它会削弱对相似点对进行分组的能力。通常,由于在采样阶段,训练模型点是根据 RelativeSamplingStep 控制的距离均匀选择的,因此 RelativeDistanceStep 预计等于此值。然而,0.025-0.05 范围内的值是合理的。但这次,当模型密集时,不建议减小此值。对于有噪声的场景,可以增加该值以提高匹配对噪声点的鲁棒性。

cv::ppf_match_3d::ICP

该类实现了迭代最近点(ICP)算法的一个非常高效且鲁棒的变体。任务是将三维模型(或点云)与一组带噪声的目标数据进行配准。这些变体是我在经过某些测试后组合而成的。任务是能够快速匹配杂乱场景中的部分、带噪声的点云。您会发现我的重点在于性能,同时保持准确性。此实现基于 Tolga Birdal 的 MATLAB 实现,链接在此:http://www.mathworks.com/matlabcentral/fileexchange/47152-icp-registration-using-efficient-variants-and-multi-resolution-scheme 主要贡献来自:更多...

cv::ppf_match_3d::Pose3D

结构体  hashnode_i
 
结构体  hashtable_int
 
类  类,用于存储姿态。该数据结构同时存储四元数和矩阵形式。它支持 I/O 功能以及各种处理姿态的辅助方法。更多...
 cv::ppf_match_3d::PoseCluster3D
 
类  当多个姿态(参见 Pose3D)被组合在一起(对相同的变换做出贡献)时,就会出现姿态簇。该类是此类姿态组的通用容器。可以存储、加载和对这些姿态执行 I/O 操作。更多...
 cv::ppf_match_3d::PPF3DDetector
 
类  类,用于加载和匹配三维模型。典型用法:更多...
 THash
 
类  结构体,表示哈希表中的一个节点。更多...
 typedef uint 
 
结构体  cv::ppf_match_3d::KeyType
 typedef Ptr< Pose3D
 

类型定义

typedef Ptr< PoseCluster3Dcv::ppf_match_3d::PoseCluster3DPtr
 
Mat 定义 pose_3d.hpp:59
 
cv::ppf_match_3d::addNoisePC (Mat pc, double scale)cv::ppf_match_3d::computeBboxStd (Mat pc, Vec2f &xRange, Vec2f &yRange, Vec2f &zRange)
 

函数

cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)计算任意点云的法线。computeNormalsPC3d 使用平面拟合方法平滑地计算局部法线。法线是通过协方差矩阵中对应于最小特征值的特征向量获得的。如果 PCNormals 提供为 Nx6 矩阵,则不进行新的分配,而是覆盖现有内存。
 
void cv::ppf_match_3d::destroyFlann (void *flannIndex)
 
int cv::ppf_match_3d::getRandomPose (Matx44d &Pose)
 hashtable_int
 
void cv::ppf_match_3d::hashtable_int_clone (hashtable_int *hashtbl)
 
void cv::ppf_match_3d::hashtableCreate (size_t size, size_t(*hashfunc)(uint))
 
cv::ppf_match_3d::hashtableDestroy (hashtable_int *hashtbl)cv::ppf_match_3d::hashtableGet (hashtable_int *hashtbl, KeyType key)
 
cv::ppf_match_3d::hashtableDestroy (hashtable_int *hashtbl)hashnode_i
 
void cv::ppf_match_3d::hashtableGetBucketHashed (hashtable_int *hashtbl, KeyType key)
 
void * cv::ppf_match_3d::hashtableInsert (hashtable_int *hashtbl, KeyType key, void *data)
 
cv::ppf_match_3d::hashtableInsertHashed (hashtable_int *hashtbl, KeyType key, void *data)cv::ppf_match_3d::hashtablePrint (hashtable_int *hashtbl)
 
int cv::ppf_match_3d::hashtableRead (FILE *f)
 
int cv::ppf_match_3d::hashtableRemove (hashtable_int *hashtbl, KeyType key)
 
void cv::ppf_match_3d::hashtableResize (hashtable_int *hashtbl, size_t size)
 
cv::ppf_match_3d::hashtableDestroy (hashtable_int *hashtbl)cv::ppf_match_3d::hashtableWrite (const hashtable_int *hashtbl, const size_t dataSize, FILE *f)
 
int cv::ppf_match_3d::indexPCFlann (Mat pc)
 
int cv::ppf_match_3d::loadPLYSimple (const char *fileName, int withNormals=0)
 
int 加载 PLY 文件。
 
void * static uint 
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::next_power_of_two (uint value)
 向上舍入到下一个最高的 2 的幂。
 
cv::ppf_match_3d::normalizePCCoeff (Mat pc, float scale, float *Cx, float *Cy, float *Cz, float *MinVal, float *MaxVal)cv::ppf_match_3d::queryPCFlann (void *flannIndex, Mat &pc, Mat &indices, Mat &distances)
 cv::ppf_match_3d::queryPCFlann (void *flannIndex, Mat &pc, Mat &indices, Mat &distances, const int numNeighbors)
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::samplePCByQuantization (Mat pc, Vec2f &xrange, Vec2f &yrange, Vec2f &zrange, float sample_step_relative, int weightByCenter=0)
 
void cv::ppf_match_3d::samplePCUniform (Mat PC, int sampleStep)
 
void cv::ppf_match_3d::samplePCUniformInd (Mat PC, int sampleStep, std::vector< int > &indices)
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::transformPCPose (Mat pc, const Matx44d &Pose)
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::transPCCoeff (Mat pc, float scale, float Cx, float Cy, float Cz, float MinVal, float MaxVal)
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::writePLY (Mat PC, const char *fileName)
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)将点云写入 PLY 文件。
 
cv::ppf_match_3d::computeNormalsPC3d (const Mat &PC, Mat &PCNormals, const int NumNeighbors, const bool FlipViewpoint, const Vec3f &viewpoint)cv::ppf_match_3d::writePLYVisibleNormals (Mat PC, const char *fileName)
 
void 用于调试目的,将点云写入 PLY 文件,并将法线向量的尖端作为可见的红点。
 ◆ KeyType
 
void typedef uint cv::ppf_match_3d::KeyType
 #include <opencv2/surface_matching/t_hash_int.hpp>
 

类型定义文档

◆ Pose3DPtr

◆ PoseCluster3DPtr

Mat cv::ppf_match_3d::addNoisePC

pc

◆ addNoisePC()

函数文档

scale )

cv.ppf_match_3d.addNoisePC( ( Mat pc, scale,
double #include <opencv2/surface_matching/ppf_helpers.hpp>
Python
以给定尺度向输入点云添加均匀噪声输入点云(CV_32F 系列)。) -> retval

输入噪声的尺度。尺度越大,输出噪声越大

◆ computeBboxStd()

参数
[输入]pc, scalevoid cv::ppf_match_3d::computeBboxStd
[输入]scaleVec2f

xRange

yRange ( Mat pc, scale,
zRange ) & ◆ computeNormalsPC3d(),
zRange ) & int cv::ppf_match_3d::computeNormalsPC3d,
zRange ) & const Mat &

输入噪声的尺度。尺度越大,输出噪声越大

PC

PCNormals ( NumNeighbors FlipViewpoint,
Mat & const Vec3f &,
const int viewpoint ),
const bool cv.ppf_match_3d.computeNormalsPC3d(,
PC, NumNeighbors, FlipViewpoint, viewpoint[, PCNormals] retval, PCNormals
Python
用于计算法线的输入点云。输出点云) -> 在局部区域考虑的邻居数量

输入噪声的尺度。尺度越大,输出噪声越大

hashtable_int

参数
[输入]FlipViewpoint法线是否应翻转到视点方向?
[输出]const Vec3f &视点
[输入]viewpoint )成功时返回 0
[输入]cv.ppf_match_3d.computeNormalsPC3d(◆ destroyFlann()
[输入]void cv::ppf_match_3d::destroyFlann
返回
flannIndex

◆ getRandomPose()

void cv::ppf_match_3d::getRandomPose ( void * Pose)

输入噪声的尺度。尺度越大,输出噪声越大

cv.ppf_match_3d.getRandomPose(

生成一个随机的 4x4 姿态矩阵 ( Matx44d & 随机姿态)
Python
◆ hashtable_int_clone()随机姿态) ->

输入噪声的尺度。尺度越大,输出噪声越大

hashtable_int * cv::ppf_match_3d::hashtable_int_clone

参数
[输出]随机姿态hashtbl

◆ hashtableCreate()

hashtable_int * cv::ppf_match_3d::hashtableCreate ( hashtable_int * size_t(*)

hashfunc )(uint) )

◆ hashtableDestroy() ( size_t size,
void cv::ppf_match_3d::hashtableDestroy ◆ hashtableGet()

void * cv::ppf_match_3d::hashtableGet

KeyType ( hashtable_int * size_t(*)

key )

◆ hashtableGetBucketHashed() ( hashtable_int * size_t(*,
hashnode_i * cv::ppf_match_3d::hashtableGetBucketHashed ◆ hashtableInsert()

int cv::ppf_match_3d::hashtableInsert

data ) ( hashtable_int * size_t(*,
hashnode_i * cv::ppf_match_3d::hashtableGetBucketHashed ◆ hashtableInsert()

◆ hashtableInsertHashed()

int cv::ppf_match_3d::hashtableInsertHashed ( hashtable_int * size_t(*,
hashnode_i * cv::ppf_match_3d::hashtableGetBucketHashed key,
void * ◆ hashtablePrint()

void cv::ppf_match_3d::hashtablePrint

◆ hashtableRead() ( hashtable_int * size_t(*,
hashnode_i * cv::ppf_match_3d::hashtableGetBucketHashed key,
void * ◆ hashtablePrint()

hashtable_int * cv::ppf_match_3d::hashtableRead

FILE * ( hashtable_int * size_t(*)

f

◆ hashtableRemove() ( int cv::ppf_match_3d::hashtableRemove ◆ hashtableResize())

int cv::ppf_match_3d::hashtableResize

◆ hashtableWrite() ( hashtable_int * size_t(*,
hashnode_i * cv::ppf_match_3d::hashtableGetBucketHashed ◆ hashtableInsert()

int cv::ppf_match_3d::hashtableWrite

const hashtable_int * ( hashtable_int * size_t(*,
size_t size )

dataSize

f ) ( ◆ indexPCFlann() size_t(*,
const size_t void * cv::ppf_match_3d::indexPCFlann,
int cv::ppf_match_3d::hashtableRemove ◆ loadPLYSimple()

Mat cv::ppf_match_3d::loadPLYSimple

withNormals = 0 ) ( Mat pc, scale)

输入噪声的尺度。尺度越大,输出噪声越大

cv.ppf_match_3d.loadPLYSimple(

fileName[, withNormals] ( const char * fileName,
int 要读取的 PLY 模型
Python
withNormals指示输入 PLY 是否包含法线信息,以及是否应该加载的标志) -> retval

输入噪声的尺度。尺度越大,输出噪声越大

向上舍入到下一个最高的 2 的幂。

参数
[输入]fileName成功加载时返回矩阵
[输入]◆ next_power_of_two()static uint cv::ppf_match_3d::next_power_of_two
返回
inlinestatic

来自 http://www-graphics.stanford.edu/~seander/bithacks.html

◆ normalizePCCoeff() ( uint )
Mat cv::ppf_match_3d::normalizePCCoeff

#include <opencv2/surface_matching/pose_3d.hpp>

cv::ppf_match_3d::queryPCFlann (void *flannIndex, Mat &pc, Mat &indices, Mat &distances, const int numNeighbors)

Cx

Cy

Cz ( Mat pc, scale,
float scale,
float * MinVal,
float * MaxVal ),
float * ◆ queryPCFlann() [1/2],
float * void cv::ppf_match_3d::queryPCFlann,
float * distances )

输入噪声的尺度。尺度越大,输出噪声越大

◆ queryPCFlann() [2/2]

distances ( void * Pose,
Mat & pc, scale,
Mat & 索引,
Mat & numNeighbors )

输入噪声的尺度。尺度越大,输出噪声越大

◆ samplePCByQuantization()

distances ( void * Pose,
Mat & pc, scale,
Mat & 索引,
Mat & Mat cv::ppf_match_3d::samplePCByQuantization,
const int xrange

输入噪声的尺度。尺度越大,输出噪声越大

yrange

zrange ( Mat pc, scale,
zRange ) & sample_step_relative,
zRange ) & weightByCenter = 0 ),
zRange ) & cv.ppf_match_3d.samplePCByQuantization(,
float pc, xrange, yrange, zrange, sample_step_relative[, weightByCenter],
int 使用均匀步长对点云进行采样
Python
输入点云模型包围盒的 X 分量(最小值和最大值)) -> retval

输入噪声的尺度。尺度越大,输出噪声越大

模型包围盒的 Y 分量(最小值和最大值)

参数
[输入]pc, scale模型包围盒的 Z 分量(最小值和最大值)
[输入]sample_step_relative点云的采样方式是使所有点都具有一定的最小距离。这个最小距离是使用参数 sample_step_relative 相对确定的。
[输入]weightByCenter = 0 )weightByCenter
[输入]cv.ppf_match_3d.samplePCByQuantization(量化数据点的贡献可以通过到原点的距离进行加权。此参数启用/禁用加权的使用。
[输入]pc, xrange, yrange, zrange, sample_step_relative[, weightByCenter]采样点云
[输入]◆ samplePCUniform()Mat cv::ppf_match_3d::samplePCUniform
返回
sampleStep )

◆ samplePCUniformInd()

Mat cv::ppf_match_3d::samplePCUniformInd ( Mat FlipViewpoint,
int sampleStep

输入噪声的尺度。尺度越大,输出噪声越大

indices )

◆ transformPCPose() ( Mat FlipViewpoint,
int Mat cv::ppf_match_3d::transformPCPose,
std::vector< int > & const Matx44d &

输入噪声的尺度。尺度越大,输出噪声越大

Pose )

cv.ppf_match_3d.transformPCPose( ( Mat pc, scale,
pc, Pose 使用给定的齐次 4x4 姿态矩阵(双精度)变换点云
Python
输入点云(CV_32F 系列)。每行预期有 3 或 6 个元素的点云。如果提供了法线,它们也会被旋转以与整个变换兼容4x4 姿态矩阵,但以行主序形式线性化。) -> retval

输入噪声的尺度。尺度越大,输出噪声越大

变换后的点云

参数
[输入]pc, scale◆ transPCCoeff()
[输入]随机姿态Mat cv::ppf_match_3d::transPCCoeff
返回
◆ writePLY()

void cv::ppf_match_3d::writePLY

fileName ) ( Mat pc, scale,
float scale,
float MinVal,
float MaxVal ),
float ◆ queryPCFlann() [1/2],
float void cv::ppf_match_3d::queryPCFlann,
float distances )

输入噪声的尺度。尺度越大,输出噪声越大

cv.ppf_match_3d.writePLY(

PC, fileName ( Mat FlipViewpoint,
const char * 要写入的 PLY 模型文件
Python
◆ writePLYVisibleNormals()void cv::ppf_match_3d::writePLYVisibleNormals) ->

输入噪声的尺度。尺度越大,输出噪声越大

◆ KeyType

参数
[输入]FlipViewpoint模型包围盒的 Z 分量(最小值和最大值)
[输入]fileNamecv.ppf_match_3d.writePLYVisibleNormals(

OpenCV 文档生成于 2025 年 7 月 3 日星期四 12:14:37,由 doxygen 1.12.0

void cv::ppf_match_3d::writePLYVisibleNormals ( Mat FlipViewpoint,
const char * 要写入的 PLY 模型文件
Python
cv.ppf_match_3d.writePLYVisibleNormals(void cv::ppf_match_3d::writePLYVisibleNormals) ->

输入噪声的尺度。尺度越大,输出噪声越大

#include <opencv2/surface_matching/t_hash_int.hpp>

参数
[输入]FlipViewpoint模型包围盒的 Z 分量(最小值和最大值)
[输入]fileNamecv.ppf_match_3d.writePLYVisibleNormals(