数据的均匀化分割算法(网格划分法、四叉树法(含C++代码))

数据的均匀化分割主要是指在分割过程中尽可能均匀地将数据点分布在各个子区域中,以保持数据分布的平衡和优化数据结构的性能。以下是几种可以实现数据均匀化分割的方法:

一. 网格划分法

1. 基本概念

        虽然传统的网格划分法不是动态调整的,但通过设计可以实现均匀的空间分割。例如,可以根据数据点的分布密度来调整网格的划分粒度,使得每个网格单元内包含的数据点数量尽量均匀。

        具体的,二维网格划分是一种对二维空间进行均匀分割的技术,用于将这种空间划分为多个小的、有时是规则的区域或单元,称为“网格”或“格子”。在图像处理中,二维网格划分可以用于将图像划分成小块进行局部分析或并行处理,从而加速图像处理任务如滤波、特征检测等。

2. 示例

  我有一组特征点存储在 std::vector<cv::KeyPoint> 类型的变量 vToDistributeKeys 中。这些特征点位于一张大小为宽1276像素、高378像素的图片上。为了在二维空间上实现点的均匀分布,我需要将图片分割成一个6x6的网格(共36个方块)。在每个方块内,我希望只保留具有最大置信度的特征点,并删除该方块内的其他点。下面是实现这一功能的具体C++代码。

#include <iostream>
#include <vector>
#include <opencv2/core/types.hpp>

// 将特征点按网格均匀分布,每个网格只保留置信度最高的特征点
std::vector<cv::KeyPoint> distributeAndFilterKeys(const std::vector<cv::KeyPoint>& keypoints, int width, int height, int gridRows, int gridCols) {
    // 计算每个网格的尺寸
    int cellWidth = width / gridCols;
    int cellHeight = height / gridRows;
    
    // 初始化网格,用于存储每个网格的最高置信度的特征点
    std::vector<std::vector<cv::KeyPoint>> grid(gridRows, std::vector<cv::KeyPoint>(gridCols));

    // 遍历所有特征点
    for (const auto& keypoint : keypoints) {
        int gridX = keypoint.pt.x / cellWidth;
        int gridY = keypoint.pt.y / cellHeight;

        // 确保网格索引不越界
        if (gridX >= gridCols) gridX = gridCols - 1;
        if (gridY >= gridRows) gridY = gridRows - 1;

        // 检查当前网格是否已有特征点,或者当前特征点置信度是否更高
        if (!grid[gridY][gridX].empty() && grid[gridY][gridX][0].response < keypoint.response) {
            grid[gridY][gridX][0] = keypoint;
        } else if (grid[gridY][gridX].empty()) {
            grid[gridY][gridX].push_back(keypoint);
        }
    }

    // 收集所有网格中的最佳特征点
    std::vector<cv::KeyPoint> filteredKeyPoints;
    for (int y = 0; y < gridRows; ++y) {
        for (int x = 0; x < gridCols; ++x) {
            if (!grid[y][x].empty()) {
                filteredKeyPoints.push_back(grid[y][x][0]);
            }
        }
    }

    return filteredKeyPoints;
}

int main() {
    // 假设的特征点数据
    std::vector<cv::KeyPoint> keypoints = {
        {cv::Point2f(100, 50), 1.f, -1, 0.8},
        {cv::Point2f(120, 60), 1.f, -1, 0.9},
        {cv::Point2f(130, 55), 1.f, -1, 0.95},
        // 添加更多点以测试
    };

    // 图片尺寸和网格配置
    int width = 1276;
    int height = 378;
    int gridRows = 6;
    int gridCols = 6;

    // 处理特征点
    std::vector<cv::KeyPoint> filteredKeyPoints = distributeAndFilterKeys(keypoints, width, height, gridRows, gridCols);

    // 输出结果
    for (const auto& kp : filteredKeyPoints) {
        std::cout << "Keypoint at (" << kp.pt.x << ", " << kp.pt.y << ") with response: " << kp.response << std::endl;
    }

    return 0;
}

二. 四叉树均匀化与非极大值抑制结合使用

在实际应用中,可以先对ORB特征点进行四叉树均匀化,然后再对每个子区域内的特征点进行非极大值抑制。这样可以在保证特征点分布均匀性的同时,提高特征点的质量和稳定性,最终得到更优的特征点集合。

