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

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

以上是关于GB28181系统设计-摄像头位置聚类快速搜索Kd-Tree算法的主要内容,如果未能解决你的问题,请参考以下文章

GoPro是不是支持GB/T28181协议

GB28181 AI视频数据库以及SDP协议

GB28181 AI视频数据库以及SDP协议

SRS4 对接海康威视GB28181协议推流 RTMP、webRTC拉流

gb28181 网守网关分离+推理服务架构

如何让Android平台像IPC一样实现GB28181前端设备接入