如何有效地在列表中找到邻居点?

问题描述

我在图像中有很多点,我想找到最接近给定点的点。

尝试过的现有方法 将图像划分为图块,并仅通过构建表格在感兴趣区域内搜索。淡蓝色的是我正在比较的要点。

enter image description here

问题 即使进行的比较很少,我的算法所花费的时间也比实际时间多。我目前的方法是否还有改进的余地?还有其他更好的方法吗?

我的机器上的运行时间: 花费的时间

FindNearestPoint  : 0.021145 ms  
FindNearestPointV2: 0.047953 ms

PC配置: Intel(R)Core(TM)i7-6820HQ cpu @ 2.70 GHZ

// Feature Comparision.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
//
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "Timer.h" //http://www.songho.ca/misc/timer/files/timer.zip

#include "opencv2\opencv.hpp"
#include "opencv2\opencv_modules.hpp"

using namespace cv;
using namespace std;

bool FindNearestPoint(const Point2f Point,const vector<Point2f>vPoints,int &Index )
{
    CV_Assert(vPoints.size() != 0);

    float Prevdistance = FLT_MAX;
    Index = -1;//Error Case
    for (size_t i = 0; i < vPoints.size(); i++)
    {
        float distance = cv::norm(Point - Point2f(vPoints[i].x,vPoints[i].y));

        if (distance < Prevdistance)
        {
            Index = i;
            Prevdistance = distance;
        }
    }
    return true;

}

static inline bool GetlistofClustersToProcess(const Point2f Pt,const Point2f szTileSize,const Size GridSize,vector<Point> &ClusterIndices)
{
    Point Index(Pt.x* szTileSize.x,Pt.y * szTileSize.y);
    vector<Point> vClusterIndices;

    //Prev Tile
    vClusterIndices.push_back(Index + Point(-1,-1));//Prev Tile
    vClusterIndices.push_back(Index + Point(-1,0)); //Curr Tile
    vClusterIndices.push_back(Index + Point(-1,1)); //Next Tile

    vClusterIndices.push_back(Index + Point(0,-1)); //Prev Tile
    vClusterIndices.push_back(Index + Point(0,0)); //Curr Tile
    vClusterIndices.push_back(Index + Point(0,1)); //Next Tile

    vClusterIndices.push_back(Index + Point(1,-1)); //Prev Tile
    vClusterIndices.push_back(Index + Point(1,0));     //Curr Tile
    vClusterIndices.push_back(Index + Point(1,1));     //Next Tile

    for (size_t i = 0; i < vClusterIndices.size(); i++)
    {
        Index = vClusterIndices[i];
        if ((Index.x < 0) || (Index.x >= GridSize.width) || (Index.y < 0) || (Index.y >= GridSize.height))
        {
            continue;
        }
        ClusterIndices.push_back(Index);
    }

    return true;
}

bool FindNearestPointV2(const Point2f Point,const vector<vector<vector<int>>>vClusters,int &Index,Mat &mDebugImage)
{
    #define EnableDebug 0

    CV_Assert(vPoints.size() != 0);

    vector<cv::Point> ClusterIndices;
    ClusterIndices.clear();

    GetlistofClustersToProcess(Point,szTileSize,GridSize,ClusterIndices);

    float Prevdistance = FLT_MAX;

    Index = -1;//Error Case
    int KeypointIdx = 0;

    for (size_t iClusterIdx = 0; iClusterIdx < ClusterIndices.size(); iClusterIdx++)
    {
        cv::Point Cluster(ClusterIndices[iClusterIdx]);

        CV_Assert((Cluster.x >= 0)&&(Cluster.x < GridSize.width));
        CV_Assert((Cluster.y >= 0) && (Cluster.y < GridSize.height));

        for (size_t i = 0; i < vClusters[Cluster.y][Cluster.x].size(); i++)
        {
            KeypointIdx = vClusters[Cluster.y][Cluster.x][i];

            CV_Assert(KeypointIdx < vPoints.size());

            float distance = cv::norm(Point - Point2f(vPoints[KeypointIdx].x,vPoints[KeypointIdx].y));

#if EnableDebug
            circle(mDebugImage,vPoints[KeypointIdx],2,Scalar(255,255,0),2);

            imshow("Input Features",mDebugImage);
#endif
            //New Optimized Implementation
            //waitKey();

            if (distance < Prevdistance)
            {
                Index = KeypointIdx;
                Prevdistance = distance;
            }
        }
    }
    return true;

}

