GB28181系统设计-摄像头位置聚类快速搜索Kd-Tree算法(二)

GB28181系统设计之-事件系统

GB28181事件

    在上一篇里面讲了事件分享,此事件系统需要和数据库订阅和发布一起做,所以我们的数据库系统还没有讲结束,这一章将会分享摄像头聚类的快速搜索,使用kdtree数据结构和算法。为什么需要该算法?在事件系统中,一旦发现我们所搜索的目标,我们就需要在临近的摄像头继续搜索该目标,并且不断递归到我们所要的边缘。
制作自己的订阅和发布系统可以查找我写的如何做一个国产数据库文章。

kdtree

    kdtree是一个多维度的树形结构,在摄像头的世界中,维度为3,就是地理位置。在此次应用中,使用附近地点搜索,也就是搜索事件系统发生后摄像头附近有哪些可以搜索的摄像头,从而标定一次目标摄像头后,立刻打开聚类摄像头的文件可以搜索目标。随着GPS和带有GPS功能的移动设备的普及,附近地点搜索也变得方便了。在比较庞大的地理数据库中搜索地点,索引非常重要的,kdtree算法用来插入静态的摄像头地址,再合适不过了!

数据结构

说明:其中dim为维度

   struct kdtree {
        int dim;
        struct kdnode* root;
        struct kdhyperrect* rect;
        void (*destr)(void*);
    };

    struct kdres {
        struct kdtree* tree;
        struct res_node* rlist, * riter;
        int size;
    };

  struct kdhyperrect {
        int dim;
        double* min, * max;              /* minimum/maximum coords */
    };

    struct kdnode {
        double* pos;
        int dir;
        void* data;

        struct kdnode* left, * right;    /* negative/positive side */
    };

搜索函数

实际上,kdtree依然是一颗二叉树,所以要找到临近的点,按照摄像头的三维地址,我们其实只要计算欧拉距离就行了,而最重要的,为了避免搜索所有的摄像头,我们一定要指定一个范围,->range,以下为两个重要函数,希望给您带来启发。

struct kdres* kd_nearest(struct kdtree* kd, const double* pos)
{
    struct kdhyperrect* rect;
    struct kdnode* result;
    struct kdres* rset;
    double dist_sq;
    int i;

    if (!kd) return 0;
    if (!kd->rect) return 0;

    /* Allocate result set */
    if (!(rset = new kdres)) {
        return 0;
    }
    if (!(rset->rlist = new res_node)) {
        delete rset;
        return 0;
    }
    rset->rlist->next = 0;
    rset->tree = kd;

    /* Duplicate the bounding hyperrectangle, we will work on the copy */
    if (!(rect = hyperrect_duplicate(kd->rect))) {
        kd_res_free(rset);
        return 0;
    }

    /* Our first guesstimate is the root node */
    result = kd->root;
    dist_sq = 0;
    for (i = 0; i < kd->dim; i++)
        dist_sq += SQ(result->pos[i] - pos[i]);

    /* Search for the nearest neighbour recursively */
    kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);

    /* Free the copy of the hyperrect */
    hyperrect_free(rect);

    /* Store the result */
    if (result) {
        if (rlist_insert(rset->rlist, result, -1.0) == -1) {
            kd_res_free(rset);
            return 0;
        }
        rset->size = 1;
        kd_res_rewind(rset);
        return rset;
    }
    else {
        kd_res_free(rset);
        return 0;
    }
}

struct kdres* kd_nearest_range(struct kdtree* kd, const double* pos, double range)
{
    int ret;
    struct kdres* rset;

    if (!(rset = new kdres)) {
        return 0;
    }
    if (!(rset->rlist = new res_node)) {
        delete rset;
        return 0;
    }
    rset->rlist->next = 0;
    rset->tree = kd;

    if ((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {
        kd_res_free(rset);
        return 0;
    }
    rset->size = ret;
    kd_res_rewind(rset);
    return rset;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qianbo_insist

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

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

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

打赏作者

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

抵扣说明:

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

余额充值