YungeCui / BoW3D

[RA-L] BoW3D: Bag of Words for Real-Time Loop Closing in 3D LiDAR SLAM.
277 stars 39 forks source link

逐帧比较的代码咨询 #6

Closed SlamCabbage closed 1 year ago

SlamCabbage commented 1 year ago

你好,我现在在使用您的代码做一件另外的事情:不同时间的场景识别。主要任务是想要实现:第一个时间采集的一个场景中的点云帧全部作为Frames加入到bow3d中,然后用另一个时间采集的同一场景的帧去与之前的bow3d对比,查看该方法的场景识别能力。我做出了如下的代码修改,您能帮我看看,我有没有误解您的代码呢? 声明: ` void retrieve(Frame pCurrentFrame, std::vector &matchedFrames, std::vector &scores);` 定义: 其中pCurrentFrame是传入的不同时间采集的点云帧,matchedFrames是用来保存score前10的查找到的匹配帧。

    void BoW3D::retrieve(Frame *pCurrentFrame, std::vector<int> &matchedFrames, std::vector<double> &scores)
    {
        // int frameId = pCurrentFrame->mnId;

        cv::Mat descriptors = pCurrentFrame->mDescriptors;
        size_t rowSize = descriptors.rows;

        std::vector<std::pair<int, double>> sortedFrames;

        for (auto &keyframe : mvFrames)
        {
            int keyframeId = keyframe->mnId;
            cv::Mat keyframeDescriptors = keyframe->mDescriptors;
            double score = 0.0;

            for (size_t i = 0; i < rowSize; i++)
            {
                unordered_map<pair<int, int>, int, pair_hash> mPlaceScore;

                float *p = descriptors.ptr<float>(i);

                int countValue = 0;

                for (size_t j = 0; j < (size_t)descriptors.cols; j++)
                {
                    countValue++;

                    if (p[j] != 0)
                    {
                        pair<float, int> word = make_pair(p[j], j);
                        auto wordPlacesIter = this->find(word);

                        if (wordPlacesIter == this->end())
                        {
                            continue;
                        }
                        else
                        {
                            double averNumInPlaceSet = N_nw_ofRatio.second / N_nw_ofRatio.first;
                            int curNumOfPlaces = (wordPlacesIter->second).size();

                            double ratio = curNumOfPlaces / averNumInPlaceSet;

                            if (ratio > thr)
                            {
                                continue;
                            }

                            for (auto placesIter = (wordPlacesIter->second).begin(); placesIter != (wordPlacesIter->second).end(); placesIter++)
                            {
                                // The interval between the loop and the current frame should be at least 300.
                                // if (keyframeId - (*placesIter).first < 300)
                                // {
                                //     continue;
                                // }

                                auto placeNumIt = mPlaceScore.find(*placesIter);

                                if (placeNumIt == mPlaceScore.end())
                                {
                                    mPlaceScore[*placesIter] = 1;
                                }
                                else
                                {
                                    mPlaceScore[*placesIter]++;
                                }
                            }
                        }
                    }
                }

                for (auto placeScoreIter = mPlaceScore.begin(); placeScoreIter != mPlaceScore.end(); placeScoreIter++)
                {
                    if ((*placeScoreIter).second > thf)
                    {
                        score += (*placeScoreIter).second;
                    }
                }
            }

            sortedFrames.emplace_back(keyframeId, score);
        }

        // Sort the frames by score in descending order.
        std::sort(sortedFrames.begin(), sortedFrames.end(), [](const auto &a, const auto &b)
                  { return a.second > b.second; });

        matchedFrames.clear();
        scores.clear();

        // Return the top 10 frames.
        for (size_t i = 0; i < std::min(sortedFrames.size(), static_cast<size_t>(10)); ++i)
        {
            matchedFrames.emplace_back(sortedFrames[i].first);
            scores.emplace_back(sortedFrames[i].second);
        }
    }

再次感谢您,期待您的回复。

YungeCui commented 1 year ago

你好,我大体看了一下,思路应该没问题,但是我没有编译,还需要你自己试一下结果有没有问题。另外,这个函数返回的很可能是一串时间相近或连续的帧,你称它们为关键帧可能不是太合适。​

SlamCabbage commented 1 year ago

非常感谢,我想保存的是score最大的10帧,作为top10输出