diff --git a/mmocr/utils/bbox_utils.py b/mmocr/utils/bbox_utils.py
index 19b28f62..3b8b8631 100644
--- a/mmocr/utils/bbox_utils.py
+++ b/mmocr/utils/bbox_utils.py
@@ -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.
diff --git a/mmocr/utils/polygon_utils.py b/mmocr/utils/polygon_utils.py
index 7c6b857f..77b552e9 100644
--- a/mmocr/utils/polygon_utils.py
+++ b/mmocr/utils/polygon_utils.py
@@ -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):
diff --git a/tests/test_utils/test_polygon_utils.py b/tests/test_utils/test_polygon_utils.py
index 94b77d2d..8cbd4f89 100644
--- a/tests/test_utils/test_polygon_utils.py
+++ b/tests/test_utils/test_polygon_utils.py
@@ -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])