OpenCV (c++)使用KDTree时,得到正确结果后报Segmentation fault (core dumped)

一、给出问题

构建包含以下文件的工程(opencv_test)
在这里插入图片描述
各文件内容给出如下:

# CMakeLists.txt
cmake_minimum_required(VERSION 2.18)
project(opencv_test)

find_package(OpenCV REQUIRED)

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(${PROJECT_NAME} main.cpp
                                kdtree.cpp 
                                kdtree.h)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
// kdtree.cpp
#include "kdtree.h"
KDTree::KDTree(std::vector<Point> ref_points)
{
    ref_points_ = ref_points;
	ConstructKDTree(kdtree_);
}

void KDTree::ConstructKDTree(cv::flann::Index* kdtree) // C1
{
    std::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);
    kdtree = new cv::flann::Index(source, indexParams); // C2
}

void KDTree::GetIndex()
{
	//预设knnSearch所需参数及容器
	int queryNum = 3;//用于设置返回邻近点的个数
	std::vector<float> vecQuery(2);//存放查询点的容器
	std::vector<int> vecIndex(queryNum);//存放返回的点索引
	std::vector<float> vecDist(queryNum);//存放距离
	cv::flann::SearchParams params(32);//设置knnSearch搜索参数

	//KD树knn查询
	vecQuery = { 3, 4};
    printf("ok31\n");
	kdtree_->knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
    printf("ok32\n");
	std::cout << "vecDist: " << std::endl;
	for (auto&x : vecDist)
		std::cout << x << " ";
	std::cout << std::endl;

	std::cout << "vecIndex: " << std::endl;
	for (auto&x : vecIndex)
		std::cout << x << " ";
    std::cout<<std::endl;
}

// kdtree.h
#ifndef KDTREE_H
#define KDTREE_H
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <memory>

struct Point{
    double x;
    double y;
    double z;
};

class KDTree{
    public:
    KDTree(std::vector<Point> ref_points);

    void ConstructKDTree(cv::flann::Index* kdtree);  // C4
    void GetIndex();

    private:
    // cv::Mat source;
    std::vector<Point> ref_points_;
    cv::flann::Index* kdtree_;  // C5
};

#endif // KDTREE_H
// main.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include "kdtree.h"

int main() {
	//用于构造kdtree的点集
    std::vector<Point> points;
    KDTree kdtree = KDTree(points);
    kdtree.GetIndex();
	return 0;
}

构建好后

cd ~/opencv_test/build
cmake ..
make
./opencv_test

报错:
ok31
Segmentation fault (core dumped)

根据标记可知,运行到kdtree->knnSearch(...)这里出错的。

根据opencv kdtree的用法后半部分描述的:
在这里插入图片描述
所以,感觉和指针释放有关。于是做了几组实验,分别记录成功不不成功的情况。

二、不同组合的实验与结果

实验通过:对上面代码中注释有C1-C5的各行进行不同设置。

2.1 指针引用cv::flann::Index*& kdtree作为函数输入(成功)

void KDTree::ConstructKDTree(cv::flann::Index*& kdtree) // C1  变化
kdtree = new cv::flann::Index(source, indexParams); // C2
kdtree_->knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
void ConstructKDTree(cv::flann::Index*& kdtree);  // C4  变化
cv::flann::Index* kdtree_;  // C5

在这里插入图片描述

2.2 继2.1后,采用内置函数build构建kdtree(失败)

void KDTree::ConstructKDTree(cv::flann::Index*& kdtree) // C1  变化
kdtree->build(source, indexParams);  // C2  变化
kdtree_->knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
void ConstructKDTree(cv::flann::Index*& kdtree);  // C4  变化
cv::flann::Index* kdtree_;  // C5

内置函数build也可以构建kdtree
在这里插入图片描述
发现,直接在kdtree->build(...)处报错。

2.3 采用变量引用cv::flann::Index& kdtree(成功)

void KDTree::ConstructKDTree(cv::flann::Index& kdtree) // C1  变化
kdtree.build(source, indexParams);  // C2  变化
kdtree_.knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
void ConstructKDTree(cv::flann::Index& kdtree);  // C4  变化
cv::flann::Index kdtree_;  // C5

在这里插入图片描述

2.4 在2.3基础上采用类构造函数实例化kdtree(失败)

void KDTree::ConstructKDTree(cv::flann::Index& kdtree) // C1  变化
kdtree = cv::flann::Index(source, indexParams);  // C2  变化
kdtree_.knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
void ConstructKDTree(cv::flann::Index& kdtree);  // C4  变化
cv::flann::Index kdtree_;  // C5

在这里插入图片描述
根据标记可知,运行到kdtree.knnSearch(...)这里出错的。

2.5 在2.4基础上,成员函数不用引用输入

void KDTree::ConstructKDTree(cv::flann::Index kdtree) // C1  变化
kdtree = cv::flann::Index(source, indexParams);  // C2  变化
kdtree_.knnSearch(vecQuery, vecIndex, vecDist, queryNum, params); // C3
void ConstructKDTree(cv::flann::Index kdtree);  // C4  变化
cv::flann::Index kdtree_;  // C5

在这里插入图片描述
根据标记可知,初始化kdtree时就出错。

结论

  • 内部成员函数传入kdtree变量,无论是否是指针,都要以引用的方式传入;
  • 如果是指针变量,以kdtree = new cv::flann::Index(source, indexParams);构建kdtree;
  • 如果是一般变量,则以kdtree.build(source, indexParams);构建kdtree.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

windSeS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值