I have two set of points (cv::Point2f): setA and setB. For each point in setA, I want to find its nearest neighbor in setB. So, I have tried two methods:
Linear search: for each point in setA, just simply scan through all points in setB to find nearest one.
Using opencv kd-tree:
_ First I built a kd-tree for setB using opencv flann:
cv::flann::KDTreeIndexParams indexParams;
cv::flann::Index kdTree(cv::Mat(setB).reshape(1), indexParams);
_ Then, for each point in setA I do query to find nearest neighbor:
kdTree.knnSearch(point_in_setA, indices, dists, maxPoints);
Note: I set maxPoints to 1, cause I only need the nearest one.
I do a bit study, and come out with some time complexity for each case:
Linear search: O(M*N)
Kd-Tree: NlogN + MlogN => first term for building kd-tree, second term is for querying
Where M is number of points in setA, and N is for setB. And range of N: 100~1000, range of M: 10000~100000.
So, the kd-tree is supposed to run much faster than the linear search method. However, when I run the real test on my laptop, the result is kd-tree method is slower than linear search (0.02~0.03s vs 0.4~0.5s).
When I do profiling, I got hot spot at knnSearch() function, it takes 20.3% CPU time compares to 7.9% of linear search.
Uhm, I read some online articles, they said to query kd-tree it usually take logN. But I am not sure about how opencv implement it.
Anyone knows what's wrong here? Is there any parameter I should adjust in kd-tree or did I make mistake somewhere in the code or computation?
Taken from the Flann documentation. For low dimensional data, you should use KDTreeSingleIndexParams.
KDTreeSingleIndexParams
When passing an object of this type the index will contain a single kd-tree optimized for searching lower dimensionality data (for example 3D point clouds), in your case 2D points. You can play with the leaf_max_size parameters and profile your results.
struct KDTreeSingleIndexParams : public IndexParams
{
KDTreeSingleIndexParams( int leaf_max_size = 10 );
};
max leaf size: The maximum number of points to have in a leaf for not
branching the tree any more
O(log(N)) doesn't necessarily mean it is faster than O(N).
This is only true for sufficiently big N.
Your N is a rather small number. If your kd-tree contained millions of elements, you'd probably see the difference between a linear scan and a logarithmic search.
So my guess is that you spend a lot of time with overhead like building the tree, which is slower for small N than just scanning this rather small list without any overhead.
Related
I'm working on implementing a ModelClass for any 3D model in my DirectX 11/12 pipeline.
My specific problem lies within calculating the min and max for the BoundingBox structure I wish to use as a member of the ModelClass.
I have two approaches to calculating them.
Approach 1.
When each vertex is being read from file, store a current minx,y,z and maxx,y,z and check each vertex as it is loaded in against the current min/max x,y,z.
Approach 2.
After all the vertices have been loaded, sort them by x, then y, then z, finding the lowest and highest value at each point.
Which Approach would you recommend and why?
Approach 1
Time complexity is in O(n) and memory complexity is O(1).
It is simple to implement.
Approach 2
Time complexity is O(nLogn) memory complexity is potentially at least linear (if you make a copy of the arrays or if you use merge sort) or O(1) if you use an in place sorting algorithm like quicksort.
This has to be done 3 times one for each dimension.
All in all Approach 1 is best in all scenarios I can think of.
Sorting generally is not a cheap operation especially as your models are getting larger. Therefore it to me like Approach 1 is more efficient but if unsure I suggest measuring it see which one takes longer.
If you are using a library like Asspimp I believe the library takes care of bounding boxes but this might not be an option if you create the pipeline as a learning opportunity.
I noticed today that I could give a C++ Vector or Array a Float value as index.
(e.g. tab[0.5f])
This Float value will be converted into an Int value and then gives me the same result as tab[0].
This behavior is not interesting to me, as I'm searching for a method to access in the fastest way possible to an Object, depending on a Float key.
Is it possible to keep the access speed of an array/vector, with a Float index ?
I understand that my keys will have an inaccuracy problem, but I expect my Float values to keep a maximum of 3 digits of precision.
Would a Map<Float, Object> do the job ? I've read on the C++ reference documentation that the Map access was "logarithmic in size", which is way less appealing to me.
Thank you :).
Edit :
I need to transform a mesh M containing X numbers of shared vertices into a mesh M' containing X' number of NON shared vertices.
Indexes of vertices are set in M, and I know it's in TRIANGLE mode.
My current algorithm is :
for i in M.indexes, i+3
take 3indexes, and deducing the vertices they are pointing to (get 3vertices of a triangle)
calculate normal on these vertices
check, for each couple {Vertex_i, Normal} (i between 1 and 3, my 3vertices) if I already have this couple stored, and act accordingly
... Next steps
To check the couple {Vertex,Normal}, i use an Array[x][y][z] based on position of the vertice, which IS a Float, though i know it won't be more than 3digits precision.
Use an unordered_map. The find method has a complexity in average case: constant and in worst case: linear in container size.
Note : Since you were willing to use an array, I'm assuming you're not interested in having an ordered container
That been said, in any case, the performance depends on the input (mesh size) and its characteristics, and the only way to choose an optimal solution would be to implement any reasonable ones and benchmark against each other. In many cases theoretical complexity is irrelevant due to implementation specifics/intrinsics. I mean even if one told that a std::vector<std::pair<float, mapped_value>> would perform better in your case, I'd have to actually do some tests to prove him right/wrong
My program contains polygons which have the form of a vector containing points (2 dimensional double coordinates, stored in a self-made structure). I'm looking for a quick way of finding the smallest square containing my polygon (ie. knowing the maximal and minimal coordinates of all the points).
Is there a quicker way than just parsing all the points and storing the minimum and maximum values?
The algorithm ou are describing is straightforward: Iterate over all your points and find the minimum and maximum for each coordinate. This is an O(n) algorithm, n being the number of points you have.
You can't do better, since you will need to check at least all your points once, otherwise the last one could be outside the square you found.
Now, the complexity is at best O(n) so you just have to minimize the constant factors, but in that case it's already pretty small : Only one loop over your vector, looking for two maximums and two minimums.
You can either iterate through all points and find max and min values, or do some preprocessing, for example, store your points in treap (http://en.wikipedia.org/wiki/Treap).
There is no way w/o some preprocessing to do it better than just iterating over all points.
I'm not sure if there can be any faster way to find the min & max values in an array of values than linear time. The only 'optimization' I can think of is to find these values on one of the other occasions you're iterating the array (filling it/performing a function on all points), then perform checks on any data update.
I want to check whether an element is present in the given array(2D) and to find the count towards the left of a cell and to the right of a cell and also to the top and bottom.How can i do it without using brute force
If the array is sorted then you can find in O(nlogm) time complexity using binary search!
where n,m is the rows and columns.
In addition to the other answers (probably not very useful for any present applications, just an idea for thought) is Grover's algorithm. A exert from Wikipedia:
Grover's algorithm is a quantum algorithm for searching an unsorted
database with N entries in O(N1/2) time and using O(log N) storage
space (see big O notation). Lov Grover formulated it in 1996.
In models of classical computation, searching an unsorted database
cannot be done in less than linear time (so merely searching through
every item is optimal). Grover's algorithm illustrates that in the
quantum model searching can be done faster than this; in fact its time
complexity O(N1/2) is asymptotically the fastest possible for
searching an unsorted database in the linear quantum model.
If your matrix is unsorted, and you don't have anything like hash-tables for quick access, there is no way.
If your matrix is, for example, sorted, you can use more effective search algorithms (such as binary search, for example) to find the element faster. Don't forget that a 2D array can be represented with a vector, and a variable to hold the column count.
I'm given m places (x,y coordinates).
I have n requests of finding the closest place to a given point P(x,y); (The minimum Euclidian distance)
How can i solve this problem below O(n*m) where n is the number of requests and m the number of places? I could use squared Euclidian distances but it's still n*m.
Try a kd-tree. A high performance library implementation can be found here.
Note: I'm pointing you to an approximate nearest-neighbors search which is optimized for high dimensions. This may be slightly overkill for your application.
Edit:
For a 2d kd-tree, the build time would be O(m*log(m)) and the query time would be O(n*sqrt(m)). This should end up being a net win over the naive solution if your number of queries n, exceeds log(m).
The library means you don't have to implement it so the complexity shouldn't be an issue.
If you want to generalize to high dimension extremely fast querying, check out locality sensitive hashing.
Interesting. To reduce the effect of n, I wonder if perhaps it would help to save the result of each request as you encounter and handle it. A clever result table might shortcut the need to calculate sqrt( x2 + y2) in solving subsequent requests.
The Nearest-Neighbor-Problem, eh? I found Robert Sedgewick Std Book very useful in these cases. He describes Nearest Neighbour Search, too.