1. 四叉树的基本概念

        在图像中,某些区域可能存在大量的特征点,而其他区域可能只有很少的特征点。这种不均匀分布会影响特征点的代表性和匹配效果。

        首先把一幅图案或一个幅面分割成多个分区或者部分。如果某个子区域内的特征点数量少于某个预设阈值,或者已经达到了分割的最小尺度,则这个子区域不再进行分割。如果特征点过于密集,则继续将这个区域分割成四个更小的子区域,并递归地对每个子区域进行同样的分割过程,直至每个子区域内的特征点数量满足预设条件。

        通过控制划分的停止条件(如特征点数量少于阈值、达到最小分割尺寸等),可以在保证足够的特征点总数的同时,让特征点在图像的不同区域内尽可能均匀分布。

        在划分完成后,每个子区域内可能包含多个特征点。为了进一步提高均匀性和代表性,可以在每个子区域内只保留响应值最大的特征点,去除其他的特征点。

2. 非极大值抑制

        非极大值抑制是一种常用的特征点后处理方法,主要用于去除临近区域内响应值较低的特征点,保留局部最大的特征点。其基本原理是,对于每个特征点,检查其周围邻域内是否存在响应值更大的特征点。如果存在,则将当前特征点去除;如果不存在,则保留当前特征点。

3. 示例

      一组特征点存储在 std::vector<cv::KeyPoint> 类型的变量 vToDistributeKeys 中。这些特征点分布在一张宽为1276像素、高为378像素的图片上。要求将图片分割成至少25个区域。

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

// 定义四叉树节点结构体
struct QuadTreeNode {
    cv::Rect rect;  // 节点代表的区域
    std::vector<cv::KeyPoint> keypoints;  // 节点内的特征点
    QuadTreeNode* children[4];  // 子节点指针

    QuadTreeNode(cv::Rect _rect) : rect(_rect) {
        for (int i = 0; i < 4; i++) {
            children[i] = nullptr;
        }
    }
};

// 递归建立四叉树
void buildQuadTree(QuadTreeNode* node, const std::vector<cv::KeyPoint>& keypoints, int minPoints, int maxLevel, int level) {
    if (level >= maxLevel || node->keypoints.size() <= minPoints) {
        return;
    }

    // 将当前节点划分为四个子区域
    int halfWidth = node->rect.width / 2;
    int halfHeight = node->rect.height / 2;
    cv::Rect childRects[4] = {
        cv::Rect(node->rect.x, node->rect.y, halfWidth, halfHeight),
        cv::Rect(node->rect.x + halfWidth, node->rect.y, halfWidth, halfHeight),
        cv::Rect(node->rect.x, node->rect.y + halfHeight, halfWidth, halfHeight),
        cv::Rect(node->rect.x + halfWidth, node->rect.y + halfHeight, halfWidth, halfHeight)
    };

    // 为每个子区域创建子节点
    for (int i = 0; i < 4; i++) {
        node->children[i] = new QuadTreeNode(childRects[i]);
    }

    // 将特征点分配到子节点中
    for (const auto& keypoint : node->keypoints) {
        for (int i = 0; i < 4; i++) {
            if (node->children[i]->rect.contains(keypoint.pt)) {
                node->children[i]->keypoints.push_back(keypoint);
                break;
            }
        }
    }

    // 递归建立子节点的四叉树
    for (int i = 0; i < 4; i++) {
        buildQuadTree(node->children[i], node->children[i]->keypoints, minPoints, maxLevel, level + 1);
    }
}

// 非极大值抑制
void nonMaximumSuppression(std::vector<cv::KeyPoint>& keypoints, float radius) {
    std::vector<cv::KeyPoint> nmsKeypoints;
    std::sort(keypoints.begin(), keypoints.end(), [](const cv::KeyPoint& a, const cv::KeyPoint& b) {
        return a.response > b.response;
    });

    std::vector<bool> mask(keypoints.size(), true);
    for (size_t i = 0; i < keypoints.size(); i++) {
        if (mask[i]) {
            nmsKeypoints.push_back(keypoints[i]);
            for (size_t j = i + 1; j < keypoints.size(); j++) {
                if (cv::norm(keypoints[i].pt - keypoints[j].pt) <= radius) {
                    mask[j] = false;
                }
            }
        }
    }

    keypoints = nmsKeypoints;
}

