照片拼接web应用程序。 KD树

时间:2012-12-18 10:57:13

标签: php language-agnostic kdtree

上个月我一直在制作一个照片马赛克网站。我用PHP构建了所有东西,我让它运行得很好。我唯一不喜欢的是执行时间。由于线性比较搜索,我认为这太长了。所以我一直在询问如何改善我的搜索时间,大多数人都指出了KD树的方向,这将使k最近邻居更快。

所以我一直在寻找KD树,我理解如何手动构建这样一棵树。现在我想编写这个代码,我只能找到C ++和java的库。因为我只熟悉PHP,所以我一直试图自己制作,但这并不像我想象的那么容易。

•我面临的一个问题是如何存储所有东西。当我得到第一个包含所有点的数组时,我会把它吐成3个。左分支,节点和右分支。当然我会对左分支做同样的事情,直到我不能分裂为止,当然我循环通过轴(XYZ)。但是如何将所有权利分支存储在一个数组中?或者,当我准备使用它们时,我会再次计算它们吗?

•我想知道的另一件事是为什么没有PHP KD树脚本,因为PHP不是这项工作的正确语言?

这是我到目前为止所得到的。

此函数计算随机颜色(RGB),我用它来测试其余颜色。

<?php
function randomiser($number){

    if($number <= 0){ 
        echo 'Error: The input of randomiser() is less than or equal to zero !!';
        return FALSE;         
    }else{ 
        $R = array();
        $G = array();
        $B = array();

        for($x = 1; $x <= $number; $x++){
            $r = rand(1, 255);
            $g = rand(1, 255);
            $b = rand(1, 255);

            $rgb['pic ' . $x]['R'] = $r;
            $rgb['pic ' . $x]['G'] = $g;
            $rgb['pic ' . $x]['B'] = $b;    
        }  
    }
return $rgb;
}
?>

此函数对特定键(默认为R)

上的多维数组进行排序
<?php
function sorter(&$array, $key = 'R'){

    if(!is_array($array)){ 
        echo 'Error: The input of sorter() is not an array !!<br>';
        return FALSE;         
    }else{ 
        uasort($array, function ($a, $b) use ($key){
            return strnatcmp($a[$key], $b[$key]);
        }); 
    }
}
?>

此类将数组拆分为左分支,节点和右分支。

<?php
class splitting {

    public $left;
    public $node;
    public $right;

    function __construct($array){

        if(!is_array($array)){ 
            echo 'Error: The input of splitter() is not an array !!<br>';
            return FALSE;         
        }else{ 
            $number = count($array);
            $median = round($number / 2) - 1; 

            $this->left = array_slice($array, 0, $median);
            $this->node = array_slice($array, $median, 1);
            $this->right = array_slice($array, $median+1);
        }
    }
}
?>

1 个答案:

答案 0 :(得分:0)

  1. 您需要在$ left和$ right变量中存储指向树的指针,而不是数组或您需要使用的任何变量。如果kd树太复杂,我也会看一个r树。 r树将平面分成4个边缘,即真正的2个euklidian维度,kd树只是二叉树。 然后你需要一个变量$ payload或者东西来备份中位数。
  2. 没有。你也可以找到php树的例子。这是一个例子:http://blog.sandfox.co.uk/2012/09/10/php-kdtree/。你也可以在php中查找我的kart-trie实现。它还使用OO和node和edge类。这是一个将光照贴图从http://www.blackpawn.com/texts/lightmaps/default.html打包到kd树中的脚本。

     struct Node
    {
         Node* child[2]
         Rectangle rc
          int imageID
     }
    
    Node* Node::Insert(const Image& img)
          if we're not a leaf then
          (try inserting into first child)
           newNode = child[0]->Insert( img )
          if newNode != NULL return newNode
    
     (no room, insert into second)
          return child[1]->Insert( img )
      else
    (if there's already a lightmap here, return)
    if imageID != NULL return NULL
    
    (if we're too small, return)
    if img doesn't fit in pnode->rect
        return NULL
    
    (if we're just right, accept)
    if img fits perfectly in pnode->rect
        return pnode
    
    (otherwise, gotta split this node and create some kids)
    pnode->child[0] = new Node
    pnode->child[1] = new Node
    
    (decide which way to split)
    dw = rc.width - img.width
    dh = rc.height - img.height
    
    if dw > dh then
        child[0]->rect = Rectangle(rc.left, rc.top, 
                                   rc.left+width-1, rc.bottom)
        child[1]->rect = Rectangle(rc.left+width, rc.top, 
                                   rc.right, rc.bottom)
    else
        child[0]->rect = Rectangle(rc.left, rc.top, 
                                   rc.right, rc.top+height-1)
        child[1]->rect = Rectangle(rc.left, rc.top+height, 
                                   rc.right, rc.bottom)
    
    (insert into first child we created)
    return Insert( img, pnode->child[0] )