def upload_annotations(cytomine, img, y, term=None, proba=1.): points = np.transpose(y.nonzero()) points = [Point(x, y) for x, y in points] if isinstance(img, Annotation): img_inst = cytomine.get_image_instance(img.image) crop_location = affine_transform(loads(img.location), [0, -1, 1, 0, img_inst.height, 0]) offset, width, height = polygon_box(crop_location) else: offset = (0, 0) img_inst = img affine_matrix = [0, 1, -1, 0, offset[1], img_inst.height - offset[0]] points = [affine_transform(pt, affine_matrix) for pt in points] for point in points: annotation = cytomine.add_annotation(point.wkt, img_inst.id) if term is not None and annotation is not None: cytomine.add_annotation_term( annotation.id, term, term, proba, annotation_term_model=AlgoAnnotationTerm)
def test_affine_3d(self): g2 = load_wkt('LINESTRING(2.4 4.1, 2.4 3, 3 3)') g3 = load_wkt('LINESTRING(2.4 4.1 100.2, 2.4 3 132.8, 3 3 128.6)') # custom scale and translate matrix2d = (2, 0, 0, 2.5, -5, 4.1) matrix3d = (2, 0, 0, 0, 2.5, 0, 0, 0, 0.3048, -5, 4.1, 100) # Combinations of 2D and 3D geometries and matrices a22 = affinity.affine_transform(g2, matrix2d) a23 = affinity.affine_transform(g2, matrix3d) a32 = affinity.affine_transform(g3, matrix2d) a33 = affinity.affine_transform(g3, matrix3d) # Check dimensions self.assertFalse(a22.has_z) self.assertFalse(a23.has_z) self.assertTrue(a32.has_z) self.assertTrue(a33.has_z) # 2D equality checks expected2d = load_wkt('LINESTRING(-0.2 14.35, -0.2 11.6, 1 11.6)') expected3d = load_wkt('LINESTRING(-0.2 14.35 130.54096, ' '-0.2 11.6 140.47744, 1 11.6 139.19728)') expected32 = load_wkt('LINESTRING(-0.2 14.35 100.2, ' '-0.2 11.6 132.8, 1 11.6 128.6)') self.assertTrue(a22.almost_equals(expected2d)) self.assertTrue(a23.almost_equals(expected2d)) # Do explicit 3D check of coordinate values for a, e in zip(a32.coords, expected32.coords): for ap, ep in zip(a, e): self.assertAlmostEqual(ap, ep) for a, e in zip(a33.coords, expected3d.coords): for ap, ep in zip(a, e): self.assertAlmostEqual(ap, ep)
def improved_buffer(input_geometry, buffer_width, separation_width, simplify_length, show_progress=False): buffer_width *= GEO.m_to_lat separation_width *= GEO.m_to_lat simplify_length *= GEO.m_to_lat if show_progress: UI.progress_bar(1, 0) input_geometry = affinity.affine_transform(input_geometry, [scalx, 0, 0, 1, 0, 0]) output_geometry = input_geometry.buffer(buffer_width + separation_width, join_style=2, mitre_limit=1.5, resolution=1) if show_progress: UI.progress_bar(1, 40) if UI.red_flag: return geometry.Polygon() output_geometry = output_geometry.buffer(-1 * separation_width, join_style=2, mitre_limit=1.5, resolution=1) if show_progress: UI.progress_bar(1, 80) if UI.red_flag: return geometry.Polygon() if simplify_length: output_geometry = output_geometry.simplify(simplify_length) if show_progress: UI.progress_bar(1, 100) if UI.red_flag: return geometry.Polygon() output_geometry = affinity.affine_transform(output_geometry, [1 / scalx, 0, 0, 1, 0, 0]) return output_geometry
def run(self, ips, imgs, para = None): shp = convert.roi2shape(ips.roi) m = ips.img.mat m = [m[0,1], 0, 0, m[1,2], m[0,0], m[1,0]] shp = affine_transform(shp, m) shp = affine_transform(shp, [0,1,1,0,0,0]) gdf = gpd.GeoDataFrame([[shp]], columns=['geometry'], crs=ips.img.crs) gdf.to_file(para['path'])
def get_dataset(cytomine, working_path, id_project, id_term, id_roi_term, id_user=None, reviewed_only=False, id_roi_user=None, reviewed_only_roi=False, force_download=False): # Download ROI annotations crops_annotations = cytomine.get_annotations( id_project=id_project, id_term=id_roi_term, id_user=id_roi_user, reviewed_only=reviewed_only_roi, showWKT=True, showMeta=True) # Download ROI crops crops = cytomine.dump_annotations( annotations=crops_annotations, dest_path=os.path.join(working_path, CROPS_PATH, str(id_project)), override=force_download, desired_zoom=0, get_image_url_func=Annotation.get_annotation_alpha_crop_url).data() dataset = list() for crop in crops: gt_annots = cytomine.get_annotations(id_project=id_project, id_image=crop.image, id_bbox=crop.id, id_term=id_term, id_user=id_user, reviewed_only=reviewed_only, showWKT=True).data() img_inst = cytomine.get_image_instance(crop.image) crop_location = affine_transform(loads(crop.location), [0, -1, 1, 0, img_inst.height, 0]) offset, width, height = polygon_box(crop_location) affine_matrix = [0, -1, 1, 0, img_inst.height - offset[0], -offset[1]] gt_locations = [ affine_transform(loads(gt.location), affine_matrix) for gt in gt_annots ] groundtruth = mk_groundtruth_image(gt_locations, width, height) image_filename = crop.filename groundtruth_filename = save_groundtruth_image( groundtruth, os.path.join(working_path, GROUNDTRUTHS_PATH, str(crop.project)), "{}_{}.png".format(crop.image, crop.id)) dataset.append((image_filename, groundtruth_filename)) return zip(*dataset)
def transform(shape, trans): if isinstance(shape, Collection): return Collection([transform(s, trans) for s in shape.geoms]) elif isinstance(shape, Polygon): # shapely should not be used if the students are implementing this return Polygon(affine_transform(shape.poly, trans).exterior.coord) else: # shapely should not be used if the students are implementing this return Point(affine_transform(shape.point, trans).coords[0])
def connect_IDL(df): logger = logging.getLogger('shippingroutes_connect_IDL') # do an affinity transform, then get nearest points, then reverse the affine transform, then V_inv to get the distance logger.info('intersecting boxes and taking affine transform') pos_box = geometry.box(178, -85, 180, 85) neg_box = geometry.box(-180, -85, -178, 85) df['pos_intersects'] = df['geometry'].apply( lambda el: wkt.loads(el).intersects(pos_box)) df['neg_intersects'] = df['geometry'].apply( lambda el: wkt.loads(el).intersects(neg_box)) df_pos = df[df['pos_intersects']] df_neg = df[df['neg_intersects']] DT = [1, 0, 0, 1, -360, 0] df_pos['geometry'] = df_pos['geometry'].apply( lambda el: affinity.affine_transform(wkt.loads(el), DT)) df_neg['geometry'] = df_neg['geometry'].apply(lambda el: wkt.loads(el)) DT = [1, 0, 0, 1, 360, 0] logger.info('Getting all nearest Points') records = [] for idx_pos, row_pos in tqdm(df_pos.iterrows()): for idx_neg, row_neg in df_neg.iterrows(): pt_pos, pt_neg = ops.nearest_points(row_pos['geometry'], row_neg['geometry']) records.append({ 'pt_pos': affinity.affine_transform(pt_pos, DT), 'pt_neg': pt_neg, 'id_pos': row_pos['unique_id'], 'id_neg': row_neg['unique_id'] }) df_intersection = pd.DataFrame.from_records(records) logger.info('Getting distance between points') df_intersection['DISTANCE'] = df_intersection.progress_apply( lambda row: V_inv((row['pt_pos'].y, row['pt_pos'].x), (row['pt_neg'].y, row['pt_neg'].x))[0] * 1000, axis=1) #m df_intersection = df_intersection.rename(columns={ 'id_pos': 'START', 'id_neg': 'END' }) df_intersection = df_intersection[df_intersection['DISTANCE'] < 10000] df_intersection['PT_START'] = df_intersection['pt_pos'].apply( lambda el: el.wkt) df_intersection['PT_END'] = df_intersection['pt_neg'].apply( lambda el: el.wkt) return df_intersection[['START', 'END', 'PT_START', 'PT_END', 'DISTANCE']]
def test_geom(g2, g3=None): self.assertFalse(g2.has_z) a2 = affinity.affine_transform(g2, matrix2d) self.assertFalse(a2.has_z) self.assertTrue(g2.equals(a2)) if g3 is not None: self.assertTrue(g3.has_z) a3 = affinity.affine_transform(g3, matrix3d) self.assertTrue(a3.has_z) self.assertTrue(g3.equals(a3)) return
def _make_polygon(elt_type, instructions, parent=None, interpolate_curve=50, return_points=False): container = None shell = [] # outer points defining the polygon's outer shell holes = [] # inner points defining holes idx_start = 0 if elt_type == "path": # build polygons from custom paths path_data = parse_path(instructions["path"]) subpaths = [subpath for subpath in _get_closed_subpaths(path_data)] points = [_get_points(subpath) for subpath in subpaths] # get the container idx_container = _get_outer_shell(points) shell = np.array(points[idx_container]) # get the holes and make the shape holes = [pp for i, pp in enumerate(points) if i != idx_container] container = Polygon(shell, holes=holes) elif elt_type == "ellipse": # build ellipses circle = Point((instructions["cx"], instructions["cy"])).buffer(1) rx, ry = instructions["rx"], instructions["ry"] container = scale(circle, rx, ry) elif elt_type == "circle": # build circles r = instructions["r"] container = Point((instructions["cx"], instructions["cy"])).buffer(r) elif elt_type == "rect": # build rectangles x, y = instructions["x"], instructions["y"] w, h = instructions["width"], instructions["height"] shell = np.array([(x, y), (x + w, y), (x + w, y + h), (x, y + h)]) container = Polygon(shell) else: raise RuntimeError("Unexpected element type: '{}'.".format(elt_type)) # transforms nn, dd = instructions["transf"][::-1], instructions["transfdata"][::-1] for name, data in zip(nn, dd): if name == "matrix": container = affine_transform(container, data) elif name == "translate": container = translate(container, *data) # y axis is inverted in SVG, so make mirror transform container = affine_transform(container, (1, 0, 0, -1, 0, 0)) shell = np.array(container.exterior.coords) if return_points: return container, shell return container
def test_affine_2d(self): g = load_wkt('LINESTRING(2.4 4.1, 2.4 3, 3 3)') # custom scale and translate expected2d = load_wkt('LINESTRING(-0.2 14.35, -0.2 11.6, 1 11.6)') matrix2d = (2, 0, 0, 2.5, -5, 4.1) a2 = affinity.affine_transform(g, matrix2d) self.assertTrue(a2.almost_equals(expected2d)) self.assertFalse(a2.has_z) # Make sure a 3D matrix does not make a 3D shape from a 2D input matrix3d = (2, 0, 0, 0, 2.5, 0, 0, 0, 10, -5, 4.1, 100) a3 = affinity.affine_transform(g, matrix3d) self.assertTrue(a3.almost_equals(expected2d)) self.assertFalse(a3.has_z)
def normalize(line, end_idx): traj = LineString(line) start = line[0] #shape [2,] #Translation normalization: start with (0.0, 0.0) #[a, b, c, d, x, y] is the planner transformation matrix[a, b, x; c, d, y; 0, 0, 1] g = [1, 0, 0, 1, -start[0], -start[1]] traj_trans = affine_transform(traj, g) #Rotation normalization: end = traj_trans.coords[end_idx] if end[0] == 0 and end[1] == 0: angle = 0.0 elif end[0] == 0: angle = 90.0 if end[1] < 0 else -90.0 elif end[1] == 0: angle = 0.0 if end[0] > 0 else 180.0 else: angle = math.degrees(math.atan(end[1] / end[0])) if (end[0] > 0 and end[1] > 0) or (end[0] > 0 and end[1] < 0): angle = -angle else: angle = 180.0 - angle #Rotate normalization: end with y=0 traj_rotate = rotate(traj_trans, angle, origin=(0, 0)).coords[:] #Transform to numpy traj_norm = np.array(traj_rotate) return traj_norm
def denormalize_xy(self, xy_locations, translation=None, rotation=None): """Reverse the Translate and rotate operations on the input data Args: xy_locations (numpy array): XY positions for the trajectory Returns: xy_locations_normalized (numpy array): denormalized XY positions """ # Apply rotation num = xy_locations.shape[0] if xy_locations.shape[0] > 1: trajectory = LineString(xy_locations) else: trajectory = LineString(np.concatenate(([[0.0, 0.0]], xy_locations), axis=0)) if rotation is not None: trajectory = rotate(trajectory, rotation, origin=(0, 0)) if translation is not None: mat = [1, 0, 0, 1, translation[0], translation[1]] trajectory = affine_transform(trajectory, mat) output = np.array(trajectory.coords, dtype=np.float32) if num <= 1: output = output[1:] return output
def minimum_rotated_rectangle(self): """Returns the general minimum bounding rectangle of the geometry. Can possibly be rotated. If the convex hull of the object is a degenerate (line or point) this same degenerate is returned. """ # first compute the convex hull hull = self.convex_hull try: coords = hull.exterior.coords except AttributeError: # may be a Point or a LineString return hull # generate the edge vectors between the convex hull's coords edges = ((pt2[0] - pt1[0], pt2[1] - pt1[1]) for pt1, pt2 in zip(coords, islice(coords, 1, None))) def _transformed_rects(): for dx, dy in edges: # compute the normalized direction vector of the edge vector length = math.sqrt(dx**2 + dy**2) ux, uy = dx / length, dy / length # compute the normalized perpendicular vector vx, vy = -uy, ux # transform hull from the original coordinate system to the coordinate system # defined by the edge and compute the axes-parallel bounding rectangle transf_rect = affine_transform(hull, (ux, uy, vx, vy, 0, 0)).envelope # yield the transformed rectangle and a matrix to transform it back # to the original coordinate system yield (transf_rect, (ux, vx, uy, vy, 0, 0)) # check for the minimum area rectangle and return it transf_rect, inv_matrix = min(_transformed_rects(), key=lambda r: r[0].area) return affine_transform(transf_rect, inv_matrix)
def calc_distance_and_angle(p: LocationLocal, ref_p: LocationLocal, rel_angle=0): # if type(p) is LocationGlobal or LocationGlobalRelative: # p = latlon_to_xy() p = Point(p.east, p.north) ref_p = Point(ref_p.east, ref_p.north) # transform to local coordinates p_local = affine_transform(p, [1,0,0,1, -ref_p.x, -ref_p.y]) # alpha = -90 # plus 90 so north is a heading of 0 degrees.With shapely positive rotations are counter clockwise # p_local = rotate(p_local, alpha, origin=(0,0)) # take into account the relative angle of the plane # # convert to polar coordinates # distance = math.sqrt(pow(p.x - ref_p.x, 2) + pow(p.y - ref_p.y, 2)) # angle = math.atan((p.x - ref_p.x) / (p.y - ref_p.y)) (distance, angle) = cmath.polar(complex(p_local.x, p_local.y)) # angle is in radians # convert to degrees and change axis # +90 to set north to heading 0 angle = 90 - math.degrees(angle) - rel_angle # only positive angles if angle < 0: angle+=360 # only angles under 360 if angle > 360: angle-=360 return (distance, angle)
def mapSuperPixels(segments=None, GT=None, proj={'init': 'epsg:32618'}, verbose=True): start = time.time() if verbose: print('--- Mapping superpixels to lat/lng coordinates ---') seg_properties = regionprops(segments) polygons = [ gpd.GeoSeries(Polygon(sp.coords)).convex_hull for sp in seg_properties if (sp.area >= 12) ] polygons = [ affine_transform(p[0], GT) for p in polygons if p[0].geom_type == 'Polygon' ] if len(polygons) == 1: if verbose: print('--- Done - execution time: {} seconds'.format( time.time() - start)) return gpd.GeoDataFrame({'geometry': polygons}, geometry='geometry', crs=proj, index=[0]) else: if verbose: print('--- Done - execution time: {} seconds'.format( time.time() - start)) return gpd.GeoDataFrame({'geometry': polygons}, geometry='geometry', crs=proj)
def minimum_rotated_rectangle(self): """Returns the general minimum bounding rectangle of the geometry. Can possibly be rotated. If the convex hull of the object is a degenerate (line or point) this same degenerate is returned. """ # first compute the convex hull hull = self.convex_hull try: coords = hull.exterior.coords except AttributeError: # may be a Point or a LineString return hull # generate the edge vectors between the convex hull's coords edges = ((pt2[0]-pt1[0], pt2[1]-pt1[1]) for pt1, pt2 in zip(coords, islice(coords, 1, None))) def _transformed_rects(): for dx, dy in edges: # compute the normalized direction vector of the edge vector length = math.sqrt(dx**2 + dy**2) ux, uy = dx/length, dy/length # compute the normalized perpendicular vector vx, vy = -uy, ux # transform hull from the original coordinate system to the coordinate system # defined by the edge and compute the axes-parallel bounding rectangle transf_rect = affine_transform(hull, (ux,uy,vx,vy,0,0)).envelope # yield the transformed rectangle and a matrix to transform it back # to the original coordinate system yield (transf_rect, (ux,vx,uy,vy,0,0)) # check for the minimum area rectangle and return it transf_rect, inv_matrix = min(_transformed_rects(), key=lambda r : r[0].area) return affine_transform(transf_rect, inv_matrix)
def run(self, ips, imgs, para = None): gdf = gpd.read_file(para['path']).to_crs(ips.img.crs) m = ips.img.mat m = [1/m[0,1], 0, 0, 1/m[1,2], -m[0,0]/m[0,1], -m[1,0]/m[1,2]] shp = affine_transform(gdf['geometry'][0], m) ips.roi = convert.shape2roi(shp) if 'back' in ips.data:ips.roi.fill(ips.data['back'], (0,0,80))
def shp2raster(shape, scale, margin=0.05, style='lab', bounds=None): shapes = shape['shape'].values kmargin = margin/(1-2*margin) geoms = list(shape['shape'].values) bounds = bounds or GeometryCollection(geoms).bounds l,t,r,b = bounds w,h = r-l, b-t if isinstance(scale, tuple): W, H = np.array(scale) * (1-margin*2) scale = max(w/W, h/H) offsetx, offsety = l-w*kmargin, b+h*kmargin shp = np.array((h,w))*(1+(kmargin*2))/scale rst = np.zeros(shp.astype(np.int), dtype=np.int16) m = [1/scale, 0, 0, -1/scale, -offsetx/scale, offsety/scale] img = Image.fromarray(rst) draw = ImageDraw.Draw(img) for i in range(len(shapes)): gs = affine_transform(shapes[i], m) for g in gs: pts = np.array(g.exterior.xy).T.astype(np.int).ravel() if style=='lab': draw.polygon(list(pts), i+1) else: draw.line(list(pts), 255, style) #pgs = [np.array(g.exterior.xy).T.astype(np.int) for g in gs] #if style=='lab':cv2.fillPoly(rst, pgs, i+1) #else: cv2.drawContours(rst, pgs, -1, 255, style) rst = np.array(img) m = np.array([offsetx, scale, 0, offsety, 0, -scale]).reshape((2,3)) return Raster([rst], shape.prj, m)
def _recalc(self): cache = _EdgeCorrect._recalc(self) if cache is not None: halfS = cache[2] m = list(halfS.flatten()) + [0, 0] geo = _saffinity.affine_transform(self._geo, m) self._cache = cache + (geo, )
def transform_csg(layerdef_from, layerdef_to, inshift, outshift, step, geom_from, geoms_to, csg_laminate, scale_x, scale_y): from popupcad.filetypes.laminate import Laminate import shapely.affinity as aff from popupcad.algorithms.points import calctransformfrom2lines lsout = Laminate(layerdef_to) for layer_from, layer_to in zip(layerdef_from.layers[::step][inshift:], layerdef_to.layers[outshift:]): newgeoms = [] for geom in geoms_to: for designgeom in csg_laminate.layer_sequence[layer_from].geoms: try: from_line = geom_from.exteriorpoints( scaling=popupcad.csg_processing_scaling) to_line = geom.exteriorpoints( scaling=popupcad.csg_processing_scaling) transform = calctransformfrom2lines(from_line, to_line, scale_x=scale_x, scale_y=scale_y) transformed_geom = aff.affine_transform( designgeom, transform) newgeoms.append(transformed_geom) except IndexError: pass result1 = popupcad.algorithms.csg_shapely.unary_union_safe(newgeoms) results2 = popupcad.algorithms.csg_shapely.condition_shapely_entities( result1) lsout.replacelayergeoms(layer_to, results2) return lsout
def draw_pred_on_slide(slide_path, preds, value_fn, color_fn, opacity=127, size=2048, base_zl=2): level = determine_tissue_extract_level(slide_path, desired_processing_size=size) slide = pyvips.Image.new_from_file(slide_path, page=level) black = (0, 0, 0, 0) mask = Image.new('RGBA', (slide.width, slide.height), black) draw = ImageDraw.Draw(mask) zoom_ratio = 2**(base_zl - level) t_matrix = [zoom_ratio, 0, 0, zoom_ratio, 0, 0] for rect, probas in preds: color = color_fn(value_fn(probas)) with_opacity = color + (opacity, ) draw.rectangle(affine_transform(rect, t_matrix).bounds, fill=with_opacity, outline=black) np_image = np.ndarray(buffer=slide.write_to_memory(), dtype=np.uint8, shape=[slide.height, slide.width, slide.bands]) pil_slide = Image.fromarray(np_image).convert("RGBA") img = Image.alpha_composite(pil_slide, mask) return pil_slide, img.convert("RGB")
def normalized_to_map_coordinates(coords: np.ndarray, translation: List[List[float]], rotation: List[float]) -> np.ndarray: """Denormalize trajectory to bring it back to map frame. Args: coords (numpy array): Array of shape (num_tracks x seq_len x 2) containing normalized coordinates translation (list): Translation matrix used in normalizing trajectories rotation (list): Rotation angle used in normalizing trajectories Returns: _ (numpy array: Array of shape (num_tracks x seq_len x 2) containing coordinates in map frame """ abs_coords = [] for i in range(coords.shape[0]): ls = LineString(coords[i]) # Rotate ls_rotate = rotate(ls, -rotation[i], origin=(0, 0)) # Translate M_inv = [1, 0, 0, 1, -translation[i][4], -translation[i][5]] ls_offset = affine_transform(ls_rotate, M_inv).coords[:] abs_coords.append(ls_offset) return np.array(abs_coords)
def random_point_in_polygon(transforms, areas): transform = random.choices(transforms, weights=areas) x, y = [random.random() for _ in range(2)] if x + y > 1: p = Point(1 - x, 1 - y) else: p = Point(x, y) return affine_transform(p, transform[0])
def _to_shape(annot: ParsedAnnotation, is_grayscale: bool = True) -> Tuple[BaseGeometry, int]: geometry = affine_transform(annot.geometry, affine) if is_grayscale: value = annot.fill_color.as_rgb_tuple()[0] else: value = annot.fill_color.as_int() return geometry, value
def rotate_route(ls, running_right): #I wanted all routes to be seen as if they were running up from the left side of the ball #need to find where they were orignially run from and transform accordingly coords = list(ls.coords) centroidx, _ = ls.centroid.xy starting_point = coords[0] running_right = bool(running_right) high_field = starting_point[1] > 53.3 / 2 #translate the points so the starting point is at 0, 0 moved_coords = LineString([ (c[0] - starting_point[0], c[1] - starting_point[1]) for c in coords ]) #error checking #draw_routes(ls.coords) #routes are designed to be from 'left' side of the ball if high_field: if running_right: #do a 90 degree turn transformed_coords = affinity.rotate(moved_coords, angle=90, origin=(0, 0)) else: #do a 270 degree turn and mirror transformed_coords = affinity.affine_transform( affinity.rotate(moved_coords, angle=270, origin=(0, 0)), (-1, 0, 0, 1, 0, 0)) else: if running_right: #do a 90 degree turn and mirror transformed_coords = affinity.affine_transform( affinity.rotate(moved_coords, angle=90, origin=(0, 0)), (-1, 0, 0, 1, 0, 0)) pass else: #do a 270 degree turn transformed_coords = affinity.rotate(moved_coords, angle=270, origin=(0, 0)) #error checkign #draw_routes(transformed_coords) return transformed_coords
def add_line(poly_xy, idx, patch, patch_angle, patch_x, patch_y, line_list): points = [(p0, p1) for p0, p1 in zip(poly_xy[0, idx:idx + 2], poly_xy[1, idx:idx + 2])] line = LineString(points) line.intersection(patch) if not line.is_empty: line = affinity.rotate(line, -patch_angle, origin=(patch_x, patch_y), use_radians=False) line = affinity.affine_transform(line, [1.0, 0.0, 0.0, 1.0, -patch_x, -patch_y]) line_list.append(line)
def _transformed_rects(): for dx, dy in edges: length = math.sqrt(dx**2 + dy**2) ux, uy = dx / length, dy / length vx, vy = -uy, ux transf_rect = affine_transform(poly, (ux, uy, vx, vy, 0, 0)).envelope yield (transf_rect, (ux, vx, uy, vy, 0, 0))
def draw_lab(raster, shp, name, color, font, anc): gs = shp['geometry'].centroid m = raster.mat m = [ 1 / m[0, 1], 0, 0, -1 / m[0, 1], -m[0, 0] / m[0, 1], m[1, 0] / m[0, 1] ] pos = [(int(p.x), int(p.y)) for p in [affine_transform(i, m) for i in gs]] return draw_text(raster, shp[name], *list(zip(*pos)), color, font, anc)
def add_noise(self, x, rotation, translation): trajectory = LineString(x) mat = [1, 0, 0, 1, translation[0], translation[1]] trajectory_translated = affine_transform(trajectory, mat) # Apply rotation trajectory_rotated = np.array(rotate(trajectory_translated, rotation, origin=(0, 0)).coords, dtype=np.float32) return trajectory_rotated
def reproject_geometry(input_geom, input_crs=None, target_crs=None, affine_obj=None): """Reproject a geometry or coordinate into a new CRS. Arguments --------- input_geom : `str`, `list`, or `Shapely <https://shapely.readthedocs.io>`_ geometry A geometry object to re-project. This can be a 2-member ``list``, in which case `input_geom` is assumed to coorespond to ``[x, y]`` coordinates in `input_crs`. It can also be a Shapely geometry object or a wkt string. input_crs : int, optional The coordinate reference system for `input_geom`'s coordinates, as an EPSG :class:`int`. Required unless `affine_transform` is provided. target_crs : int, optional The target coordinate reference system to re-project the geometry into. If not provided, the appropriate UTM zone will be selected by default, unless `affine_transform` is provided (and therefore CRSs are ignored.) affine_transform : :class:`affine.Affine`, optional An :class:`affine.Affine` object (or a ``[a, b, c, d, e, f]`` list to convert to that format) to use for transformation. Has no effect unless `input_crs` **and** `target_crs` are not provided. Returns ------- output_geom : Shapely geometry A shapely geometry object: - in `target_crs`, if one was provided; - in the appropriate UTM zone, if `input_crs` was provided and `target_crs` was not; - with `affine_transform` applied to it if neither `input_crs` nor `target_crs` were provided. """ input_geom = _check_geom(input_geom) if input_crs is not None: input_crs = _check_crs(input_crs) if target_crs is None: geom = reproject_geometry(input_geom, input_crs, target_crs=_check_crs(4326)) target_crs = latlon_to_utm_epsg(geom.centroid.y, geom.centroid.x) target_crs = _check_crs(target_crs) gdf = gpd.GeoDataFrame(geometry=[input_geom], crs=input_crs.to_wkt()) # create a new instance of the same geometry class as above with the # new coordinates output_geom = gdf.to_crs(target_crs.to_wkt()).iloc[0]['geometry'] else: if affine_obj is None: raise ValueError('If an input CRS is not provided, ' 'affine_transform is required to complete the ' 'transformation.') elif isinstance(affine_obj, Affine): affine_obj = affine_to_list(affine_obj) output_geom = affine_transform(input_geom, affine_obj) return output_geom
def _to_shape(annot: ParsedAnnotation, is_grayscale: bool = True) -> Tuple[BaseGeometry, int]: width = _contour_width(annot.stroke_width) geometry = stretch_contour(affine_transform( contour(annot.geometry, point_style=point_style), affine), width=width) value = annot.stroke_color.as_rgb_tuple( )[0] if is_grayscale else annot.stroke_color.as_int() return geometry, value
def _upload_annotation(cytomine, img_inst, polygon, label=None, proba=1.0): """Upload an annotation and its term (if provided)""" image_id = img_inst.id # Transform polygon to match cytomine (bottom-left) origin point polygon = affine_transform(polygon, [1, 0, 0, -1, 0, img_inst.height]) annotation = cytomine.add_annotation(polygon.wkt, image_id) if label is not None and annotation is not None: cytomine.add_annotation_term(annotation.id, label, label, proba, annotation_term_model=AlgoAnnotationTerm)
def operate(self,design): import shapely.affinity as aff subdesign = design.subdesigns[self.subdesignid] locateline = subdesign.findlocateline() try: designgeometry = subdesign.operations[subdesign.operation_index(self.subopid)].output[self.getoutputref()].csg except AttributeError: subdesign.reprocessoperations() designgeometry = subdesign.operations[subdesign.operation_index(self.subopid)].output[self.getoutputref()].csg sketch = design.sketches[self.sketchid] if self.transformtype==self.transformtypes.place: scale_x = 1. scale_y = 1. elif self.transformtype==self.transformtypes.stretch: scale_x = None scale_y = 1. if self.transformtype==self.transformtypes.scale: scale_x = None scale_y = None if self.transformtype==self.transformtypes.custom: scale_x = self.scalex scale_y = self.scaley lsout = Laminate(design.return_layer_definition()) step = 1 if self.flip: step = -1 if self.shift > 0: outshift = self.shift inshift = 0 elif self.shift <0: outshift = 0 inshift = -self.shift else: outshift = 0 inshift = 0 for layerout,layerin in zip(design.return_layer_definition().layers[outshift:],subdesign.return_layer_definition().layers[::step][inshift:]): newgeoms = [] for geom in sketch.operationgeometry: for designgeom in designgeometry.layer_sequence[layerin].geoms: try: newgeoms.append(aff.affine_transform(designgeom,calctransformfrom2lines(locateline.exteriorpoints(),geom.exteriorpoints(),scale_x = scale_x,scale_y = scale_y))) except IndexError: pass newgeoms = customshapely.unary_union_safe(newgeoms) newgeoms = popupcad.geometry.customshapely.multiinit(newgeoms) lsout.replacelayergeoms(layerout,newgeoms) return lsout
def test_affine_geom_types(self): # identity matrices, which should result with no transformation matrix2d = (1, 0, 0, 1, 0, 0) matrix3d = (1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) # empty in, empty out empty2d = load_wkt('MULTIPOLYGON EMPTY') self.assertTrue(affinity.affine_transform(empty2d, matrix2d).is_empty) def test_geom(g2, g3=None): self.assertFalse(g2.has_z) a2 = affinity.affine_transform(g2, matrix2d) self.assertFalse(a2.has_z) self.assertTrue(g2.equals(a2)) if g3 is not None: self.assertTrue(g3.has_z) a3 = affinity.affine_transform(g3, matrix3d) self.assertTrue(a3.has_z) self.assertTrue(g3.equals(a3)) return pt2d = load_wkt('POINT(12.3 45.6)') pt3d = load_wkt('POINT(12.3 45.6 7.89)') test_geom(pt2d, pt3d) ls2d = load_wkt('LINESTRING(0.9 3.4, 0.7 2, 2.5 2.7)') ls3d = load_wkt('LINESTRING(0.9 3.4 3.3, 0.7 2 2.3, 2.5 2.7 5.5)') test_geom(ls2d, ls3d) lr2d = load_wkt('LINEARRING(0.9 3.4, 0.7 2, 2.5 2.7, 0.9 3.4)') lr3d = load_wkt( 'LINEARRING(0.9 3.4 3.3, 0.7 2 2.3, 2.5 2.7 5.5, 0.9 3.4 3.3)') test_geom(lr2d, lr3d) test_geom(load_wkt('POLYGON((0.9 2.3, 0.5 1.1, 2.4 0.8, 0.9 2.3), ' '(1.1 1.7, 0.9 1.3, 1.4 1.2, 1.1 1.7), ' '(1.6 1.3, 1.7 1, 1.9 1.1, 1.6 1.3))')) test_geom(load_wkt( 'MULTIPOINT ((-300 300), (700 300), (-800 -1100), (200 -300))')) test_geom(load_wkt( 'MULTILINESTRING((0 0, -0.7 -0.7, 0.6 -1), ' '(-0.5 0.5, 0.7 0.6, 0 -0.6))')) test_geom(load_wkt( 'MULTIPOLYGON(((900 4300, -1100 -400, 900 -800, 900 4300)), ' '((1200 4300, 2300 4400, 1900 1000, 1200 4300)))')) # GeometryCollection fails, since it does not have a good constructor gc = load_wkt('GEOMETRYCOLLECTION(POINT(20 70),' ' POLYGON((60 70, 13 35, 60 -30, 60 70)),' ' LINESTRING(60 70, 50 100, 80 100))') self.assertRaises(TypeError, test_geom, gc) # TODO: fix this
def _transformed_rects(): for dx, dy in edges: # compute the normalized direction vector of the edge vector length = math.sqrt(dx**2 + dy**2) ux, uy = dx/length, dy/length # compute the normalized perpendicular vector vx, vy = -uy, ux # transform hull from the original coordinate system to the coordinate system # defined by the edge and compute the axes-parallel bounding rectangle transf_rect = affine_transform(hull, (ux,uy,vx,vy,0,0)).envelope # yield the transformed rectangle and a matrix to transform it back # to the original coordinate system yield (transf_rect, (ux,vx,uy,vy,0,0))
def operate(self,design): from popupcad.filetypes.genericshapes import GenericLine import shapely.affinity as aff import popupcad.algorithms.points as points import popupcad import shapely.geometry as sg import numpy parent_ref,parent_index = self.operation_links['source'][0] parent = design.op_from_ref(parent_ref).output[parent_index].csg sketch = design.sketches[self.sketch_links['cross_section'][0]] layerdef = design.return_layer_definition() laminate = Laminate(layerdef) for item in sketch.operationgeometry: if isinstance(item,GenericLine): line = item b = line.exteriorpoints()[0] c = numpy.array(b)+numpy.array([1,0]) a = points.calctransformfrom2lines(line.exteriorpoints(),[b,c.tolist()],scale_x=1,scale_y=1) sketch_csg = sketch.output_csg() for layer in layerdef.layers: laminate.replacelayergeoms(layer,sketch_csg) result = parent.intersection(laminate) laminate2 = Laminate(layerdef) for ii,layerid in enumerate(layerdef.layers): # for ii,layer in enumerate(result): yshift = layerdef.zvalue[layerid] * self.scale_value layer = result.layer_sequence[layerid] thickness = layerid.thickness*popupcad.internal_argument_scaling*self.scale_value newgeoms = [item for item in layer.geoms] newgeoms = [aff.affine_transform(item,a) for item in newgeoms] # newgeoms = [item.buffer(bufferval) for item in newgeoms] newgeoms2 = [] for geom in newgeoms: newgeom = sg.box(geom.coords[0][0],geom.coords[0][1],geom.coords[-1][0],geom.coords[-1][1]+thickness) newgeoms2.append(newgeom) newgeoms = newgeoms2 newgeoms = [aff.translate(item,yoff = yshift) for item in newgeoms] newgeoms = popupcad.geometry.customshapely.multiinit(*newgeoms) laminate2[ii] = newgeoms return laminate2 return laminate
def cross_section(layerdef, sketch, parent, scale_value): from popupcad.filetypes.laminate import Laminate from popupcad.filetypes.genericshapes import GenericLine import shapely.affinity as aff import popupcad.algorithms.points as points import shapely.geometry as sg import numpy laminate = Laminate(layerdef) for item in sketch.operationgeometry: if isinstance(item, GenericLine): line = item b = line.exteriorpoints(scaling = popupcad.csg_processing_scaling)[0] c = numpy.array(b) + numpy.array([1, 0]) a = points.calctransformfrom2lines( line.exteriorpoints(scaling = popupcad.csg_processing_scaling), [ b, c.tolist()], scale_x=1, scale_y=1) sketch_csg = sketch.output_csg() for layer in layerdef.layers: laminate.replacelayergeoms(layer, sketch_csg) result = parent.intersection(laminate) laminate2 = Laminate(layerdef) for ii, layerid in enumerate(layerdef.layers): # for ii,layer in enumerate(result): yshift = layerdef.zvalue[layerid] * popupcad.csg_processing_scaling * scale_value layer = result.layer_sequence[layerid] thickness = layerid.thickness * popupcad.csg_processing_scaling * scale_value newgeoms = [item for item in layer.geoms] newgeoms = [aff.affine_transform(item, a) for item in newgeoms] # newgeoms = [item.buffer(bufferval) for item in newgeoms] newgeoms2 = [] for geom in newgeoms: newgeom = sg.box(geom.coords[0][0], geom.coords[0][1], geom.coords[-1][0], geom.coords[-1][1] + thickness) newgeoms2.append(newgeom) newgeoms = newgeoms2 newgeoms = [aff.translate(item,yoff=yshift) for item in newgeoms] newgeoms = popupcad.algorithms.csg_shapely.condition_shapely_entities(*newgeoms) laminate2[ii] = newgeoms return laminate2 return laminate
def transform( layerdef, layerdef_subdesign, inshift, outshift, step, sketch, designgeometry, locateline, scale_x, scale_y): from popupcad.filetypes.laminate import Laminate import shapely.affinity as aff from popupcad.algorithms.points import calctransformfrom2lines lsout = Laminate(layerdef) for layerout, layerin in zip( layerdef.layers[ outshift:], layerdef_subdesign.layers[ ::step][ inshift:]): newgeoms = [] for geom in sketch.operationgeometry: if not geom.is_construction(): for designgeom in designgeometry.layer_sequence[layerin].geoms: try: newgeoms.append( aff.affine_transform( designgeom, calctransformfrom2lines( locateline.exteriorpoints(scaling = popupcad.csg_processing_scaling), geom.exteriorpoints(scaling = popupcad.csg_processing_scaling), scale_x=scale_x, scale_y=scale_y))) except IndexError: pass result1 = popupcad.algorithms.csg_shapely.unary_union_safe(newgeoms) results2 = popupcad.algorithms.csg_shapely.condition_shapely_entities(result1) lsout.replacelayergeoms(layerout, results2) return lsout
def _locate(segmented, offset=None): """Inspired from: https://goo.gl/HYPrR1""" # CV_RETR_EXTERNAL to only get external contours. _, contours, hierarchy = cv2.findContours(segmented.copy(), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) # Note: points are represented as (col, row)-tuples apparently transform = identity if offset is not None: col_off, row_off = offset transform = lambda p: affine_transform(p, [1, 0, 0, 1, col_off, row_off]) components = [] if len(contours) > 0: top_index = 0 tops_remaining = True while tops_remaining: exterior = contours[top_index][:, 0, :].tolist() interiors = [] # check if there are childs and process if necessary if hierarchy[0][top_index][2] != -1: sub_index = hierarchy[0][top_index][2] subs_remaining = True while subs_remaining: interiors.append(contours[sub_index][:, 0, :].tolist()) # check if there is another sub contour if hierarchy[0][sub_index][0] != -1: sub_index = hierarchy[0][sub_index][0] else: subs_remaining = False # add component tuple to components only if exterior is a polygon if len(exterior) == 1: components.append(Point(exterior[0])) elif len(exterior) == 2: components.append(LineString(exterior)) elif len(exterior) > 2: polygon = Polygon(exterior, interiors) polygon = transform(polygon) if polygon.is_valid: # some polygons might be invalid components.append(polygon) else: fixed = fix_geometry(polygon) if fixed.is_valid and not fixed.is_empty: components.append(fixed) else: warn("Attempted to fix invalidity '{}' in polygon but failed... " "Output polygon still invalid '{}'".format(explain_validity(polygon), explain_validity(fixed))) # check if there is another top contour if hierarchy[0][top_index][0] != -1: top_index = hierarchy[0][top_index][0] else: tops_remaining = False del contours del hierarchy return components
def getsvggeo(node): """ Extracts and flattens all geometry from an SVG node into a list of Shapely geometry. :param node: xml.etree.ElementTree.Element :return: List of Shapely geometry :rtype: list """ kind = re.search('(?:\{.*\})?(.*)$', node.tag).group(1) geo = [] # Recurse if len(node) > 0: for child in node: subgeo = getsvggeo(child) if subgeo is not None: geo += subgeo # Parse elif kind == 'path': log.debug("***PATH***") P = parse_path(node.get('d')) P = path2shapely(P) geo = [P] elif kind == 'rect': log.debug("***RECT***") R = svgrect2shapely(node) geo = [R] elif kind == 'circle': log.debug("***CIRCLE***") C = svgcircle2shapely(node) geo = [C] elif kind == 'ellipse': log.debug("***ELLIPSE***") E = svgellipse2shapely(node) geo = [E] elif kind == 'polygon': log.debug("***POLYGON***") poly = svgpolygon2shapely(node) geo = [poly] elif kind == 'line': log.debug("***LINE***") line = svgline2shapely(node) geo = [line] elif kind == 'polyline': log.debug("***POLYLINE***") pline = svgpolyline2shapely(node) geo = [pline] else: log.warning("Unknown kind: " + kind) geo = None # Transformations if 'transform' in node.attrib: trstr = node.get('transform') trlist = parse_svg_transform(trstr) #log.debug(trlist) # Transformations are applied in reverse order for tr in trlist[::-1]: if tr[0] == 'translate': geo = [translate(geoi, tr[1], tr[2]) for geoi in geo] elif tr[0] == 'scale': geo = [scale(geoi, tr[0], tr[1], origin=(0, 0)) for geoi in geo] elif tr[0] == 'rotate': geo = [rotate(geoi, tr[1], origin=(tr[2], tr[3])) for geoi in geo] elif tr[0] == 'skew': geo = [skew(geoi, tr[1], tr[2], origin=(0, 0)) for geoi in geo] elif tr[0] == 'matrix': geo = [affine_transform(geoi, tr[1:]) for geoi in geo] else: raise Exception('Unknown transformation: %s', tr) return geo
def cov_transform(p, obst_cov): ''' Returns the convex polygon p transformed by W, where W*cov*W^T = I''' W = np.linalg.inv( np.linalg.cholesky(obst_cov) ) affine_params = np.concatenate((W.flatten(), np.zeros(2))) return affinity.affine_transform(p, affine_params), W