* [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>

* fix

---------

Co-authored-by: liferecords <yjmm10@yeah.net>
Co-authored-by: xinyu <wangxinyu2017@gmail.com>
pull/1781/head
Tong Gao 2023-03-10 14:51:40 +08:00 committed by GitHub
parent 75c06d34bb
commit e9b23c56ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 71 deletions

View File

@ -1,11 +1,10 @@
# Copyright (c) OpenMMLab. All rights reserved.
import functools
from typing import List, Tuple
import numpy as np
from shapely.geometry import LineString, Point
from mmocr.utils.check_argument import is_2dlist, is_type_list
from mmocr.utils.check_argument import is_type_list
from mmocr.utils.point_utils import point_distance, points_center
from mmocr.utils.typing_utils import ArrayLike
@ -248,47 +247,6 @@ def bezier2polygon(bezier_points: np.ndarray,
return points.tolist()
def sort_points(points):
# TODO Add typehints & test & docstring
"""Sort arbitory points in clockwise order. Reference:
https://stackoverflow.com/a/6989383.
Args:
points (list[ndarray] or ndarray or list[list]): A list of unsorted
boundary 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))
def sort_vertex(points_x, points_y):
# TODO Add typehints & docstring & test
"""Sort box vertices in clockwise order from left-top first.

View File

@ -1,5 +1,7 @@
# Copyright (c) OpenMMLab. All rights reserved.
import functools
import math
import operator
from functools import reduce
from typing import List, Optional, Sequence, Tuple, Union
import numpy as np
@ -374,8 +376,14 @@ def boundary_iou(src: List,
def sort_points(points):
# TODO Add typehints & test & docstring
"""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
@ -384,33 +392,16 @@ def sort_points(points):
Returns:
list[ndarray]: A list of points sorted in clockwise order.
"""
assert is_list_of(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)
def sort_vertex(points_x, points_y):

View File

@ -343,6 +343,27 @@ class TestPolygonUtils(unittest.TestCase):
points = [[1, 1], [1, -1], [-1, 1], [-1, -1]]
self.assertTrue(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]]
self.assertTrue(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]]
self.assertTrue(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]]
self.assertTrue(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]]
self.assertFalse(np.allclose(target, sort_points(points)))
with self.assertRaises(AssertionError):
sort_points([1, 2])