|
1 | 1 | import pycocotools.mask as mask |
2 | 2 | import numpy as np |
| 3 | +import shapely |
| 4 | +from shapely.geometry import LineString, Point |
3 | 5 |
|
4 | 6 | from database import ( |
5 | 7 | fix_ids, |
@@ -48,8 +50,8 @@ def paperjs_to_coco(image_width, image_height, paperjs): |
48 | 50 |
|
49 | 51 | # Point |
50 | 52 | if len(point) == 2: |
51 | | - x = _fit(round(center[0] + point[0], 2), image_width, 0) |
52 | | - y = _fit(round(center[1] + point[1], 2), image_height, 0) |
| 53 | + x = round(center[0] + point[0], 2) |
| 54 | + y = round(center[1] + point[1], 2) |
53 | 55 | segments_to_add.extend([x, y]) |
54 | 56 |
|
55 | 57 | # Make sure shape is not all outside the image |
@@ -78,6 +80,113 @@ def paperjs_to_coco(image_width, image_height, paperjs): |
78 | 80 | return segments, area, bbox |
79 | 81 |
|
80 | 82 |
|
| 83 | +def paperjs_to_coco_cliptobounds(image_width, image_height, paperjs): # todo: there's lots of edge cases to this. It needs a different solution or many many if statements :P |
| 84 | + """ |
| 85 | + Given a paperjs CompoundPath, converts path into coco segmentation format based on children paths |
| 86 | +
|
| 87 | + :param image_width: Width of Image |
| 88 | + :param image_height: Height of Image |
| 89 | + :param paperjs: paperjs CompoundPath in dict format |
| 90 | + :return: segmentation, area, bbox |
| 91 | + """ |
| 92 | + assert image_width > 0 |
| 93 | + assert image_height > 0 |
| 94 | + assert len(paperjs) == 2 |
| 95 | + |
| 96 | + # Compute segmentation |
| 97 | + # paperjs points are relative to the center, so we must shift them relative to the top left. |
| 98 | + segments = [] |
| 99 | + center = [image_width/2, image_height/2] |
| 100 | + |
| 101 | + if paperjs[0] == "Path": |
| 102 | + compound_path = {"children": [paperjs]} |
| 103 | + else: |
| 104 | + compound_path = paperjs[1] |
| 105 | + |
| 106 | + children = compound_path.get('children', []) |
| 107 | + |
| 108 | + for child in children: |
| 109 | + |
| 110 | + child_segments = child[1].get('segments', []) |
| 111 | + segments_to_add = [] |
| 112 | + |
| 113 | + |
| 114 | + i_start = 0 |
| 115 | + inside = False |
| 116 | + # find a point that's inside the canvas |
| 117 | + while(i_start < len(child_segments)): |
| 118 | + point = child_segments[i_start] |
| 119 | + if len(point) == 4: point = point[0] # curve |
| 120 | + if len(point) == 2: # point |
| 121 | + if (abs(point[0]) > image_width/2 or point[1] > image_height/2): |
| 122 | + i_start += 1 |
| 123 | + continue |
| 124 | + inside = True |
| 125 | + break |
| 126 | + i_start += 1 |
| 127 | + |
| 128 | + if inside: # if point is inside the canvas. Otherwise ignore it |
| 129 | + edges = { |
| 130 | + 'w_0': np.array([[0,0],[image_width, 0]], np.float), |
| 131 | + 'w_1': np.array([[0,image_height],[image_width, image_height]], np.float), |
| 132 | + 'h_0': np.array([[0,0],[0, image_height]], np.float), |
| 133 | + 'h_1': np.array([[image_width,0],[image_width, image_height]], np.float), |
| 134 | + } |
| 135 | + prev_point = None |
| 136 | + for i in range(i_start, i_start + len(child_segments)): |
| 137 | + p = i % len(child_segments) |
| 138 | + point = child_segments[p] |
| 139 | + |
| 140 | + # print('point:', point, flush=True) |
| 141 | + # Cruve |
| 142 | + if len(point) == 4: |
| 143 | + point = point[0] |
| 144 | + |
| 145 | + # Point |
| 146 | + if len(point) == 2: |
| 147 | + x = round(center[0] + point[0], 2) |
| 148 | + y = round(center[1] + point[1], 2) |
| 149 | + x_orig, y_orig = x,y |
| 150 | + point_outside = x > image_width or x < 0 or y > image_height or y < 0 |
| 151 | + # prev_point_outside = prev_point[0] > image_width or prev_point[0] < 0 or prev_point[1] > image_height or prev_point[1] < 0 |
| 152 | + if point_outside: # outside canvas |
| 153 | + line = LineString([[x,y], prev_point]) |
| 154 | + for _, edge in edges.items(): |
| 155 | + intersect = line.intersection(LineString(edge)) |
| 156 | + if not intersect.is_empty: |
| 157 | + if intersect.type == 'LineString': intersect = intersect.xy[0] |
| 158 | + else: intersect = [intersect.x, intersect.y] |
| 159 | + print(x,y, prev_point) |
| 160 | + print(intersect, flush=True) |
| 161 | + x,y = intersect |
| 162 | + break |
| 163 | + segments_to_add.extend([x, y]) |
| 164 | + prev_point = [x_orig,y_orig] |
| 165 | + # Make sure shape is not all outside the image |
| 166 | + if sum(segments_to_add) == 0: |
| 167 | + continue |
| 168 | + |
| 169 | + if len(segments_to_add) == 4: |
| 170 | + # len 4 means this is a line with no width; it contributes |
| 171 | + # no area to the mask, and if we include it, coco will treat |
| 172 | + # it instead as a bbox (and throw an error) |
| 173 | + continue |
| 174 | + |
| 175 | + num_widths = segments_to_add.count(image_width) |
| 176 | + num_heights = segments_to_add.count(image_height) |
| 177 | + if num_widths + num_heights == len(segments_to_add): |
| 178 | + continue |
| 179 | + |
| 180 | + segments.append(segments_to_add) |
| 181 | + |
| 182 | + if len(segments) < 1: |
| 183 | + return [], 0, [0, 0, 0, 0] |
| 184 | + |
| 185 | + area, bbox = get_segmentation_area_and_bbox( |
| 186 | + segments, image_height, image_width) |
| 187 | + |
| 188 | + return segments, area, bbox |
| 189 | + |
81 | 190 | def get_segmentation_area_and_bbox(segmentation, image_height, image_width): |
82 | 191 | # Convert into rle |
83 | 192 | rles = mask.frPyObjects(segmentation, image_height, image_width) |
|
0 commit comments