We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Shrink map generation at training for DB is wrong for some polygon
Hi. Thanks for the great works.

After trying the DB training code, I've found out that the current shrink map generation at training for DB is wrong for some polygon.

For example, this polygon:
```
[[370, 111], [360, 111], [354, 113], [337, 113], [336, 109], [281, 109], [278, 111], [269, 111], [260, 108], [243, 108], [241, 108], [181, 108], [177, 111], [169, 111], [162, 112], [145, 112], [144, 108], [84, 108], [83, 108], [9, 108], [9, 117], [83, 117], [84, 117], [144, 117], [145, 119], [162, 119], [169, 117], [177, 117], [181, 118], [241, 118], [243, 114], [260, 114], [269, 118], [278, 118], [281, 118], [336, 118], [337, 119], [354, 119], [360, 118], [370, 118]]
```
![lol2](https://user-images.githubusercontent.com/26834698/108241717-b582d380-717e-11eb-9d7a-d6bf3fc0cf55.png)

Will result in this mask after shrinking
![lol](https://user-images.githubusercontent.com/26834698/108241733-bb78b480-717e-11eb-9bfd-da67fc275607.png)

Why? We can take a look at this block of code

https://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L47-L60

Since vatti clipping algorithm invoked by pyclipper can return multiple polygon (5 in this case, with the default shrink ratio 0.4) like this:
```
[[[240, 112], [239, 115], [181, 115], [177, 114], [179, 114], [183, 111], [243, 111]], [[367, 115], [360, 115], [356, 116], [361, 114], [367, 114]], [[334, 114], [334, 115], [270, 115], [268, 114], [280, 114], [283, 112], [333, 112]], [[142, 113], [142, 114], [12, 114], [12, 111], [141, 111]], [[147, 116], [147, 115], [162, 115], [169, 114], [162, 116]]]
```
![lol](https://user-images.githubusercontent.com/26834698/108242184-3510a280-717f-11eb-8cc9-90e14e1f351b.png)

But the current implementation only uses the first polygon and assumes there is only one polygon, leading to the wrong shrink map. 
https://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L59

This will greatly affect the accuracy of the trained model. Ideally, we would want a shrink map of a text region to not be spliced up like above but rather a shrink map like this (not using the original polygon of course, if it can):

![lol](https://user-images.githubusercontent.com/26834698/108242699-cbdd5f00-717f-11eb-8f05-4d81f53ae649.png)

I already sent a PR to fix this issue (#2014).
Shrink map generation at training for DB is wrong for some polygon
Hi. Thanks for the great works.

After trying the DB training code, I've found out that the current shrink map generation at training for DB is wrong for some polygon.

For example, this polygon:
```
[[370, 111], [360, 111], [354, 113], [337, 113], [336, 109], [281, 109], [278, 111], [269, 111], [260, 108], [243, 108], [241, 108], [181, 108], [177, 111], [169, 111], [162, 112], [145, 112], [144, 108], [84, 108], [83, 108], [9, 108], [9, 117], [83, 117], [84, 117], [144, 117], [145, 119], [162, 119], [169, 117], [177, 117], [181, 118], [241, 118], [243, 114], [260, 114], [269, 118], [278, 118], [281, 118], [336, 118], [337, 119], [354, 119], [360, 118], [370, 118]]
```
![lol2](https://user-images.githubusercontent.com/26834698/108241717-b582d380-717e-11eb-9d7a-d6bf3fc0cf55.png)

Will result in this mask after shrinking
![lol](https://user-images.githubusercontent.com/26834698/108241733-bb78b480-717e-11eb-9bfd-da67fc275607.png)

Why? We can take a look at this block of code

https://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L47-L60

Since vatti clipping algorithm invoked by pyclipper can return multiple polygon (5 in this case, with the default shrink ratio 0.4) like this:
```
[[[240, 112], [239, 115], [181, 115], [177, 114], [179, 114], [183, 111], [243, 111]], [[367, 115], [360, 115], [356, 116], [361, 114], [367, 114]], [[334, 114], [334, 115], [270, 115], [268, 114], [280, 114], [283, 112], [333, 112]], [[142, 113], [142, 114], [12, 114], [12, 111], [141, 111]], [[147, 116], [147, 115], [162, 115], [169, 114], [162, 116]]]
```
![lol](https://user-images.githubusercontent.com/26834698/108242184-3510a280-717f-11eb-8cc9-90e14e1f351b.png)

But the current implementation only uses the first polygon and assumes there is only one polygon, leading to the wrong shrink map. 
https://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L59

This will greatly affect the accuracy of the trained model. Ideally, we would want a shrink map of a text region to not be spliced up like above but rather a shrink map like this (not using the original polygon of course, if it can):

![lol](https://user-images.githubusercontent.com/26834698/108242699-cbdd5f00-717f-11eb-8f05-4d81f53ae649.png)

I already sent a PR to fix this issue (#2014).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ppocr/data/imaug/make_shrink_map.py`
Content:
```
1 # -*- coding:utf-8 -*- 
2 
3 from __future__ import absolute_import
4 from __future__ import division
5 from __future__ import print_function
6 from __future__ import unicode_literals
7 
8 import numpy as np
9 import cv2
10 from shapely.geometry import Polygon
11 import pyclipper
12 
13 __all__ = ['MakeShrinkMap']
14 
15 
16 class MakeShrinkMap(object):
17     r'''
18     Making binary mask from detection data with ICDAR format.
19     Typically following the process of class `MakeICDARData`.
20     '''
21 
22     def __init__(self, min_text_size=8, shrink_ratio=0.4, **kwargs):
23         self.min_text_size = min_text_size
24         self.shrink_ratio = shrink_ratio
25 
26     def __call__(self, data):
27         image = data['image']
28         text_polys = data['polys']
29         ignore_tags = data['ignore_tags']
30 
31         h, w = image.shape[:2]
32         text_polys, ignore_tags = self.validate_polygons(text_polys,
33                                                          ignore_tags, h, w)
34         gt = np.zeros((h, w), dtype=np.float32)
35         # gt = np.zeros((1, h, w), dtype=np.float32)
36         mask = np.ones((h, w), dtype=np.float32)
37         for i in range(len(text_polys)):
38             polygon = text_polys[i]
39             height = max(polygon[:, 1]) - min(polygon[:, 1])
40             width = max(polygon[:, 0]) - min(polygon[:, 0])
41             if ignore_tags[i] or min(height, width) < self.min_text_size:
42                 cv2.fillPoly(mask,
43                              polygon.astype(np.int32)[np.newaxis, :, :], 0)
44                 ignore_tags[i] = True
45             else:
46                 polygon_shape = Polygon(polygon)
47                 distance = polygon_shape.area * (
48                     1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length
49                 subject = [tuple(l) for l in text_polys[i]]
50                 padding = pyclipper.PyclipperOffset()
51                 padding.AddPath(subject, pyclipper.JT_ROUND,
52                                 pyclipper.ET_CLOSEDPOLYGON)
53                 shrinked = padding.Execute(-distance)
54                 if shrinked == []:
55                     cv2.fillPoly(mask,
56                                  polygon.astype(np.int32)[np.newaxis, :, :], 0)
57                     ignore_tags[i] = True
58                     continue
59                 shrinked = np.array(shrinked[0]).reshape(-1, 2)
60                 cv2.fillPoly(gt, [shrinked.astype(np.int32)], 1)
61                 # cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1)
62 
63         data['shrink_map'] = gt
64         data['shrink_mask'] = mask
65         return data
66 
67     def validate_polygons(self, polygons, ignore_tags, h, w):
68         '''
69         polygons (numpy.array, required): of shape (num_instances, num_points, 2)
70         '''
71         if len(polygons) == 0:
72             return polygons, ignore_tags
73         assert len(polygons) == len(ignore_tags)
74         for polygon in polygons:
75             polygon[:, 0] = np.clip(polygon[:, 0], 0, w - 1)
76             polygon[:, 1] = np.clip(polygon[:, 1], 0, h - 1)
77 
78         for i in range(len(polygons)):
79             area = self.polygon_area(polygons[i])
80             if abs(area) < 1:
81                 ignore_tags[i] = True
82             if area > 0:
83                 polygons[i] = polygons[i][::-1, :]
84         return polygons, ignore_tags
85 
86     def polygon_area(self, polygon):
87         # return cv2.contourArea(polygon.astype(np.float32))
88         edge = 0
89         for i in range(polygon.shape[0]):
90             next_index = (i + 1) % polygon.shape[0]
91             edge += (polygon[next_index, 0] - polygon[i, 0]) * (
92                 polygon[next_index, 1] - polygon[i, 1])
93 
94         return edge / 2.
95
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ppocr/data/imaug/make_shrink_map.py b/ppocr/data/imaug/make_shrink_map.py
--- a/ppocr/data/imaug/make_shrink_map.py
+++ b/ppocr/data/imaug/make_shrink_map.py
@@ -44,20 +44,33 @@
                 ignore_tags[i] = True
             else:
                 polygon_shape = Polygon(polygon)
-                distance = polygon_shape.area * (
-                    1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length
-                subject = [tuple(l) for l in text_polys[i]]
+                subject = [tuple(l) for l in polygon]
                 padding = pyclipper.PyclipperOffset()
                 padding.AddPath(subject, pyclipper.JT_ROUND,
                                 pyclipper.ET_CLOSEDPOLYGON)
-                shrinked = padding.Execute(-distance)
+                shrinked = []
+
+                # Increase the shrink ratio every time we get multiple polygon returned back 
+                possible_ratios = np.arange(self.shrink_ratio, 1, self.shrink_ratio)
+                np.append(possible_ratios, 1)
+                # print(possible_ratios)
+                for ratio in possible_ratios:
+                    # print(f"Change shrink ratio to {ratio}")
+                    distance = polygon_shape.area * (
+                        1 - np.power(ratio, 2)) / polygon_shape.length
+                    shrinked = padding.Execute(-distance)
+                    if len(shrinked) == 1:
+                        break
+
                 if shrinked == []:
                     cv2.fillPoly(mask,
                                  polygon.astype(np.int32)[np.newaxis, :, :], 0)
                     ignore_tags[i] = True
                     continue
-                shrinked = np.array(shrinked[0]).reshape(-1, 2)
-                cv2.fillPoly(gt, [shrinked.astype(np.int32)], 1)
+
+                for each_shirnk in shrinked:
+                    shirnk = np.array(each_shirnk).reshape(-1, 2)
+                    cv2.fillPoly(gt, [shirnk.astype(np.int32)], 1)
                 # cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1)
 
         data['shrink_map'] = gt
@@ -91,4 +104,4 @@
             edge += (polygon[next_index, 0] - polygon[i, 0]) * (
                 polygon[next_index, 1] - polygon[i, 1])
 
-        return edge / 2.
+        return edge / 2.
\ No newline at end of file

{"golden_diff": "diff --git a/ppocr/data/imaug/make_shrink_map.py b/ppocr/data/imaug/make_shrink_map.py\n--- a/ppocr/data/imaug/make_shrink_map.py\n+++ b/ppocr/data/imaug/make_shrink_map.py\n@@ -44,20 +44,33 @@\n                 ignore_tags[i] = True\n             else:\n                 polygon_shape = Polygon(polygon)\n-                distance = polygon_shape.area * (\n-                    1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length\n-                subject = [tuple(l) for l in text_polys[i]]\n+                subject = [tuple(l) for l in polygon]\n                 padding = pyclipper.PyclipperOffset()\n                 padding.AddPath(subject, pyclipper.JT_ROUND,\n                                 pyclipper.ET_CLOSEDPOLYGON)\n-                shrinked = padding.Execute(-distance)\n+                shrinked = []\n+\n+                # Increase the shrink ratio every time we get multiple polygon returned back \n+                possible_ratios = np.arange(self.shrink_ratio, 1, self.shrink_ratio)\n+                np.append(possible_ratios, 1)\n+                # print(possible_ratios)\n+                for ratio in possible_ratios:\n+                    # print(f\"Change shrink ratio to {ratio}\")\n+                    distance = polygon_shape.area * (\n+                        1 - np.power(ratio, 2)) / polygon_shape.length\n+                    shrinked = padding.Execute(-distance)\n+                    if len(shrinked) == 1:\n+                        break\n+\n                 if shrinked == []:\n                     cv2.fillPoly(mask,\n                                  polygon.astype(np.int32)[np.newaxis, :, :], 0)\n                     ignore_tags[i] = True\n                     continue\n-                shrinked = np.array(shrinked[0]).reshape(-1, 2)\n-                cv2.fillPoly(gt, [shrinked.astype(np.int32)], 1)\n+\n+                for each_shirnk in shrinked:\n+                    shirnk = np.array(each_shirnk).reshape(-1, 2)\n+                    cv2.fillPoly(gt, [shirnk.astype(np.int32)], 1)\n                 # cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1)\n \n         data['shrink_map'] = gt\n@@ -91,4 +104,4 @@\n             edge += (polygon[next_index, 0] - polygon[i, 0]) * (\n                 polygon[next_index, 1] - polygon[i, 1])\n \n-        return edge / 2.\n+        return edge / 2.\n\\ No newline at end of file\n", "issue": "Shrink map generation at training for DB is wrong for some polygon\nHi. Thanks for the great works.\r\n\r\nAfter trying the DB training code, I've found out that the current shrink map generation at training for DB is wrong for some polygon.\r\n\r\nFor example, this polygon:\r\n```\r\n[[370, 111], [360, 111], [354, 113], [337, 113], [336, 109], [281, 109], [278, 111], [269, 111], [260, 108], [243, 108], [241, 108], [181, 108], [177, 111], [169, 111], [162, 112], [145, 112], [144, 108], [84, 108], [83, 108], [9, 108], [9, 117], [83, 117], [84, 117], [144, 117], [145, 119], [162, 119], [169, 117], [177, 117], [181, 118], [241, 118], [243, 114], [260, 114], [269, 118], [278, 118], [281, 118], [336, 118], [337, 119], [354, 119], [360, 118], [370, 118]]\r\n```\r\n![lol2](https://user-images.githubusercontent.com/26834698/108241717-b582d380-717e-11eb-9d7a-d6bf3fc0cf55.png)\r\n\r\nWill result in this mask after shrinking\r\n![lol](https://user-images.githubusercontent.com/26834698/108241733-bb78b480-717e-11eb-9bfd-da67fc275607.png)\r\n\r\nWhy? We can take a look at this block of code\r\n\r\nhttps://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L47-L60\r\n\r\nSince vatti clipping algorithm invoked by pyclipper can return multiple polygon (5 in this case, with the default shrink ratio 0.4) like this:\r\n```\r\n[[[240, 112], [239, 115], [181, 115], [177, 114], [179, 114], [183, 111], [243, 111]], [[367, 115], [360, 115], [356, 116], [361, 114], [367, 114]], [[334, 114], [334, 115], [270, 115], [268, 114], [280, 114], [283, 112], [333, 112]], [[142, 113], [142, 114], [12, 114], [12, 111], [141, 111]], [[147, 116], [147, 115], [162, 115], [169, 114], [162, 116]]]\r\n```\r\n![lol](https://user-images.githubusercontent.com/26834698/108242184-3510a280-717f-11eb-8cc9-90e14e1f351b.png)\r\n\r\nBut the current implementation only uses the first polygon and assumes there is only one polygon, leading to the wrong shrink map. \r\nhttps://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L59\r\n\r\nThis will greatly affect the accuracy of the trained model. Ideally, we would want a shrink map of a text region to not be spliced up like above but rather a shrink map like this (not using the original polygon of course, if it can):\r\n\r\n![lol](https://user-images.githubusercontent.com/26834698/108242699-cbdd5f00-717f-11eb-8f05-4d81f53ae649.png)\r\n\r\nI already sent a PR to fix this issue (#2014).\nShrink map generation at training for DB is wrong for some polygon\nHi. Thanks for the great works.\r\n\r\nAfter trying the DB training code, I've found out that the current shrink map generation at training for DB is wrong for some polygon.\r\n\r\nFor example, this polygon:\r\n```\r\n[[370, 111], [360, 111], [354, 113], [337, 113], [336, 109], [281, 109], [278, 111], [269, 111], [260, 108], [243, 108], [241, 108], [181, 108], [177, 111], [169, 111], [162, 112], [145, 112], [144, 108], [84, 108], [83, 108], [9, 108], [9, 117], [83, 117], [84, 117], [144, 117], [145, 119], [162, 119], [169, 117], [177, 117], [181, 118], [241, 118], [243, 114], [260, 114], [269, 118], [278, 118], [281, 118], [336, 118], [337, 119], [354, 119], [360, 118], [370, 118]]\r\n```\r\n![lol2](https://user-images.githubusercontent.com/26834698/108241717-b582d380-717e-11eb-9d7a-d6bf3fc0cf55.png)\r\n\r\nWill result in this mask after shrinking\r\n![lol](https://user-images.githubusercontent.com/26834698/108241733-bb78b480-717e-11eb-9bfd-da67fc275607.png)\r\n\r\nWhy? We can take a look at this block of code\r\n\r\nhttps://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L47-L60\r\n\r\nSince vatti clipping algorithm invoked by pyclipper can return multiple polygon (5 in this case, with the default shrink ratio 0.4) like this:\r\n```\r\n[[[240, 112], [239, 115], [181, 115], [177, 114], [179, 114], [183, 111], [243, 111]], [[367, 115], [360, 115], [356, 116], [361, 114], [367, 114]], [[334, 114], [334, 115], [270, 115], [268, 114], [280, 114], [283, 112], [333, 112]], [[142, 113], [142, 114], [12, 114], [12, 111], [141, 111]], [[147, 116], [147, 115], [162, 115], [169, 114], [162, 116]]]\r\n```\r\n![lol](https://user-images.githubusercontent.com/26834698/108242184-3510a280-717f-11eb-8cc9-90e14e1f351b.png)\r\n\r\nBut the current implementation only uses the first polygon and assumes there is only one polygon, leading to the wrong shrink map. \r\nhttps://github.com/PaddlePaddle/PaddleOCR/blob/d91c3e7c6b851f1c3d3af95c8f9c3e7276200ee7/ppocr/data/imaug/make_shrink_map.py#L59\r\n\r\nThis will greatly affect the accuracy of the trained model. Ideally, we would want a shrink map of a text region to not be spliced up like above but rather a shrink map like this (not using the original polygon of course, if it can):\r\n\r\n![lol](https://user-images.githubusercontent.com/26834698/108242699-cbdd5f00-717f-11eb-8f05-4d81f53ae649.png)\r\n\r\nI already sent a PR to fix this issue (#2014).\n", "before_files": [{"content": "# -*- coding:utf-8 -*- \n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport numpy as np\nimport cv2\nfrom shapely.geometry import Polygon\nimport pyclipper\n\n__all__ = ['MakeShrinkMap']\n\n\nclass MakeShrinkMap(object):\n    r'''\n    Making binary mask from detection data with ICDAR format.\n    Typically following the process of class `MakeICDARData`.\n    '''\n\n    def __init__(self, min_text_size=8, shrink_ratio=0.4, **kwargs):\n        self.min_text_size = min_text_size\n        self.shrink_ratio = shrink_ratio\n\n    def __call__(self, data):\n        image = data['image']\n        text_polys = data['polys']\n        ignore_tags = data['ignore_tags']\n\n        h, w = image.shape[:2]\n        text_polys, ignore_tags = self.validate_polygons(text_polys,\n                                                         ignore_tags, h, w)\n        gt = np.zeros((h, w), dtype=np.float32)\n        # gt = np.zeros((1, h, w), dtype=np.float32)\n        mask = np.ones((h, w), dtype=np.float32)\n        for i in range(len(text_polys)):\n            polygon = text_polys[i]\n            height = max(polygon[:, 1]) - min(polygon[:, 1])\n            width = max(polygon[:, 0]) - min(polygon[:, 0])\n            if ignore_tags[i] or min(height, width) < self.min_text_size:\n                cv2.fillPoly(mask,\n                             polygon.astype(np.int32)[np.newaxis, :, :], 0)\n                ignore_tags[i] = True\n            else:\n                polygon_shape = Polygon(polygon)\n                distance = polygon_shape.area * (\n                    1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length\n                subject = [tuple(l) for l in text_polys[i]]\n                padding = pyclipper.PyclipperOffset()\n                padding.AddPath(subject, pyclipper.JT_ROUND,\n                                pyclipper.ET_CLOSEDPOLYGON)\n                shrinked = padding.Execute(-distance)\n                if shrinked == []:\n                    cv2.fillPoly(mask,\n                                 polygon.astype(np.int32)[np.newaxis, :, :], 0)\n                    ignore_tags[i] = True\n                    continue\n                shrinked = np.array(shrinked[0]).reshape(-1, 2)\n                cv2.fillPoly(gt, [shrinked.astype(np.int32)], 1)\n                # cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1)\n\n        data['shrink_map'] = gt\n        data['shrink_mask'] = mask\n        return data\n\n    def validate_polygons(self, polygons, ignore_tags, h, w):\n        '''\n        polygons (numpy.array, required): of shape (num_instances, num_points, 2)\n        '''\n        if len(polygons) == 0:\n            return polygons, ignore_tags\n        assert len(polygons) == len(ignore_tags)\n        for polygon in polygons:\n            polygon[:, 0] = np.clip(polygon[:, 0], 0, w - 1)\n            polygon[:, 1] = np.clip(polygon[:, 1], 0, h - 1)\n\n        for i in range(len(polygons)):\n            area = self.polygon_area(polygons[i])\n            if abs(area) < 1:\n                ignore_tags[i] = True\n            if area > 0:\n                polygons[i] = polygons[i][::-1, :]\n        return polygons, ignore_tags\n\n    def polygon_area(self, polygon):\n        # return cv2.contourArea(polygon.astype(np.float32))\n        edge = 0\n        for i in range(polygon.shape[0]):\n            next_index = (i + 1) % polygon.shape[0]\n            edge += (polygon[next_index, 0] - polygon[i, 0]) * (\n                polygon[next_index, 1] - polygon[i, 1])\n\n        return edge / 2.\n", "path": "ppocr/data/imaug/make_shrink_map.py"}], "after_files": [{"content": "# -*- coding:utf-8 -*- \n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport numpy as np\nimport cv2\nfrom shapely.geometry import Polygon\nimport pyclipper\n\n__all__ = ['MakeShrinkMap']\n\n\nclass MakeShrinkMap(object):\n    r'''\n    Making binary mask from detection data with ICDAR format.\n    Typically following the process of class `MakeICDARData`.\n    '''\n\n    def __init__(self, min_text_size=8, shrink_ratio=0.4, **kwargs):\n        self.min_text_size = min_text_size\n        self.shrink_ratio = shrink_ratio\n\n    def __call__(self, data):\n        image = data['image']\n        text_polys = data['polys']\n        ignore_tags = data['ignore_tags']\n\n        h, w = image.shape[:2]\n        text_polys, ignore_tags = self.validate_polygons(text_polys,\n                                                         ignore_tags, h, w)\n        gt = np.zeros((h, w), dtype=np.float32)\n        # gt = np.zeros((1, h, w), dtype=np.float32)\n        mask = np.ones((h, w), dtype=np.float32)\n        for i in range(len(text_polys)):\n            polygon = text_polys[i]\n            height = max(polygon[:, 1]) - min(polygon[:, 1])\n            width = max(polygon[:, 0]) - min(polygon[:, 0])\n            if ignore_tags[i] or min(height, width) < self.min_text_size:\n                cv2.fillPoly(mask,\n                             polygon.astype(np.int32)[np.newaxis, :, :], 0)\n                ignore_tags[i] = True\n            else:\n                polygon_shape = Polygon(polygon)\n                subject = [tuple(l) for l in polygon]\n                padding = pyclipper.PyclipperOffset()\n                padding.AddPath(subject, pyclipper.JT_ROUND,\n                                pyclipper.ET_CLOSEDPOLYGON)\n                shrinked = []\n\n                # Increase the shrink ratio every time we get multiple polygon returned back \n                possible_ratios = np.arange(self.shrink_ratio, 1, self.shrink_ratio)\n                np.append(possible_ratios, 1)\n                # print(possible_ratios)\n                for ratio in possible_ratios:\n                    # print(f\"Change shrink ratio to {ratio}\")\n                    distance = polygon_shape.area * (\n                        1 - np.power(ratio, 2)) / polygon_shape.length\n                    shrinked = padding.Execute(-distance)\n                    if len(shrinked) == 1:\n                        break\n\n                if shrinked == []:\n                    cv2.fillPoly(mask,\n                                 polygon.astype(np.int32)[np.newaxis, :, :], 0)\n                    ignore_tags[i] = True\n                    continue\n\n                for each_shirnk in shrinked:\n                    shirnk = np.array(each_shirnk).reshape(-1, 2)\n                    cv2.fillPoly(gt, [shirnk.astype(np.int32)], 1)\n                # cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1)\n\n        data['shrink_map'] = gt\n        data['shrink_mask'] = mask\n        return data\n\n    def validate_polygons(self, polygons, ignore_tags, h, w):\n        '''\n        polygons (numpy.array, required): of shape (num_instances, num_points, 2)\n        '''\n        if len(polygons) == 0:\n            return polygons, ignore_tags\n        assert len(polygons) == len(ignore_tags)\n        for polygon in polygons:\n            polygon[:, 0] = np.clip(polygon[:, 0], 0, w - 1)\n            polygon[:, 1] = np.clip(polygon[:, 1], 0, h - 1)\n\n        for i in range(len(polygons)):\n            area = self.polygon_area(polygons[i])\n            if abs(area) < 1:\n                ignore_tags[i] = True\n            if area > 0:\n                polygons[i] = polygons[i][::-1, :]\n        return polygons, ignore_tags\n\n    def polygon_area(self, polygon):\n        # return cv2.contourArea(polygon.astype(np.float32))\n        edge = 0\n        for i in range(polygon.shape[0]):\n            next_index = (i + 1) % polygon.shape[0]\n            edge += (polygon[next_index, 0] - polygon[i, 0]) * (\n                polygon[next_index, 1] - polygon[i, 1])\n\n        return edge / 2.", "path": "ppocr/data/imaug/make_shrink_map.py"}]}