// 四叉树均匀化结合非极大值抑制
void quadTreeUniformNMS(std::vector<cv::KeyPoint>& keypoints, int minPoints, int maxLevel, float nmsRadius) {
    // 创建根节点
    QuadTreeNode* root = new QuadTreeNode(cv::Rect(0, 0, 1276, 378));
    root->keypoints = keypoints;

    // 建立四叉树
    buildQuadTree(root, keypoints, minPoints, maxLevel, 0);

    // 对每个叶子节点进行非极大值抑制
    std::vector<cv::KeyPoint> uniformKeypoints;
    std::function<void(QuadTreeNode*)> traverseQuadTree = [&](QuadTreeNode* node) {
        if (node->children[0] == nullptr) {
            nonMaximumSuppression(node->keypoints, nmsRadius);
            uniformKeypoints.insert(uniformKeypoints.end(), node->keypoints.begin(), node->keypoints.end());
        } else {
            for (int i = 0; i < 4; i++) {
                traverseQuadTree(node->children[i]);
            }
        }
    };
    traverseQuadTree(root);

    keypoints = uniformKeypoints;

    // 释放内存
    std::function<void(QuadTreeNode*)> deleteQuadTree = [&](QuadTreeNode* node) {
        if (node->children[0] != nullptr) {
            for (int i = 0; i < 4; i++) {
                deleteQuadTree(node->children[i]);
                delete node->children[i];
            }
        }
    };
    deleteQuadTree(root);
    delete root;
}

