OpenCV技术问询:如何从descriptors Mat提取指定KeyPoint对应的单个描述符
获取OpenCV中特定KeyPoint对应的特征描述符
嘿,这个问题我之前也碰到过,本质是对OpenCV特征描述符矩阵的结构理解有点偏差,咱们一步步来解决:
先搞懂描述符矩阵的结构
你用ORB提取的descriptors_1矩阵,每一行对应一个KeyPoint的描述符,而列数是描述符的维度(ORB默认是32维,如果你创建ORB时调整过参数,维度也可能是64,但核心逻辑不变)。
所以你看到的rows其实就是关键点的数量,和keypoints_1.size()是完全相等的,而cols是单个描述符的长度——这就是你觉得“行列和关键点数量不匹配”的原因,你可能误以为cols对应关键点数量啦。
你可以先验证一下,加两行代码打印看看:
cout << "关键点数量: " << keypoints_1.size() << endl; cout << "描述符矩阵行数: " << descriptors_1.rows << ", 列数: " << descriptors_1.cols << endl;
输出的行数和关键点数量肯定是一致的。
提取单个KeyPoint对应的描述符
知道了结构,提取指定位置(比如第12个)的描述符就很简单了,有几种常用方法:
方法1:直接提取行(最简洁)
因为每一行对应一个描述符,直接用row()方法提取:
// 获取第12个关键点的描述符,得到1xN的Mat(N是描述符维度) Mat single_descriptor = descriptors_1.row(12); // 如果需要列向量形式,转置即可 // single_descriptor = single_descriptor.t();
注意:这种方式得到的是原矩阵的引用,如果修改single_descriptor会影响原descriptors_1。如果需要独立的副本,加上clone():
Mat single_descriptor = descriptors_1.row(12).clone();
方法2:用Range范围提取
这种方式更灵活,适合提取连续多个描述符,单个的话写法是:
Mat single_descriptor = descriptors_1(Range(12, 13), Range::all());
Range(12,13)表示行索引从12到13(不包含13),也就是只取第12行;Range::all()表示取所有列。同样,需要副本的话加clone()。
完整示例代码
把你的代码和提取逻辑整合起来:
std::vector<KeyPoint> keypoints_1; Mat descriptors_1; Ptr<FeatureDetector> detector = ORB::create(); Ptr<DescriptorExtractor> descriptor = ORB::create(); detector->detect(img_1, keypoints_1); descriptor->compute(img_1, keypoints_1, descriptors_1); // 验证数量是否匹配 cout << "关键点数量: " << keypoints_1.size() << endl; cout << "描述符矩阵行数: " << descriptors_1.rows << ", 列数: " << descriptors_1.cols << endl; // 提取第12个关键点的描述符(注意索引从0开始,keypoints_1[12]是第13个关键点哦) if (keypoints_1.size() > 12) { Mat single_desc = descriptors_1.row(12).clone(); // 可以打印看看这个描述符的内容 cout << "第12个关键点的描述符:\n" << single_desc << endl; } else { cout << "关键点数量不足12个!" << endl; }
最后提醒一句:OpenCV的容器索引都是从0开始的,keypoints_1[12]是第13个关键点,别搞混啦~
内容的提问来源于stack exchange,提问作者anti
相关产品推荐
相关产品推荐

