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

相关文章

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

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

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

bytes.split的用法和注意事项

当然,我很乐意详细介绍 bytes.Split 的用法和注意事项。这个函数是 Go 标准库中 bytes 包的一个重要组成部分,用于分割字节切片。 基本用法 bytes.Split 的函数签名如下: func Split(s, sep []byte) [][]byte s 是要分割的字节切片sep 是用作分隔符的字节切片返回值是一个二维字节切片,包含分割后的结果 基本使用示例: pa

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

这些ES6用法你都会吗?

一 关于取值 取值在程序中非常常见,比如从对象obj中取值 const obj = {a:1b:2c:3d:4} 吐槽: const a = obj.a;const b = obj.b;const c = obj.c;//或者const f = obj.a + obj.b;const g = obj.c + obj.d; 改进:用ES6解构赋值

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段

Verybot之OpenCV应用三:色标跟踪

下面的这个应用主要完成的是Verybot跟踪色标的功能,识别部分还是居于OpenCV编写,色标跟踪一般需要将图像的颜色模式进行转换,将RGB转换为HSV,因为对HSV格式下的图像进行识别时受光线的影响比较小,但是也有采用RGB模式来进行识别的情况,这种情况一般光线条件比较固定,背景跟识别物在颜色上很容易区分出来。         下面这个程序的流程大致是这样的:

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i