我最近使用了OpenCV的函数minEnclosingCircle(2.4.2),因为我需要测量一个点的直径。
过了一会儿,我意识到结果不正确,所以我决定编写一个小程序来计算一小组点的直径。
我测试了这个功能:
在下表中,您可以看到我的测试结果:
Note Diameter Center Points
1x1 2.000 (1.0, 1.0) [[1, 1]]
2x1 2.000 (1.0, 1.5) [[1, 1], [1, 2]]
3x1 2.060 (1.0, 2.0) [[1, 1], [1, 2], [1, 3]]
4x1 3.090 (1.0, 2.5) [[1, 1], [1, 2], [1, 3], [1, 4]]
2x2 2.000 (1.5, 1.5) [[1, 1], [1, 2], [2, 1], [2, 2]]
3x3 2.913 (2.0, 2.0) [[1, 1], [1, 3], [3, 1], [3, 3]]
4x4 4.370 (2.5, 2.5) [[1, 1], [1, 4], [4, 1], [4, 4]]
6x6 7.283 (3.5, 3.5) [[1, 1], [1, 6], [6, 1], [6, 6]]
8x8 10.196 (4.5, 4.5) [[1, 1], [1, 8], [8, 1], [8, 8]]
9x9 11.653 (5.0, 5.0) [[1, 1], [1, 9], [9, 1], [9, 9]]
16x16 21.850 (8.5, 8.5) [[1, 1], [1, 16], [16, 1], [16, 16]]
10x10 13.110 (5.5, 5.5) [[1, 1], [1, 10], [10, 1], [10, 10]]
100x100 144.207 (50.5, 50.5) [[1, 1], [1, 100], [100, 1], [100, 100]]
1000x1000 1455.183 (500.5, 500.5) [[1, 1], [1, 1000], [1000, 1], [1000, 1000]]
我已经看到该函数没有返回小于1的半径,所以我得到的最小直径是2.0。
除此之外,该函数总是返回比我预期的更大的半径。 例如,10x10平方的半径约为12.726而不是13.110。 误差随着方块的大小而增加:对于1000x1000的平方,我期望1412.5而不是1455.
实际上,我意识到相对误差总是大约3%。
我该如何解释这种奇怪的行为?
答案 0 :(得分:2)
我相信,子功能icvFindEnslosingCicle4pts_32f
中有一个因子1.03错误 - 它与半径相乘但从未再次划分。我在http://code.opencv.org/issues/3362
答案 1 :(得分:1)
我尝试使用另一个名为Miniball的库来解决同样的问题。
使用Miniball获得的结果是正确的。此时我猜minEnclosingCircle
中使用的算法包含一些错误。
答案 2 :(得分:1)
为了完整起见,有几种算法实现可以解决最小的封闭球问题。
对于2D和3D,Gärtner's implementation,在这个问题的另一个答案中也提到,可能是最快的。
对于更高的尺寸(比如说高达10,000),请查看https://github.com/hbf/miniball,这是Gärtner,Kutz和Fischer的算法实现(注意:我是其中一个-authors)。
对于非常非常高的维度,核心集(近似)算法会更快。
注意:如果您正在寻找计算球体的最小封闭球的算法,您将在Computational Geometry Algorithms Library (CGAL)中找到C ++实现。 (您不需要使用所有CGAL;只需提取所需的头文件和源文件。)