opencv kdtree的用法

2024-06-07 23:18
文章标签 opencv 用法 kdtree

本文主要是介绍opencv kdtree的用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

求解如下红色点的3个最近邻居
在这里插入图片描述

1、测试代码
int main() {//用于构造kdtree的点集vector<cv::Point2f> features = { { 1,1 },{ 2, 2},{ 3, 3},{ 4, 4},{ 2, 4} };cv::Mat source = cv::Mat(features).reshape(1);source.convertTo(source, CV_32F);cv::flann::KDTreeIndexParams indexParams(2);cv::flann::Index kdtree(source, indexParams); //预设knnSearch所需参数及容器int queryNum = 3;//用于设置返回邻近点的个数vector<float> vecQuery(2);//存放查询点的容器vector<int> vecIndex(queryNum);//存放返回的点索引vector<float> vecDist(queryNum);//存放距离cv::flann::SearchParams params(32);//设置knnSearch搜索参数//KD树knn查询vecQuery = { 3, 4};kdtree.knnSearch(vecQuery, vecIndex, vecDist, queryNum, params);cout << "vecDist: " << endl;for (auto&x : vecDist)cout << x << " ";cout << endl;cout << "vecIndex: " << endl;for (auto&x : vecIndex)cout << x << " ";return 0;
}

输出:
vecDist: (注意这里是距离的平方)
1 1 1
vecIndex:
2 3 4

2、可能的问题

我写程序需要构建多个kdtree, 我试图用vector存储多个kdtree,我写成如下的代码就会报错

int main(){vector<cv::flann::Index> kdtrees;vector<cv::Point2f> features = { { 1,1 },{ 2, 2 },{ 3, 3 },{ 4, 4 },{ 2, 4 } };cv::Mat source = cv::Mat(features).reshape(1);cout << source;source.convertTo(source, CV_32F);cv::flann::KDTreeIndexParams indexParams(2);cv::flann::Index kdtree(source, indexParams);kdtrees.push_back(kdtree);
}

报错为:
在这里插入图片描述
这里显示的应该是vector释放的时候出了问题,初步查明 cv::flann::Index 这个class有一个 指针类型:void* index. 很有可能是浅拷贝的时候,释放kdtree的时候将 index释放,然后在释放vector的是时候再次释放index出了问题。

protected:cvflann::flann_distance_t distType;cvflann::flann_algorithm_t algo;int featureType;void* index;

因此,这里直接改为指针形式即可。

int main(){vector<cv::flann::Index*> kdtrees;vector<cv::Point2f> features = { { 1,1 },{ 2, 2 },{ 3, 3 },{ 4, 4 },{ 2, 4 } };cv::Mat source = cv::Mat(features).reshape(1);cout << source;source.convertTo(source, CV_32F);cv::flann::KDTreeIndexParams indexParams(2);cv::flann::Index* pkdtree = new cv::flann::Index(source, indexParams);kdtrees.push_back(pkdtree);
}

3、knnsearch返回无穷大的值

当我写成如下形式的时候(注意kdtrees后面加了局部作用域)

int main() {int queryNum = 3;//用于设置返回邻近点的个数vector<float> vecQuery(2);//存放查询点的容器vector<int> vecIndex(queryNum);//存放返回的点索引vector<float> vecDist(queryNum);//存放距离cv::flann::SearchParams params(32);//设置knnSearch搜索参数cv::flann::KDTreeIndexParams indexParams(2);vecQuery[0] = 3, vecQuery[1] = 4;vector<cv::flann::Index*> kdtrees;{vector<cv::Vec2d> features = { { 1,1 },{ 2, 2 },{ 3, 3 },{ 4, 4 },{ 2, 4 } };cv::Mat source = cv::Mat(features).reshape(1);source.convertTo(source, CV_32F);cv::flann::Index* kdtree = new cv::flann::Index(source, indexParams);kdtrees.push_back(kdtree);}kdtrees[0]->knnSearch(vecQuery, vecIndex, vecDist, queryNum, params);for (int i = 0; i < vecIndex.size(); i++)cout << "nearest id: " << vecIndex[i] << "\tdist:" << vecDist[i] << endl;return 0;
}

输出结果为:

nearest id: 2 dist:7.98718e+36
nearest id: 3 dist:7.98718e+36
nearest id: 4 dist:7.98718e+36

为何是这么大的值?调查发现构建kdtree使用的 cv::Mat source是局部变量,被释放后,kdtree被破坏,于是把cv::Mat source定义为全局变量即可。 最主要的问题是 opencv的矩阵如果是浅拷贝的话,有一个引用计数的问题,如果引用计数为0,那么数据会被释放。

int main() {int queryNum = 3;//用于设置返回邻近点的个数vector<float> vecQuery(2);//存放查询点的容器vector<int> vecIndex(queryNum);//存放返回的点索引vector<float> vecDist(queryNum);//存放距离cv::flann::SearchParams params(32);//设置knnSearch搜索参数cv::flann::KDTreeIndexParams indexParams(2);vecQuery[0] = 3, vecQuery[1] = 4;cv::Mat source;vector<cv::flann::Index*> kdtrees;{vector<cv::Vec2d> features = { { 1,1 },{ 2, 2 },{ 3, 3 },{ 4, 4 },{ 2, 4 } };source = cv::Mat(features).reshape(1);source.convertTo(source, CV_32F);cv::flann::Index* kdtree = new cv::flann::Index(source, indexParams);kdtrees.push_back(kdtree);}kdtrees[0]->knnSearch(vecQuery, vecIndex, vecDist, queryNum, params);for (int i = 0; i < vecIndex.size(); i++)cout << "nearest id: " << vecIndex[i] << "\tdist:" << vecDist[i] << endl;return 0;
}

这篇关于opencv kdtree的用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1040581

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

oracle中exists和not exists用法举例详解

《oracle中exists和notexists用法举例详解》:本文主要介绍oracle中exists和notexists用法的相关资料,EXISTS用于检测子查询是否返回任何行,而NOTE... 目录基本概念:举例语法pub_name总结 exists (sql 返回结果集为真)not exists (s

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

Springboot中Jackson用法详解

《Springboot中Jackson用法详解》Springboot自带默认json解析Jackson,可以在不引入其他json解析包情况下,解析json字段,下面我们就来聊聊Springboot中J... 目录前言Jackson用法将对象解析为json字符串将json解析为对象将json文件转换为json

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传