int main() {
    std::vector<cv::KeyPoint> vToDistributeKeys;
    // ... 初始化 vToDistributeKeys ...

    int minPoints = 1;  // 每个区域最少特征点数量
    int maxLevel = 5;  // 最大分割层数
    float nmsRadius = 10.0f;  // 非极大值抑制半径

    quadTreeUniformNMS(vToDistributeKeys, minPoints, maxLevel, nmsRadius);

    // ... 使用均匀化后的特征点 vToDistributeKeys ...

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/614785.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年电工杯数学建模A题思路 中国电机工程学会杯建模思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

【高校科研前沿】北师大陈晋教授团队在遥感顶刊发表最新成果:ClearSCD模型:在高空间分辨率遥感影像中综合利用语义和变化关系进行语义变化检测

01文章简介 论文名称&#xff1a;The ClearSCD model: Comprehensively leveraging semantics and change relationships for semantic change detection in high spatial resolution remote sensing imagery&#xff08;ClearSCD模型&#xff1a;在高空间分辨率遥感影像中综合…

在Spring Boot应用安装SSL证书

目录 前提条件 步骤一&#xff1a;下载SSL证书 步骤二&#xff1a;在Spring Boot安装SSL证书 步骤三&#xff1a;验证SSL证书是否安装成功 前提条件 已通过数字证书管理服务控制台签发证书SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射已在W…

[Markdown]是时候该学学使用markdown写文章了

&#x1f495;&#x1f495;&#x1f495;欢迎各位来到我的博客&#xff0c;今天我们的主题是markdown&#xff0c;你将在这里学习到最全的markdown知识&#x1f495;&#x1f495;&#x1f495; 你还在使用富文本编辑器写文档或文章吗&#xff1f; 你还在用word一点一点地进行…

网络匿名--不只是TOR

今天&#xff0c;我们将讨论互联网匿名和隐私&#xff1a; 如何隐藏你的真实身份。 什么是 TOR 。 如何以完全匿名的方式执行黑客任务。 如何使用proxy chain。 如何让我们的匿名性领先一步。 如何使用特定的操作系统保持匿名。 结论&#xff0c;如何实现互联网匿名和隐…

2024高校网络安全管理运维赛wp

文章目录 misc签到钓鱼邮件识别easyshellSecretDBGatewayzipApachef for r webphpsqlMessy Mongo misc 签到 钓鱼邮件识别 两部分解base64&#xff0c;各一个flag 后面没有什么地方有有用信息了&#xff0c;根据题目钓鱼邮件&#xff0c;可能第三段flag就跟DMARC、DKIM 和 SP…

ppt通过修改幻灯片母版修改页脚

修改幻灯片母版 幻灯片母版就可以了&#xff0c;就可以修改页脚

如何打破数据管理僵局,释放数据资产价值?[AMT企源案例]

引言 数据是企业信息运作的核心和基础&#xff0c;是影响企业决策的关键要素&#xff0c;而主数据是数据中的最基础和公共的部分。面临长期以来的数据治理缺失导致的杂论局面&#xff0c;如何有条不紊推进主数据管理&#xff0c;让数据资产“活”起来&#xff1f;S集团的做法非…

Linux线程(二)线程互斥

目录 一、为什么需要线程互斥 二、线程互斥的必要性 三、票务问题举例&#xff08;多个线程并发的操作共享变量引发问题&#xff09; 四、互斥锁的用法 1.互斥锁的原理 2、互斥锁的使用 1、初始化互斥锁 2、加锁和解锁 3、销毁互斥锁&#xff08;动态分配时需要&#…

PostgreSQL的学习心得和知识总结(一百四十三)|深入理解PostgreSQL数据库之Support event trigger for logoff

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

Stable Diffusion教程|图生图原理和实战

Stable Diffusion凭借其卓越的图生图功能&#xff0c;极大地提升了图像生成的可控性与输出品质&#xff0c;赋予用户前所未有的个性化创作风格表达能力。这一革新特性使得Stable Diffusion不仅能精准地捕捉用户的艺术愿景&#xff0c;更能以数字化手段孕育出新颖且极具创意的画…

论文 学习 Transformer : Attention Is All You Need

目录 概述&#xff1a; 对摘要的理解&#xff1a; 框架解析 按比例缩放的点积注意力 多头注意力机制 前馈神经网络与位置编码 概述&#xff1a; transformer 是一个encoder ——decoder 结构的用于处理序列到序列转换任务的框架&#xff0c;是第一个完全依赖自注意力机制…

写了 1000 条 Prompt 之后,我总结出了这 9 个框架【建议收藏】

如果你对于写 Prompt 有点无从下手&#xff0c;那么&#xff0c;本文将为你带来 9 个快速编写 Prompt 的框架&#xff0c;你可以根据自己的需求&#xff0c;选择任意一个框架&#xff0c;填入指定的内容&#xff0c;即可以得到一段高效的 Prompt&#xff0c;让 LLM 给你准确满意…

再谈毕业论文设计投机取巧之IVR自动语音服务系统设计(信息与通信工程A+其实不难)

目录 举个IVR例子格局打开&#xff0c;万物皆能IVR IVR系统其实可盐可甜。还能可圈可点。 戎马一生&#xff0c;归来依然IVR。 举个IVR例子 以下是IVR系统的一个例子。 当您拨打电话进入IVR系统。 首先检验是否为工作时间。 如是&#xff0c;您将被送入ivr-lang阶段&#xff0…

python3如何安装bs4

在python官网找到beautifulsoup模块的下载页面&#xff0c;点击"downloap"将该模块的安装包下载到本地。 将该安装包解压&#xff0c;然后在打开cmd&#xff0c;并通过cmd进入到该安装包解压后的文件夹目录下。 在该文件目录下输入"python install setup.py&quo…

程序人生 | 人生如棋,落子无悔

人生的开始&#xff0c;始于哭声&#xff0c;浮浮沉沉几十年。终了&#xff0c;一声长叹&#xff0c;在一片哭声中撒手离去。 人生的道路虽然漫长&#xff0c;但是关键就是那么几次机会的选择&#xff0c;可以决定此后几十年的光阴。 有个故事讲&#xff1a;古代有个人去砍柴…

搭建一个Xx431?

搭建一个Xx431? 嘿uu们!刚结束了一周六天班感觉如何? 我的状态倒还行,工作生活总能找到乐子,本周整活就是用纸巾和蛋糕托做的油灯,另外想制冷片做个温水冷水可调的杯托,但我还不会搞3d,希望今年能搞起来. 题外话就说到这,这个选题也是因为实际遇到的问题需要这玩意,下班路…

基于Matplotlib的模型性能可视化工作

一、项目简介 本项目是科技考古墓葬识别工作的中间过程&#xff0c;因为需要大量复用所以另起一章好了。 主要涉及到数据读取、数据可视化和少量的数据处理过程。 二、相关知识 PandasMatplotlib 三、实验过程 1. 数据探索性分析 1.1 准备工作–导入模块 import pandas…

【Python系列】Python中列表属性提取

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…