IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> slam14book2的ch7中3 -> 正文阅读

[数据结构与算法]slam14book2的ch7中3

slam14book2的ch7中3

使用了vins-mono和orbslam2的思想去实现了两个特征点均匀化的代码

// 特征点均匀化方法
// 

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;


struct node{
    int left;
    int right;
    int up;
    int down;
    vector<int> featureIndex;// 特征点的索引
};
// 父节点 总共的特征点 
// 这个不能用递归去做,要用队列去做---为了保证是平行调用的
void divisionNode(node &father, std::vector<KeyPoint>& keypoints, int targetNum, vector<KeyPoint>& rekeypoints){
    queue<node *> nodeQue;
    nodeQue.push(&father);// 把根结点入队
    int sizet = 0;
    cout << keypoints.size() << endl;
    while(1){
        // 分为上下左右四个区域
        node* nowmakenode = nodeQue.front();
        nodeQue.pop();
        // 新建node节点
        node* leftup = new node();
        node* rightup = new node();
        node* leftdown = new node();
        node* rightdown = new node();
        // 把father node的特征点给分了
        int h_middle = (nowmakenode->up + nowmakenode->down)/2;// 240
        int l_middle = (nowmakenode->left + nowmakenode->right)/2;// 320
        leftup->left = nowmakenode->left;
        leftup->up = nowmakenode->up;
        leftup->right = l_middle;
        leftup->down = h_middle;

        rightup->left = l_middle;
        rightup->up = nowmakenode->up;
        rightup->right = nowmakenode->right;
        rightup->down = h_middle;

        leftdown->left = nowmakenode->left;
        leftdown->up = h_middle;
        leftdown->right = l_middle;
        leftdown->down = nowmakenode->down;

        rightdown->left = l_middle;
        rightdown->up = h_middle;
        rightdown->right = nowmakenode->right;
        rightdown->down = nowmakenode->down;
        // 按照两个middle进行索引去
        for(int i = 0; i < nowmakenode->featureIndex.size(); i++){
            Point2f nowpoint = keypoints[nowmakenode->featureIndex[i]].pt;
            if(nowpoint.y < l_middle){// 在左边
                if(nowpoint.x < h_middle){// 在上面
                    leftup->featureIndex.push_back(nowmakenode->featureIndex[i]);
                }else{
                    leftdown->featureIndex.push_back(nowmakenode->featureIndex[i]);
                }
            }else{// 在右面
                if(nowpoint.x < h_middle){// 在上面
                    rightup->featureIndex.push_back(nowmakenode->featureIndex[i]);
                }else{
                    rightdown->featureIndex.push_back(nowmakenode->featureIndex[i]);
                }
            }
        }

        // 如果size == 1,直接把这个节点塞进去
        //          》 1加入到queue中
        //         == 0 直接free掉
        if(leftup->featureIndex.size() == 0) delete leftup;
        else if(leftup->featureIndex.size() == 1){
            sizet++;
            rekeypoints.push_back(keypoints[leftup->featureIndex[0]]);
            delete leftup;
        }else{
            nodeQue.push(leftup);
        }

        if(leftdown->featureIndex.size() == 0) delete leftdown;
        else if(leftdown->featureIndex.size() == 1){
            sizet++;
            rekeypoints.push_back(keypoints[leftdown->featureIndex[0]]);
            delete leftdown;
        }else{
            nodeQue.push(leftdown);
        }

        if(rightup->featureIndex.size() == 0) delete rightup;
        else if(rightup->featureIndex.size() == 1){
            sizet++;
            rekeypoints.push_back(keypoints[rightup->featureIndex[0]]);
            delete rightup;
        }else{
            nodeQue.push(rightup);
        }

        if(rightdown->featureIndex.size() == 0) delete rightdown;
        else if(rightdown->featureIndex.size() == 1){
            sizet++;
            rekeypoints.push_back(keypoints[rightdown->featureIndex[0]]);
            delete rightdown;
        }else{
            nodeQue.push(rightdown);
        }
        cout << "nodeQue:" <<  nodeQue.size() << endl;
        // 判断下数量
        if(sizet + nodeQue.size() >= targetNum ){// 数量够了
            while(nodeQue.size()>0){
                // 简单的就只要第一个点
                node* makenode = nodeQue.front();
                nodeQue.pop();
                rekeypoints.push_back(keypoints[makenode->featureIndex[0]]);
                delete makenode;
            }
            break;
        }
       
        if(nodeQue.size() == 0){//所有节点都不能分裂了
            break;
        }
        //break;

    }

} 

int main(char argc, char **argv){
    // read picture
    Mat img= imread("1.png");
	if (!img.data)
	{
		cout << "error reading images " << endl;
		return -1;
	}
    Mat gry;
    cvtColor(img, gry, COLOR_BGR2GRAY);
    std::vector<KeyPoint> keypoints;//关键点容器  二维点
    Mat descriptors;			      //关键点对应的描述子
    Ptr<FeatureDetector> detector = ORB::create();  //cv3下 ORB特征检测    其他 BRISK   FREAK
    Ptr<DescriptorExtractor> descriptor = ORB::create();//cv3下 ORB描述子
    Ptr<DescriptorMatcher> matcher  = DescriptorMatcher::create ( "BruteForce-Hamming" );
    detector->detect (gry,keypoints );
    Mat showImage1;
    drawKeypoints( img, keypoints, showImage1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
    // 原图展示
    imshow("picture",showImage1);
    
    // 使用vins mono的方法进行极大值抑制的方法
    // 光流追踪的上一帧数据进行操作,按照光流追踪的评分进行排序
    // 按照排序的情况放进图片中,如果那个位置被mask了就跳过
    // 如果没有被mask过,就给他加入到集合中,然后在mask图片上这个特征点周围画一个圆

    // 依照此策略直接开干(假设特征点已经按照评分进行排序了)
    vector<KeyPoint> resiveID;
    Mat mask = cv::Mat(img.rows, img.cols, CV_8UC1, cv::Scalar(255));
    int MIN_DIST = 10;// 10个像素之内不再接受这个
    for(int i = 0; i < keypoints.size(); i++){
        Point2f pointLocation = keypoints[i].pt;// 点
        if (mask.at<uchar>(pointLocation) == 255){ // 是否被占用
            resiveID.push_back(keypoints[i]);// 
            cv::circle(mask, pointLocation, MIN_DIST, 0, -1);
        }
    }
    // show
    Mat showImage2;
    drawKeypoints( img, resiveID, showImage2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
    // vins策略展示
    imshow("picture2",showImage2);


    // 再使用orbslam2的策略
    // orbslam2使用了一个四叉树的结构,只要分裂个数没有到达想要留下特征点的个数,就会接着分裂
    vector<KeyPoint> resivepoint2;
    node father;
    father.left = 0;
    father.right = img.cols;
    father.up = 0;
    father.down = img.rows;
    for(int i = 0; i < keypoints.size(); i++) 
        father.featureIndex.push_back(i);
    divisionNode(father, keypoints, 30, resivepoint2);
    cout << "orb:" << resivepoint2.size() << endl; 
    Mat showImage3;
   
    drawKeypoints( img, resivepoint2, showImage3, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
    imshow("picture3",showImage3);

   
    waitKey(0);

}

实验效果记录:

原图

请添加图片描述

vins-mono思想

请添加图片描述

orb-slam2思想

请添加图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 23:27:37  更:2022-04-06 23:29:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:56:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码