编写GPU版本的FLANN算法

头文件.h:

                /**

                 * @brief GPU加速的Flann描述符匹配器

                 *

                 * 这个匹配器使用FLANN库来进行描述符的匹配,并使用GPU加速来提高性能。

                 */

                class GpuFlannBasedMatcher : public cv::DescriptorMatcher {

                public:

                    // 构造函数

                    CV_WRAP GpuFlannBasedMatcher(

                        const cv::Ptr<cv::flann::IndexParams>& indexParams = cv::makePtr<cv::flann::KDTreeIndexParams>(),

                        const cv::Ptr<cv::flann::SearchParams>& searchParams = cv::makePtr<cv::flann::SearchParams>()

                        // int addedDescCount = 0

                    );

               

                    // 添加描述符到GPU

                    virtual void add(cv::InputArrayOfArrays descriptors) CV_OVERRIDE;

               

                    // 清除已添加的描述符

                    virtual void clear() CV_OVERRIDE;

                    // Reads matcher object from a file node

                    virtual void read( const FileNode& ) CV_OVERRIDE;

                    // Writes matcher object to a file storage

                    virtual void write( FileStorage& ) const CV_OVERRIDE;                    

               

                    // 训练FLANN索引

                    virtual void train() CV_OVERRIDE;

                    virtual bool isMaskSupported() const CV_OVERRIDE;

                    CV_WRAP static Ptr<GpuFlannBasedMatcher> create();

                    CV_NODISCARD_STD virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const CV_OVERRIDE;

                    // KNN匹配

                    CV_WRAP virtual void knnMatchImpl(cv::InputArray queryDescriptors,

                                                    std::vector<std::vector<cv::DMatch>>& matches,

                                                    int k,

                                                    cv::InputArrayOfArrays masks = cv::noArray(),

                                                    bool compactResult = false) CV_OVERRIDE;

               

                    // 半径匹配

                    virtual void radiusMatchImpl(cv::InputArray queryDescriptors,

                                                std::vector<std::vector<cv::DMatch>>& matches,

                                                float maxDistance,

                                                cv::InputArrayOfArrays masks = cv::noArray(),

                                                bool compactResult = false) CV_OVERRIDE;

               

                protected:

                    // 将FLANN搜索结果转换为DMatch格式

                    static void convertToDMatches(const std::vector<cv::Mat>& descriptors,

                                                const cv::Mat& indices,

                                                const cv::Mat& distances,

                                                std::vector<std::vector<cv::DMatch>>& matches);

               

                private:

                    cv::Ptr<cv::flann::IndexParams> indexParams;  // FLANN索引参数

                    cv::Ptr<cv::flann::SearchParams> searchParams;  // FLANN搜索参数

                    cv::Ptr<cv::flann::Index> flannIndex;  // FLANN索引

               

                    std::vector<cv::cuda::GpuMat> descriptorsGpu;  // 存储GPU上的描述符

                    int addedDescCount;

                };

