mirror of https://github.com/open-mmlab/mmocr.git
[Bug fix] box points ordering (#1205)
* fix sort_points * remove functools * add test cases * add descriptions for coordinates * del Co-authored-by: xinyu <wangxinyu2017@gmail.com>pull/1463/head
parent
a71889aeb4
commit
8905daea5b
|
@ -1,5 +1,7 @@
|
|||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import functools
|
||||
import math
|
||||
import operator
|
||||
from functools import reduce
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
@ -160,8 +162,14 @@ def bezier_to_polygon(bezier_points, num_sample=20):
|
|||
|
||||
|
||||
def sort_points(points):
|
||||
"""Sort arbitory points in clockwise order. Reference:
|
||||
https://stackoverflow.com/a/6989383.
|
||||
"""Sort arbitrary points in clockwise order in Cartesian coordinate, you
|
||||
may need to reverse the output sequence if you are using OpenCV's image
|
||||
coordinate.
|
||||
|
||||
Reference:
|
||||
https://github.com/novioleo/Savior/blob/master/Utils/GeometryUtils.py.
|
||||
|
||||
Warning: This function can only sort convex polygons.
|
||||
|
||||
Args:
|
||||
points (list[ndarray] or ndarray or list[list]): A list of unsorted
|
||||
|
@ -170,30 +178,13 @@ def sort_points(points):
|
|||
Returns:
|
||||
list[ndarray]: A list of points sorted in clockwise order.
|
||||
"""
|
||||
|
||||
assert is_type_list(points, np.ndarray) or isinstance(points, np.ndarray) \
|
||||
or is_2dlist(points)
|
||||
|
||||
points = np.array(points)
|
||||
center = np.mean(points, axis=0)
|
||||
|
||||
def cmp(a, b):
|
||||
oa = a - center
|
||||
ob = b - center
|
||||
|
||||
# Some corner cases
|
||||
if oa[0] >= 0 and ob[0] < 0:
|
||||
return 1
|
||||
if oa[0] < 0 and ob[0] >= 0:
|
||||
return -1
|
||||
|
||||
prod = np.cross(oa, ob)
|
||||
if prod > 0:
|
||||
return 1
|
||||
if prod < 0:
|
||||
return -1
|
||||
|
||||
# a, b are on the same line from the center
|
||||
return 1 if (oa**2).sum() < (ob**2).sum() else -1
|
||||
|
||||
return sorted(points, key=functools.cmp_to_key(cmp))
|
||||
center_point = tuple(
|
||||
map(operator.truediv,
|
||||
reduce(lambda x, y: map(operator.add, x, y), points),
|
||||
[len(points)] * 2))
|
||||
return sorted(
|
||||
points,
|
||||
key=lambda coord: (180 + math.degrees(
|
||||
math.atan2(*tuple(map(operator.sub, coord, center_point))))) % 360)
|
||||
|
|
|
@ -124,5 +124,27 @@ def test_sort_points():
|
|||
points = [[1, 1], [1, -1], [-1, 1], [-1, -1]]
|
||||
assert np.allclose(target, sort_points(points))
|
||||
|
||||
points = [[0.5, 0.3], [1, 0.5], [-0.5, 0.8], [-0.1, 1]]
|
||||
target = [[-0.5, 0.8], [-0.1, 1], [1, 0.5], [0.5, 0.3]]
|
||||
assert np.allclose(target, sort_points(points))
|
||||
|
||||
points = [[0.5, 3], [0.1, -0.2], [-0.5, -0.3], [-0.7, 3.1]]
|
||||
target = [[-0.5, -0.3], [-0.7, 3.1], [0.5, 3], [0.1, -0.2]]
|
||||
assert np.allclose(target, sort_points(points))
|
||||
|
||||
points = [[1, 0.8], [0.8, -1], [1.8, 0.5], [1.9, -0.6], [-0.5, 2],
|
||||
[-1, 1.8], [-2, 0.7], [-1.6, -0.2], [-1, -0.5]]
|
||||
target = [[-1, -0.5], [-1.6, -0.2], [-2, 0.7], [-1, 1.8], [-0.5, 2],
|
||||
[1, 0.8], [1.8, 0.5], [1.9, -0.6], [0.8, -1]]
|
||||
assert np.allclose(target, sort_points(points))
|
||||
|
||||
# concave polygon may failed
|
||||
points = [[1, 0], [-1, 0], [0, 0], [0, -1], [0.25, 1], [0.75, 1],
|
||||
[-0.25, 1], [-0.75, 1]]
|
||||
target = [[-1, 0], [-0.75, 1], [-0.25, 1], [0, 0], [0.25, 1], [0.75, 1],
|
||||
[1, 0], [0, -1]]
|
||||
with pytest.raises(AssertionError):
|
||||
assert np.allclose(target, sort_points(points))
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
sort_points([1, 2])
|
||||
|
|
Loading…
Reference in New Issue