int main(int argc,char* argv[])
{
    /*TestKNN();
    return 0;*/

    Size ImageSize(900,300);
    Mat mInputimage(ImageSize,CV_8UC3,Scalar::all(0));
    RNG rng(0xFFFFFFFF);
    vector<Point2f>vKeypoints;
    int MaxNoOfKeypoints = 2000;
    uint16_t maxFilteredKeypoints = 350;
    int TileSize = 32;//Tile Size in Pixels
    Size GridSize((ImageSize.width / TileSize)+1,(ImageSize.height / TileSize)+1);
    vector<vector<vector<int>>>vClusters;
    Point ptTileIdx(0,0);
    Point2f PtQuery,PtNearestPoint,PtNearestPointV2;
    Point2f GridScale((float)GridSize.width / (float)ImageSize.width,(float)GridSize.height / (float)ImageSize.height);
    int NoOfTestPoints = 100,Iteration = 0;

    for (;;)
    {
        vKeypoints.clear();
        vClusters.clear();
        mInputimage.setTo(0);
        //Generating Random Keypoints
        for (size_t i = 0; i < MaxNoOfKeypoints; i++)
        {
            vKeypoints.push_back(Point2f(rng.uniform(0,ImageSize.width),rng.uniform(0,ImageSize.height)));
        }

        cout << "Grid Size :" << GridSize << "\n";
        for (size_t iVerTile = 0; iVerTile < GridSize.height; iVerTile++)
        {
            vector<vector<int>>HorTiles;
            Scalar color = Scalar(rng.uniform(0,255),255));
            for (size_t iHorTile = 0; iHorTile < GridSize.width; iHorTile++)
            {
                Rect TileRect(iHorTile*TileSize,iVerTile*TileSize,TileSize,TileSize);
                rectangle(mInputimage,TileRect,color,1);
                color += Scalar(0,10);
                HorTiles.push_back(vector<int>());
            }
            vClusters.push_back(HorTiles);
        }
        printf("Cluster Size : %d,%d \n",vClusters.size(),vClusters[0].size());
        
        //Classify Tile Idx for all the Keypoints
        for (size_t i = 0; i < MaxNoOfKeypoints; i++)
        {
            ptTileIdx.x = (int)(vKeypoints[i].x / TileSize);
            ptTileIdx.y = (int)(vKeypoints[i].y / TileSize);
            vClusters[ptTileIdx.y][ptTileIdx.x].push_back(i);
        }

        //displaying the Keypoints
        for (size_t i = 0; i < MaxNoOfKeypoints; i++)
        {
            circle(mInputimage,vKeypoints[i],2);
        }
        Mat mInputTestimage = mInputimage.clone();
        Iteration = 0;
        while (Iteration<NoOfTestPoints)
        {
            PtQuery = Point2f(rng.uniform(0,ImageSize.height));

            circle(mInputTestimage,PtQuery,4,Scalar(0,4);
            circle(mInputTestimage,2);
            
            int NearestPointIndex = -1,NearestPointIndexV2 = -1;
            Timer t_FindNearestPt;
            t_FindNearestPt.start();

            FindNearestPoint(PtQuery,vKeypoints,NearestPointIndex);

            t_FindNearestPt.stop();

            PtNearestPoint = vKeypoints[NearestPointIndex];

            Timer t_FindNearestPtV2;
            t_FindNearestPtV2.start();
            //New Optimized Implementation
            FindNearestPointV2(PtQuery,vClusters,GridScale,NearestPointIndexV2,mInputTestimage);

            t_FindNearestPtV2.stop();

            PtNearestPointV2 = vKeypoints[NearestPointIndexV2];

            if (NearestPointIndexV2 != -1)
            {
                circle(mInputTestimage,PtNearestPointV2,2);
            }
            if (NearestPointIndex != -1)
            {
                circle(mInputTestimage,2);
            }

            if (NearestPointIndex != NearestPointIndexV2)
            {
                printf("[Error] Closest Point not Matching! \n");
                cout << "Point" << PtQuery <<  " Org" << PtNearestPoint << "!= V2 " << PtNearestPointV2 << "\n";
                float distance = cv::norm(PtQuery - PtNearestPoint);
                float distanceV2 = cv::norm(PtQuery - PtNearestPointV2);
                printf("distance : %f - %f  \n",distance,distanceV2);
            }
            /*else
            {
                printf("[Passed] Closest Point Matching! \n");
            }*/
            float TiMetaken_C = t_FindNearestPt.getelapsedtimeInMilliSec();
            printf("Time Taken for FindNearestPoint  : %f ms\t",TiMetaken_C);
            printf("FindNearestPointV2: %f ms\t",t_FindNearestPtV2.getelapsedtimeInMilliSec());
            printf("Speed: %f x\n",TiMetaken_C/t_FindNearestPtV2.getelapsedtimeInMilliSec());

            imshow("Input Features",mInputTestimage);
            Iteration++;
            char key = (char)waitKey();
            if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
                break;
            mInputTestimage= mInputimage.clone();
        }
    
        char key = (char)waitKey();
        if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
            break;
    }


    return 0;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)