.cpp文件函数实现:

                // 构造函数实现

                GpuFlannBasedMatcher::GpuFlannBasedMatcher(

                    const cv::Ptr<cv::flann::IndexParams>& indexParams,

                    const cv::Ptr<cv::flann::SearchParams>& searchParams

                ) : indexParams(indexParams), searchParams(searchParams){

                    // 初始化 flannIndex 或者其他成员变量

                }

                // 添加描述符

                void GpuFlannBasedMatcher::add(cv::InputArrayOfArrays descriptors) {

                    // 将每个描述符上传到GPU内存

                    for (size_t i = 0; i < descriptors.total(); ++i) {

                        descriptorsGpu.push_back(cv::cuda::GpuMat(descriptors.getMat(i)));

                    }

                }

                // 清除描述符

                void GpuFlannBasedMatcher::clear() {

                    descriptorsGpu.clear();

                    addedDescCount = 0;

                }

                void GpuFlannBasedMatcher::read( const FileNode& fn)

                {

                     if (!indexParams)

                         indexParams = makePtr<flann::IndexParams>();

               

                     FileNode ip = fn["indexParams"];

                     CV_Assert(ip.type() == FileNode::SEQ);

               

                     for(int i = 0; i < (int)ip.size(); ++i)

                     {

                        CV_Assert(ip[i].type() == FileNode::MAP);

                        String _name =  (String)ip[i]["name"];

                        FlannIndexType type = (FlannIndexType)(int)ip[i]["type"];

                        CV_CheckLE((int)type, (int)LAST_VALUE_FLANN_INDEX_TYPE, "");

               

                        switch(type)

                        {

                        case FLANN_INDEX_TYPE_8U:

                        case FLANN_INDEX_TYPE_8S:

                        case FLANN_INDEX_TYPE_16U:

                        case FLANN_INDEX_TYPE_16S:

                        case FLANN_INDEX_TYPE_32S:

                            indexParams->setInt(_name, (int) ip[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_32F:

                            indexParams->setFloat(_name, (float) ip[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_64F:

                            indexParams->setDouble(_name, (double) ip[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_STRING:

                            indexParams->setString(_name, (String) ip[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_BOOL:

                            indexParams->setBool(_name, (int) ip[i]["value"] != 0);

                            break;

                        case FLANN_INDEX_TYPE_ALGORITHM:

                            indexParams->setAlgorithm((int) ip[i]["value"]);

                            break;

                        // don't default: - compiler warning is here

                        };

                     }

               

                     if (!searchParams)

                         searchParams = makePtr<flann::SearchParams>();

               

                     FileNode sp = fn["searchParams"];

                     CV_Assert(sp.type() == FileNode::SEQ);

               

                     for(int i = 0; i < (int)sp.size(); ++i)

                     {

                        CV_Assert(sp[i].type() == FileNode::MAP);

                        String _name =  (String)sp[i]["name"];

                        FlannIndexType type = (FlannIndexType)(int)sp[i]["type"];

                        CV_CheckLE((int)type, (int)LAST_VALUE_FLANN_INDEX_TYPE, "");

               

                        switch(type)

                        {

                        case FLANN_INDEX_TYPE_8U:

                        case FLANN_INDEX_TYPE_8S:

                        case FLANN_INDEX_TYPE_16U:

                        case FLANN_INDEX_TYPE_16S:

                        case FLANN_INDEX_TYPE_32S:

                            searchParams->setInt(_name, (int) sp[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_32F:

                            searchParams->setFloat(_name, (float) sp[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_64F:

                            searchParams->setDouble(_name, (double) sp[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_STRING:

                            searchParams->setString(_name, (String) sp[i]["value"]);

                            break;

                        case FLANN_INDEX_TYPE_BOOL:

                            searchParams->setBool(_name, (int) sp[i]["value"] != 0);

                            break;

                        case FLANN_INDEX_TYPE_ALGORITHM:

                            searchParams->setAlgorithm((int) sp[i]["value"]);

                            break;

                        // don't default: - compiler warning is here

                        };

                     }

               

                    flannIndex.release();

                }

               

                void GpuFlannBasedMatcher::write( FileStorage& fs) const

                {

                     writeFormat(fs);

                     fs << "indexParams" << "[";

               

                     if (indexParams)

                     {

                         std::vector<String> names;

                         std::vector<FlannIndexType> types;

                         std::vector<String> strValues;

                         std::vector<double> numValues;

               

                         indexParams->getAll(names, types, strValues, numValues);

               

                         for(size_t i = 0; i < names.size(); ++i)

                         {

                             fs << "{" << "name" << names[i] << "type" << types[i] << "value";

                             FlannIndexType type = (FlannIndexType)types[i];

                             if ((int)type < 0 || type > LAST_VALUE_FLANN_INDEX_TYPE)

                             {

                                 fs << (double)numValues[i];

                                 fs << "typename" << strValues[i];

                                 fs << "}";

                                 continue;

                             }

                             switch(type)

                             {

                             case FLANN_INDEX_TYPE_8U:

                                 fs << (uchar)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_8S:

                                 fs << (char)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_16U:

                                 fs << (ushort)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_16S:

                                 fs << (short)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_32S:

                             case FLANN_INDEX_TYPE_BOOL:

                             case FLANN_INDEX_TYPE_ALGORITHM:

                                 fs << (int)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_32F:

                                 fs << (float)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_64F:

                                 fs << (double)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_STRING:

                                 fs << strValues[i];

                                 break;

                             // don't default: - compiler warning is here

                             }

                             fs << "}";

                         }

                     }

               

                     fs << "]" << "searchParams" << "[";

               

                     if (searchParams)

                     {

                         std::vector<String> names;

                         std::vector<FlannIndexType> types;

                         std::vector<String> strValues;

                         std::vector<double> numValues;

               

                         searchParams->getAll(names, types, strValues, numValues);

               

                         for(size_t i = 0; i < names.size(); ++i)

                         {

                             fs << "{" << "name" << names[i] << "type" << types[i] << "value";

                             FlannIndexType type = (FlannIndexType)types[i];

                             if ((int)type < 0 || type > LAST_VALUE_FLANN_INDEX_TYPE)

                             {

                                 fs << (double)numValues[i];

                                 fs << "typename" << strValues[i];

                                 fs << "}";

                                 continue;

                             }

                             switch(type)

                             {

                             case FLANN_INDEX_TYPE_8U:

                                 fs << (uchar)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_8S:

                                 fs << (char)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_16U:

                                 fs << (ushort)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_16S:

                                 fs << (short)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_32S:

                             case FLANN_INDEX_TYPE_BOOL:

                             case FLANN_INDEX_TYPE_ALGORITHM:

                                 fs << (int)numValues[i];

                                 break;

                             case CV_32F:

                                 fs << (float)numValues[i];

                                 break;

                             case CV_64F:

                                 fs << (double)numValues[i];

                                 break;

                             case FLANN_INDEX_TYPE_STRING:

                                 fs << strValues[i];

                                 break;

                             // don't default: - compiler warning is here

                             }

                             fs << "}";

                         }

                     }

                     fs << "]";

                }

               

                bool GpuFlannBasedMatcher::isMaskSupported() const

                {

                    return false;

                }

               

                Ptr<DescriptorMatcher> GpuFlannBasedMatcher::clone( bool emptyTrainData ) const

                {

                    Ptr<GpuFlannBasedMatcher> matcher = makePtr<GpuFlannBasedMatcher>(indexParams, searchParams);

                    if( !emptyTrainData )

                    {

                        CV_Error( Error::StsNotImplemented, "deep clone functionality is not implemented, because "

                                  "Flann::Index has not copy constructor or clone method ");

                #if 0

                        //matcher->flannIndex;

                        matcher->addedDescCount = addedDescCount;

                        matcher->mergedDescriptors = DescriptorCollection( mergedDescriptors );

                        std::transform( trainDescCollection.begin(), trainDescCollection.end(),

                                        matcher->trainDescCollection.begin(), clone_op );

                #endif

                    }

                    return matcher;

                }                



 

                // 训练 FLANN 索引

                void GpuFlannBasedMatcher::train() {

                    // 将所有的GPU描述符下载到CPU

                    std::vector<cv::Mat> cpuDescriptors;

                    for (size_t i = 0; i < descriptorsGpu.size(); ++i) {

                        cv::Mat temp;

                        descriptorsGpu[i].download(temp);  // 修正download调用,传入一个cv::Mat作为参数

                        cpuDescriptors.push_back(temp);

                    }

           

                    // 将所有描述符合并成一个单独的矩阵

                    cv::Mat allDescriptors;

                    cv::vconcat(cpuDescriptors, allDescriptors);

           

                    // 使用合并后的描述符训练FLANN索引(索引训练在CPU上进行)

                    flannIndex = cv::makePtr<cv::flann::Index>(allDescriptors, *indexParams);

                }

                // KNN 匹配实现

                void GpuFlannBasedMatcher::knnMatchImpl(

                    cv::InputArray queryDescriptors,

                    std::vector<std::vector<cv::DMatch>>& matches,

                    int k,

                    cv::InputArrayOfArrays masks,

                    bool compactResult

                ) {

                            // 将查询描述符上传到GPU

                            cv::cuda::GpuMat queryDescriptorsGpu = cv::cuda::GpuMat(queryDescriptors.getMat());

                   

                            // 创建存储匹配结果的GPU矩阵

                            cv::cuda::GpuMat indices(queryDescriptorsGpu.rows, k, CV_32SC1);  // 索引矩阵

                            cv::cuda::GpuMat distances(queryDescriptorsGpu.rows, k, CV_32FC1);  // 距离矩阵

                   

                            // 在GPU上执行FLANN的KNN搜索,返回匹配的索引和距离

                            flannIndex->knnSearch(queryDescriptorsGpu, indices, distances, k, *searchParams);

                   

                            // 下载GPU上的搜索结果到CPU

                            cv::Mat indicesMat;

                            indices.download(indicesMat);  // 修正download调用,传入cv::Mat对象

                            cv::Mat distancesMat;

                            distances.download(distancesMat);  // 修正download调用,传入cv::Mat对象

                   

                            // 将匹配结果转换为DMatch格式

                            // convertToDMatches(queryDescriptors, indicesMat, distancesMat, matches);

                            std::vector<cv::Mat> queryDescsVec;

                            queryDescriptors.getMatVector(queryDescsVec);

                            convertToDMatches(queryDescsVec, indicesMat, distancesMat, matches);

                }

                // 半径匹配实现

                void GpuFlannBasedMatcher::radiusMatchImpl(

                    cv::InputArray queryDescriptors,

                    std::vector<std::vector<cv::DMatch>>& matches,

                    float maxDistance,

                    cv::InputArrayOfArrays masks,

                    bool compactResult

                ) {

                    // 将查询描述符传输到GPU

                    cv::cuda::GpuMat queryGpuDescriptors;

                    queryGpuDescriptors.upload(queryDescriptors.getMat());

                    // 创建存储结果的GPU矩阵

                    cv::cuda::GpuMat indicesGpu, distancesGpu;

                    // 如果描述符索引未创建,先创建FLANN索引

                    if (flannIndex.empty()) {

                        // 使用默认的FLANN索引类型(KDTree)

                        // flannIndex = cv::flann::Index(queryGpuDescriptors, *indexParams);

                        flannIndex = cv::makePtr<cv::flann::Index>(queryGpuDescriptors, *indexParams);

                    }

                    // 执行半径匹配

                    // flannIndex->radiusMatch(queryGpuDescriptors, indicesGpu, distancesGpu, maxDistance, *searchParams);

                    // flannIndex->radiusSearch(queryGpuDescriptors, indicesGpu, distancesGpu, maxDistance, *searchParams);

                    flannIndex->radiusSearch(queryGpuDescriptors, indicesGpu, distancesGpu, maxDistance, 0, *searchParams);

                    // 下载结果到CPU

                    cv::Mat indicesMat, distancesMat;

                    indicesGpu.download(indicesMat);

                    distancesGpu.download(distancesMat);

                    // 处理结果并转换为DMatch格式

                    matches.resize(indicesMat.rows);

                    for (int i = 0; i < indicesMat.rows; ++i) {

                        std::vector<cv::DMatch> matchRow;

                        for (int j = 0; j < indicesMat.cols; ++j) {

                            int index = indicesMat.at<int>(i, j);

                            if (index >= 0 && distancesMat.at<float>(i, j) <= maxDistance) {

                                matchRow.push_back(cv::DMatch(i, index, distancesMat.at<float>(i, j)));

                            }

                        }

                        matches[i] = matchRow;

                    }

                }

                // 将 FLANN 索引结果转换为 DMatch 格式

                void GpuFlannBasedMatcher::convertToDMatches(

                    const std::vector<cv::Mat>& descriptors,

                    const cv::Mat& indices,

                    const cv::Mat& distances,

                    std::vector<std::vector<cv::DMatch>>& matches

                ) {

                    matches.clear();

                    for (int i = 0; i < indices.rows; ++i) {

                        std::vector<cv::DMatch> rowMatches;

                        for (int j = 0; j < indices.cols; ++j) {

                            int idx = indices.at<int>(i, j);  // 获取匹配的索引

                            float dist = distances.at<float>(i, j);  // 获取匹配的距离

                            rowMatches.push_back(cv::DMatch(i, idx, dist));  // 创建DMatch对象

                        }

                        matches.push_back(rowMatches);

                    }

                }            

编译:

### 配置 GPU 加速以实现高效的点云处理 为了在 Ubuntu 系统上配置 GPU 加速来高效地处理点云数据,需要安装一系列必要的库和支持工具。这不仅涉及基础的操作系统环境准备,还包括特定于点云处理的软件包。 #### 安装 NVIDIA 显卡驱动程序 确保已正确安装适用于系统的最新版本 NVIDIA 显卡驱动程序。可以通过官方文档获取详细的安装指南[^1]。这是启用 GPU 计算的前提条件之一。 #### 安装 CUDA 工具包 CUDA 是由 NVIDIA 开发的一个平行计算平台和应用程序接口(API),它允许开发者利用 GPU 的强大性能来进行通用目的运算。对于希望使用 GPU 进行加速的应用来说,安装 CUDA 至关重要。建议按照官方说明完成 CUDA 的安装过程,并验证其是否正常工作。 #### 设置 cuDNN 库 cuDNN 是一个针对深度神经网络应用优化过的高性能库,能够显著提升训练速度。下载与所使用的 CUDA 版本兼容的 cuDNN 后解压并将文件复制到相应目录下即可完成设置。 #### 安装 TensorFlow 或 PyTorch 深度学习框架 选择合适的深度学习框架如 TensorFlow 或者 PyTorch 来加载预训练模型或编写自定义算法。这两个框架都提供了良好的 GPU 支持选项,在安装过程中需指定要链接至哪个版本的 CUDA 和 cuDNN[^3]。 #### 编译 PCL Point Cloud Library with VTK and FLANN support Point Cloud Library (PCL) 是一个专门用来处理三维点云数据的强大开源库。编译带有 VTK 可视化功能以及快速最近邻搜索算法FLANN支持的 PCL 将有助于更有效地管理和分析大规模点云集合。具体步骤如下: ```bash sudo apt-essential libvtk7-dev libflann1.9 libeigen3-dev git clone https://github.com/PointCloudLibrary/pcl.git cd pcl mkdir build && cd build cmake .. -DVTK_DIR=/usr/lib/x86_64-linux-gnu/vtk-7.1/ make -j$(nproc) sudo make install ``` 以上命令会从源码编译最新的 PCL 并开启 GPU 加速特性,同时关联之前提到的一些依赖项如 VTK、FLANN 和 Eigen。 #### 使用 Open3DSOT 实现 LiDAR 数据的目标跟踪 如果专注于自动驾驶领域内的点云单目标追踪,则可以考虑采用基于 PyTorch Lightning 构建的 Open3DSOT 框架。此项目已经集成了多种先进的 SOT 方法论和技术栈,可以直接应用于实际场景中去测试效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

搬砖者(视觉算法工程师)

绝对物超所值的干货

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

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

打赏作者

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

抵扣说明:

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

余额充值