def enlarge_park_boundary(park_list): ''' Takes a list of parks, enlarges their boundaries and stores in a dictionary and returns it ''' polygon_dict = {} enlarged_polygon_dict = {} for park in park_list: for k in range(len(park_dict[park])): for i in range(len(park_dict[park][k])): coordiante = park_dict[park][k][i][0] polygon = Polygon(coordiante) if park not in polygon_dict.keys(): polygon_dict[park] = [polygon] else: polygon_dict[park].append(polygon) # x, y = polygon.exterior.xy # plt.figure(1) # plt.plot(x, y, 'k') enlarged_polygon = Polygon(polygon.buffer(0.0005).exterior) if park not in enlarged_polygon_dict.keys(): enlarged_polygon_dict[park] = [enlarged_polygon] else: enlarged_polygon_dict[park].append(enlarged_polygon) # x1, y1 = enlarged_polygon.exterior.xy # plt.figure(1) # plt.plot(x1, y1, 'b') # plt.show() return enlarged_polygon_dict
def _contour_to_poly(contour): poly = Polygon(contour) if not poly.is_valid: poly = poly.buffer(0) assert poly.is_valid, \ "Contour %r did not make valid polygon %s because %s" \ % (contour, poly.wkt, explain_validity(poly)) return poly
def hasCollision(line, obstacles): line_string = LineString([(line[0][0],line[0][1]),(line[1][0],line[1][1])]) for obstacle in obstacles: polygon = Polygon(obstacle) polygon_small = polygon.buffer(-.01) if line_string.intersects(polygon_small): return True return False
def buffer(self, distance=None, join_style=2): # type: (Optional[float], Optional[int]) -> Polygon2D """Returns a representation of all points within a given distance of the polygon. :param join_style: The styles of joins between offset segments: 1 (round), 2 (mitre), and 3 (bevel). """ s_poly = SPoly(self.vertices) core = s_poly.buffer(distance=distance, join_style=join_style) return Polygon2D(core.boundary.coords)
def s2polygon_from_shapely_polygon(shapely_polygon: Polygon) -> s2.S2Polygon: '''Convert a Shapely Polygon to S2Polygon. Arguments: shapely_polygon(Polygon): The Shapely Polygon to be converted to S2Polygon. Returns: The S2Polygon equivelent to the input Shapely Polygon. ''' # Filter where shape has no exterior attributes (e.g. lines). if not hasattr(shapely_polygon.buffer(0.00005), 'exterior'): return else: # Add a small buffer for cases where cover doesn't work. list_coords = list(shapely_polygon.buffer(0.00005).exterior.coords) # Get list of points. s2point_list = list(map(s2point_from_coord_xy, list_coords)) s2point_list = s2point_list[::-1] # Counterclockwise. return s2.S2Polygon(s2.S2Loop(s2point_list))
def calculate_road_geometry(self, resolution: float = 0.25, fix_eps: float = 1e-2): """ Calculate the boundary Polygon of the road. Calculates boundaries of lanes as a sub-function. Args: resolution: Sampling resolution for geometries fix_eps: If positive, then the algorithm attempts to fix sliver geometry in the map with this threshold """ if self.lanes is None or self.lanes.lane_sections == []: return self.calculate_center_lane(resolution) boundary = Polygon() for ls in self.lanes.lane_sections: start_segment = ls.center_lanes[0].reference_line sample_distances = np.linspace(0.0, ls.length, int(ls.length / resolution) + 1) previous_direction = None reference_segment = start_segment reference_widths = np.zeros_like(sample_distances) for lane in ls.all_lanes: current_direction = np.sign(lane.id) if previous_direction is None or previous_direction != current_direction: reference_segment = start_segment reference_widths = np.zeros_like(sample_distances) lane_boundary, reference_segment, segment_widths = \ lane.sample_geometry(sample_distances, start_segment, reference_segment, reference_widths) boundary = unary_union([boundary, lane_boundary]) previous_direction = current_direction reference_widths += segment_widths if fix_eps > 0.0: boundary = boundary.buffer(fix_eps, 1, join_style=JOIN_STYLE.mitre) \ .buffer(-fix_eps, 1, join_style=JOIN_STYLE.mitre) if not boundary.boundary.geom_type == "LineString": logger.warning( f"Boundary of road ID {self.id} is not a closed a loop!") self._boundary = boundary
def handlePolygons(polygon): shapelyPolygon = Polygon(polygon) # orients the polygon shapelyPolygon = orient(shapelyPolygon, -1) if not shapelyPolygon.is_valid or not shapelyPolygon.is_simple: shapelyPolygon = shapelyPolygon.buffer(0) if not isinstance(shapelyPolygon, Polygon): polygons = shapelyPolygon.geoms listOfPolygons = [] for pol in polygons: listOfPolygons.append(list(pol.exterior.coords)) return listOfPolygons else: listOfPolygons = [] if isinstance(shapelyPolygon, Polygon): try: listOfPolygons.append(list(shapelyPolygon.exterior.coords)) except AttributeError: listOfPolygons = [] return listOfPolygons
def CorrelateStitchImages(dirname, dirout, stitchchannel, chosenstitchgroup, x1lim=-.05, x2lim=1.05, y1lim=-.05, y2lim=1.05, save_stitched=True, save_multipage=True, constant_size=250000000, roll_ball=True, use_gene_name=True, save_merged=False): #dirname = os.path.expanduser('/wynton/group/ye/mtschmitz/images/MacaqueMotorCortex2/P2sagittal1_27_20200828/TR1.2020-09-03-01-35-13/') #Test params '''dirname = os.path.expanduser('/media/mt/Extreme SSD/MacaqueMotorCortex2/P2_OB_20200805/TR1.2020-08-06-23-10-18') dirout =os.path.expanduser('~/tmp/') stitchchannel='1' chosenstitchgroup='1' x1lim=0 x2lim=1 y1lim=0 y2lim=1 save_merged=False save_stitched=False save_multipage=True use_gene_name=True ''' print(dirname, flush=True) ray.shutdown() num_cpus = 1 #psutil.cpu_count(logical=False) #set number of cores to use print('cpus:', num_cpus) ray.init(num_cpus=num_cpus) x1lim = float(x1lim) x2lim = float(x2lim) y1lim = float(y1lim) y2lim = float(y2lim) chosenstitchgroup = re.sub('TR_', "1", chosenstitchgroup) chosenstitchgroup = re.sub('TR', "", chosenstitchgroup) protocol = [x for x in os.listdir(dirname) if '.scanprotocol' in x][0] minoverlap = 0 with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: #print(line) if 'MinOverlapPixel' in line: minoverlap = float(line.split('>')[1].split('<')[0]) * 1.1 except: pass n_locations = 0 counting = False with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: if 'LocationIds' in line: counting = ~counting elif counting: n_locations += 1 except: pass n_location = 1 counting = False reference = False shapes = defaultdict(list) with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: if '<d2p1:ScanLocation>' in line: counting = ~counting if counting and '<d10p1:_x>' in line: x = float(line.split('>')[1].split('<')[0]) if counting and '<d10p1:_y>' in line: y = float(line.split('>')[1].split('<')[0]) shapes[str(n_location)].append((x, y)) if '<d2p1:ReferencePoint ' in line: counting = False reference = True if reference and '<d10p1:_x>' in line: xref = float(line.split('>')[1].split('<')[0]) if reference and '<d10p1:_y>' in line: yref = float(line.split('>')[1].split('<')[0]) reference = False shapes[str(n_location)] = [ (x + xref, y + yref) for x, y in shapes[str(n_location)] ] n_location += 1 xref = 0 yref = 0 except: pass tags_to_get = [ 'SizeX', 'SizeY', 'ActualPositionX', 'ActualPositionY', 'Run Index', 'Index', '"field" Index', 'TheC', 'AreaGrid AreaGridIndex', 'Name', '<Image ID="Image:" Name', 'ActualPositionZ' ] def get_tag(x, tp): return (re.search(x + '=' + '"([A-Za-z0-9_\./\\-]*)"', tp).group(1)) @ray.remote def getTiffMetadata(f): f = open(f, 'rb') # Return Exif tags tags = exifread.process_file(f) tp = tags['Image ImageDescription'].values d = {} for tag in tags_to_get: d[tag] = get_tag(tag, tp) return (d) data = [] for fname in sorted(os.listdir(dirname)): if fname.endswith(".TIF"): fpath = os.path.join(dirname, fname) path = os.path.normpath(dirname) d = path.split(os.sep)[-2] data.append((fname, d, fpath)) imageFiles = pd.DataFrame(data, columns=['FileName', 'DirName', 'Path']) #normalize positions so starts at 0,0 #imageFiles['ActualPositionX']=imageFiles['ActualPositionX']-imageFiles['ActualPositionX'].min() #imageFiles['ActualPositionY']=imageFiles['ActualPositionY']-imageFiles['ActualPositionY'].min() imageFiles = imageFiles.loc[['_R_' in x for x in imageFiles['FileName']], :] l = [] for i in imageFiles.index: f = imageFiles.loc[i, 'Path'] #d=getTiffMetadata(f) l.append(getTiffMetadata.remote(f)) #print(d) #imageFiles.loc[i,d.keys()]=list(d.values()) metadf = pd.DataFrame(ray.get(l)) metadf.index = imageFiles.index imageFiles = imageFiles.join(metadf) ray.shutdown() imageFiles.rename(columns={'<Image ID="Image:" Name': 'Channel Name'}, inplace=True) imageFiles['ActualPositionX'] = imageFiles['ActualPositionX'].astype(float) imageFiles['ActualPositionY'] = imageFiles['ActualPositionY'].astype(float) #print(imageFiles['ActualPositionX']) #print(imageFiles['ActualPositionY']) imageFiles['SizeX'] = imageFiles['SizeX'].astype(float) imageFiles['SizeY'] = imageFiles['SizeY'].astype(float) imageFiles.sort_values(by=['"field" Index', 'Channel Name'], inplace=True) print(imageFiles, flush=True) #Max size chif = imageFiles #.loc[imageFiles['Channel Name']==stitchchannel,:] chif['x1pix'] = 0 chif['x2pix'] = 0 chif['y1pix'] = 0 chif['y2pix'] = 0 xsize = imageFiles['SizeX'].value_counts().idxmax() ysize = imageFiles['SizeY'].value_counts().idxmax() xend = len(chif.ActualPositionX.unique()) * xsize yend = len(chif.ActualPositionY.unique()) * ysize #assume adjacent images are taken sequentially xd = [] yd = [] for i in range(len(chif['"field" Index'].unique()) - 1): indi = chif['"field" Index'] == list(chif['"field" Index'])[i] indip1 = chif['"field" Index'] == list(chif['"field" Index'])[i + 1] xdiff = np.abs( list(chif.loc[indi, 'ActualPositionX'])[0] - list(chif.loc[indip1, 'ActualPositionX'])[0]) ydiff = np.abs( list(chif.loc[indi, 'ActualPositionY'])[0] - list(chif.loc[indip1, 'ActualPositionY'])[0]) xd.append(xdiff) yd.append(ydiff) xd = np.array(xd) yd = np.array(yd) #nonzero (>10) median is the distance between images xmedian = np.median(xd[xd > 10]) ymedian = np.median(yd[yd > 10]) #for reference xsize-minoverlap=xmedian print('MEDIANS') print(xmedian, ymedian) from shapely.geometry import Point from shapely.geometry.polygon import Polygon polygon = Polygon(shapes[chosenstitchgroup]) #Buffer expands, scale doesn't work for expanding linear regions with no points buffgon = Polygon(polygon.buffer(min(xmedian, ymedian)).exterior) #polygon=shapely.affinity.scale(polygon,xfact=1.2,yfact=1.2) inside = [ buffgon.contains(Point(x, y)) for x, y in list(zip(chif['ActualPositionX'], chif['ActualPositionY'])) ] matplotlib.pyplot.scatter(list(chif['ActualPositionX']), list(chif['ActualPositionY'])) matplotlib.pyplot.scatter([x[0] for x in shapes[chosenstitchgroup]], [x[1] for x in shapes[chosenstitchgroup]]) matplotlib.pyplot.scatter(buffgon.exterior.coords.xy[0], buffgon.exterior.coords.xy[1]) matplotlib.pyplot.savefig(os.path.join(dirout, 'BufferPolygon.png')) matplotlib.pyplot.close() chif = chif.loc[inside, :] #normalize positions so starts at 0,0 chif['ActualPositionX'] = chif['ActualPositionX'] - chif[ 'ActualPositionX'].min() chif['ActualPositionY'] = chif['ActualPositionY'] - chif[ 'ActualPositionY'].min() xorder = dict( zip(np.sort(chif['ActualPositionX'].unique()), np.sort(chif['ActualPositionX'].unique().argsort()))) yorder = dict( zip(np.sort(chif['ActualPositionY'].unique()), np.sort(chif['ActualPositionY'].unique().argsort()))) for i in chif.index: x = chif.loc[ i, 'ActualPositionX'] / xmedian #xorder[chif.loc[i,'ActualPositionX']] y = chif.loc[ i, 'ActualPositionY'] / ymedian #yorder[chif.loc[i,'ActualPositionY']] x1 = int((xsize * x) - (x * minoverlap)) x2 = x1 + int(xsize) y1 = int((ysize * y) - (y * minoverlap)) y2 = y1 + int(ysize) chif.loc[i, 'x1pix'] = x1 chif.loc[i, 'x2pix'] = x2 chif.loc[i, 'y1pix'] = y1 chif.loc[i, 'y2pix'] = y2 cf = chif.loc[chif['TheC'] == stitchchannel, :] cf['Image'] = None for i in tqdm.tqdm(cf.index): img = cv2.imread(cf.loc[i, 'Path'])[:, :, 0].T cf.loc[i, 'Image'] = [img] print(chif, flush=True) #print(cf.loc[2,'Image'].shape) #plt.imshow(cf.loc[2,'Image'],origin='lower') index = pynndescent.NNDescent(cf.loc[:, ['x1pix', 'y1pix']], n_neighbors=9) nn = index.query(cf.loc[:, ['x1pix', 'y1pix']], k=9)[0][:, 1:] g = networkx.DiGraph().to_undirected() for i, x in enumerate(nn): for j in x: g.add_edge(i, j) g = g.to_undirected() x1i = np.where(cf.columns == 'x1pix')[0][0] x2i = np.where(cf.columns == 'x2pix')[0][0] y1i = np.where(cf.columns == 'y1pix')[0][0] y2i = np.where(cf.columns == 'y2pix')[0][0] imgi = np.where(cf.columns == 'Image')[0][0] #could be modified with inner loop to get #average correlation of all channels #Downside of course is 4x processing time def correlateOffsets(x): xoffset, yoffset = x[0], x[1] for i in cf.index: x = cf.loc[ i, 'ActualPositionX'] / xmedian #xorder[chif.loc[i,'ActualPositionX']] y = cf.loc[ i, 'ActualPositionY'] / ymedian #yorder[chif.loc[i,'ActualPositionY']] x1 = int((xsize * x) - x * int(xoffset)) x2 = x1 + int(xsize) y1 = int((ysize * y) - y * int(yoffset)) y2 = y1 + int(ysize) cf.loc[i, 'x1pix'] = x1 cf.loc[i, 'x2pix'] = x2 cf.loc[i, 'y1pix'] = y1 cf.loc[i, 'y2pix'] = y2 i_vect = [] j_vect = [] for i, j in list(g.edges): ix1i = cf.iloc[i, x1i] iy1i = cf.iloc[i, y1i] ix2i = cf.iloc[i, x2i] iy2i = cf.iloc[i, y2i] jx1i = cf.iloc[j, x1i] jy1i = cf.iloc[j, y1i] jx2i = cf.iloc[j, x2i] jy2i = cf.iloc[j, y2i] p = Polygon([(ix1i, iy1i), (ix2i, iy1i), (ix2i, iy2i), (ix1i, iy2i)]) q = Polygon([(jx1i, jy1i), (jx2i, jy1i), (jx2i, jy2i), (jx1i, jy2i)]) if p.intersects(q): pqi = p.intersection(q) #x1,y1,x2,y2 bounds = pqi.bounds ix1b, iy1b, ix2b, iy2b = bounds[0] - ix1i, bounds[ 1] - iy1i, bounds[2] - ix2i, bounds[3] - iy2i jx1b, jy1b, jx2b, jy2b = bounds[0] - jx1i, bounds[ 1] - jy1i, bounds[2] - jx2i, bounds[3] - jy2i rxi = np.intersect1d(np.arange(ix1i, ix2i), np.arange(bounds[0], bounds[2])) - ix1i rxj = np.intersect1d(np.arange(jx1i, jx2i), np.arange(bounds[0], bounds[2])) - jx1i ryi = np.intersect1d(np.arange(iy1i, iy2i), np.arange(bounds[1], bounds[3])) - iy1i ryj = np.intersect1d(np.arange(jy1i, jy2i), np.arange(bounds[1], bounds[3])) - jy1i rxi = rxi.astype(int) rxj = rxj.astype(int) ryi = ryi.astype(int) ryj = ryj.astype(int) if len(rxi) > 0 and len(rxj) > 0: i_vect.append( list(cf.iloc[i, imgi][rxi, ryi[:, np.newaxis]].flatten())) j_vect.append( list(cf.iloc[j, imgi][rxj, ryj[:, np.newaxis]].flatten())) #plt.imshow(cf.iloc[i,imgi][rxi,ryi[:,np.newaxis]],origin='lower') #plt.show() #plt.imshow(cf.iloc[j,imgi][rxj,ryj[:,np.newaxis]],origin='lower') #plt.show() #x,y = p.exterior.xy #plt.plot(x,y) #x,y = q.exterior.xy #plt.plot(x,y) #x,y = pqi.exterior.xy #plt.plot(x,y) #plt.show() i_vect = [item for sublist in i_vect for item in sublist] j_vect = [item for sublist in j_vect for item in sublist] corr = 1 - np.corrcoef(i_vect, j_vect)[1, 0] #print(corr) return (corr) #opt=scipy.optimize.brute(correlateOffsets,(slice(30,500),slice(30,500)),full_output=True,disp=False,workers=num_cpus) opt = scipy.optimize.minimize(correlateOffsets, (minoverlap * 2.5, minoverlap * 2.5), method='Nelder-Mead', options={ 'xtol': .9, 'ftol': .05 }) chif['final_identifier'] = chif['TheC'] if use_gene_name: l = [] for x in chif['FileName']: if x.startswith('L_'): l.append('1') continue if x.startswith('R_'): l.append('2') continue if '_TR_' in x: l.append('1') continue if '_TD_' in x: l.append('1') continue if 'TR' in x or 'TD' in x: groupnum = re.sub('TR|TD', '', re.search('TD[0-9]|TR[0-9]', x).group(0)) l.append(groupnum) continue l.append(chosenstitchgroup) chif['stitchgroup'] = l tmppath = os.path.expanduser('~/imagingmetadata.csv') if os.path.exists(tmppath): refdf = pd.read_csv(tmppath, sep='\t') else: refdf = pd.read_csv( 'https://docs.google.com/spreadsheets/d/e/2PACX-1vSYbvCJpS-GfRKuGgs2IBH7MD1KtDPDqs7ePqQJ1PyrMKp7f7z7ZpY4WtMFGPxU4mWbnRHgBl4PtaeH/pub?output=tsv&gid=1520792104', sep='\t') refdf.to_csv(tmppath, sep='\t') refdf.rename(columns={ 'Channel0': '0', 'Channel1': '1', 'Channel2': '2', 'Channel3': '3' }, inplace=True) chif = pd.merge(chif, refdf, how='left', left_on=['DirName', 'stitchgroup'], right_on=['DirName', 'SlidePosition.1isL']) chif['gene'] = list( [chif.loc[chif.index[i], x] for i, x in enumerate(chif['TheC'])]) chif['final_identifier'] = chif['gene'] else: chif['final_identifier'] = chif['TheC'] xoffset = opt.x[0] yoffset = opt.x[1] #xoffset=218 #yoffset=209 for i in chif.index: x = chif.loc[ i, 'ActualPositionX'] / xmedian #xorder[chif.loc[i,'ActualPositionX']] y = chif.loc[ i, 'ActualPositionY'] / ymedian #yorder[chif.loc[i,'ActualPositionY']] x1 = int((xsize * x) - x * int(xoffset)) x2 = x1 + int(xsize) y1 = int((ysize * y) - y * int(yoffset)) y2 = y1 + int(ysize) chif.loc[i, 'x1pix'] = x1 chif.loc[i, 'x2pix'] = x2 chif.loc[i, 'y1pix'] = y1 chif.loc[i, 'y2pix'] = y2 print('before min subtract') print(chif) xmin = chif['x1pix'].min() ymin = chif['y1pix'].min() chif['x1pix'] = chif['x1pix'] - xmin chif['x2pix'] = chif['x2pix'] - xmin chif['y1pix'] = chif['y1pix'] - ymin chif['y2pix'] = chif['y2pix'] - ymin def write_stitchy(chdf, infile, keyname='FileName'): with open(infile, 'w') as the_file: the_file.write('dim = 2\n') for i in chdf.index: cur = chdf.loc[i, :] the_file.write(cur[keyname] + '; ; (' + str(cur['x1pix']) + ',' + str(cur['y1pix']) + ') \n') #for imagej merge on the fly for c in chif['final_identifier'].unique(): cf = chif.loc[chif['final_identifier'] == c, :] infile = os.path.join( dirout, str(chosenstitchgroup) + '_' + stitchchannel + '.stitchy') write_stitchy(cf, infile, keyname='FileName') print(chif) #Or write whole file if save_stitched: for c in chif['final_identifier'].unique(): cf = chif.loc[chif['final_identifier'] == c, :] cf['Image'] = None for i in cf.index: img = cv2.imread(cf.loc[i, 'Path'])[:, :, 0].T cf.loc[i, 'Image'] = [img] newimg = np.zeros( (int(np.nanmax(cf['x2pix'])), int(np.nanmax(cf['y2pix']))), np.uint8) divisor = np.zeros( (int(np.nanmax(cf['x2pix'])), int(np.nanmax(cf['y2pix']))), np.uint8) for i in cf.index: x1, x2, y1, y2 = cf.loc[i, ['x1pix', 'x2pix', 'y1pix', 'y2pix']] newimg[x1:x2, y1:y2] += cf.loc[i, 'Image'] divisor[x1:x2, y1:y2] += 1 im = np.nan_to_num(np.divide(newimg, divisor).T, nan=0).astype(np.uint8) cur_size = im.shape[0] * im.shape[1] if constant_size < cur_size: scale_percent = np.sqrt(constant_size / cur_size) # percent of original size width = int(im.shape[1] * scale_percent) height = int(im.shape[0] * scale_percent) dim = (width, height) # resize image im = cv2.resize(im, dim, interpolation=cv2.INTER_LINEAR) #from PIL import Image print('background subbing', flush=True) #import skimage #from skimage import morphology #im=im-skimage.morphology.rolling_ball(im,radius=100) #subtract_background(im,radius=100,light_bg=False) im = im.astype(np.uint16) tifffile.imsave(os.path.join(dirout, c + '_stitched.TIF'), im, compress=6) if roll_ball: RollingBallIJ(os.path.join(dirout, c + '_stitched.TIF')) print('background subbed', flush=True) ''' if save_merged: imgs={} for c in sorted(chif['final_identifier'].unique()): cf=chif.loc[chif['final_identifier']==c,:] cf['Image']=None for i in tqdm.tqdm(cf.index): img=cv2.imread(cf.loc[i,'Path'])[:,:,0].T cf.loc[i,'Image']=[img] newimg=np.zeros((int(cf['x2pix'].max()),int(cf['y2pix'].max())), np.uint8) divisor=np.zeros((int(cf['x2pix'].max()),int(cf['y2pix'].max())), np.uint8) for i in cf.index: x1,x2,y1,y2=cf.loc[i,['x1pix','x2pix','y1pix','y2pix']] newimg[x1:x2,y1:y2]+=cf.loc[i,'Image'] divisor[x1:x2,y1:y2]+=1 imgs[c]=np.nan_to_num(np.divide(newimg,divisor).T,nan=0).astype(np.uint8) tifffile.imsave(os.path.join(dirout,'merged_stitched.TIF'),list(imgs.values()),metadata={'Test':'YES,No','Value':100},compress=6) ''' if save_multipage: l = [] for f in tqdm.tqdm(cf['"field" Index'].unique()): print(f, flush=True) cf = chif.loc[chif['"field" Index'] == f, :] cf = cf.sort_values(by='final_identifier', axis=0) cf['Image'] = None for i in cf.index: img = cv2.imread(cf.loc[i, 'Path'])[:, :, 0] cf.loc[i, 'Image'] = [img] #print(cf) imgs = {} for i in cf.index: imgs[cf.loc[i, 'final_identifier']] = cf.loc[i, 'Image'] # metadata = {'channel_names': ','.join(list(imgs.keys()))} metadata.update(cf.loc[i, [ 'DirName', 'SizeX', 'SizeY', 'ActualPositionX', 'ActualPositionY', '"field" Index', 'ActualPositionZ', 'x1pix', 'y1pix' ]].astype(str).to_dict()) tifffile.imsave(os.path.join(dirout, f + '_merged.TIF'), list(imgs.values()), metadata=metadata, compress=6) l.append( [f + '_merged.TIF', cf.loc[i, 'x1pix'], cf.loc[i, 'y1pix']]) infile = os.path.join(dirout, '_'.join(list(imgs.keys())) + '_merged.stitchy') write_stitchy(pd.DataFrame(l, columns=['FileName', 'x1pix', 'y1pix']), infile, keyname='FileName')
def PatchMatch(Edges1F, gt1F, fx1F, fy1F, Edges0F, gt0F, fx0F, fy0F, MaskB0F, x_off, y_off, CV1): ps0F = 0.05 w = int(25 / ps0F) buffer = 2 * w edges1Fa = np.zeros( (Edges1F.shape[0] + buffer * 2, Edges1F.shape[1] + 2 * buffer)) edges1Fa[buffer:-buffer, buffer:-buffer] = Edges1F md = 12 if CV1 > 4: md = md / 2 elif CV1 > 1.5: md = md / 3 else: md = md / 4 max_dist = int((md) / (ps0F)) contours, hierarchy = cv2.findContours( (1 - MaskB0F).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-w) v = w while polygon.is_empty or polygon.geom_type == 'MultiPolygon' or polygon.area / ps0F < 100: v -= int(2 / ps0F) polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-v) if v != w: print("WARNING : Polygon-buffer: " + str(v * ps0F) + " < 25...") x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt(np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) CVa = np.zeros(len(grid)) x0 = np.zeros(len(grid)).astype(int) y0 = np.zeros(len(grid)).astype(int) xog = np.zeros(len(grid)).astype(int) yog = np.zeros(len(grid)).astype(int) xof = np.zeros(len(grid)).astype(int) yof = np.zeros(len(grid)).astype(int) x1 = np.zeros(len(grid)).astype(int) y1 = np.zeros(len(grid)).astype(int) origin_x = np.zeros(len(grid)) origin_y = np.zeros(len(grid)) target_lon = np.zeros(len(grid)) target_lat = np.zeros(len(grid)) RECC_total = np.zeros(Edges1F.shape) circle1 = np.zeros((2 * w, 2 * w)) for x in range(circle1.shape[0]): for y in range(circle1.shape[1]): if (x - w)**2 + (y - w)**2 < w**2: circle1[x, y] = 1 circle2 = np.zeros((2 * max_dist, 2 * max_dist)) for x in range(circle2.shape[0]): for y in range(circle2.shape[1]): if (x - max_dist)**2 + (y - max_dist)**2 < max_dist**2: circle2[x, y] = 1 circle2[circle2 == 0] = np.NaN for i in tqdm(range(len(grid)), position=0, miniters=int(len(grid) / 10), desc="RECC(f) "): x0[i] = grid[i][1] y0[i] = grid[i][0] target_lon[i] = gt0F[0] + gt0F[1] * y0[i] * fy0F target_lat[i] = gt0F[3] + gt0F[5] * x0[i] * fx0F xog[i] = int(round((target_lat[i] - gt1F[3]) / (gt1F[5] * fx1F))) yog[i] = int(round((target_lon[i] - gt1F[0]) / (gt1F[1] * fy1F))) xof[i] = int(round(xog[i] + x_off / ps0F)) yof[i] = int(round(yog[i] + y_off / ps0F)) target = Edges0F[x0[i] - w:x0[i] + w, y0[i] - w:y0[i] + w] if target.shape != (2 * w, 2 * w): continue target = target * circle1 sum_target = np.sum(target) search_wide = np.zeros((2 * (max_dist + w), 2 * (max_dist + w))) search_wide = edges1Fa[buffer + xof[i] - max_dist - w:buffer + xof[i] + max_dist + w, buffer + yof[i] - max_dist - w:buffer + yof[i] + max_dist + w] if search_wide.shape != (2 * (max_dist + w), 2 * (max_dist + w)): continue sum_patch = cv2.filter2D(search_wide, -1, circle1) numerator = cv2.filter2D(search_wide, -1, target) RECC_wide = numerator / (sum_patch + sum_target) RECC_area = RECC_wide[w:-w, w:-w] * circle2 RECC_total.fill(np.NaN) RECC_total[xof[i] - max_dist:xof[i] + max_dist, yof[i] - max_dist:yof[i] + max_dist] = RECC_area max_one = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -1)[-1] max_n = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -4 - 1)[-4 - 1] y1[i] = np.where(RECC_total >= max_one)[1][0] x1[i] = np.where(RECC_total >= max_one)[0][0] y_n = np.where(RECC_total >= max_n)[1][0:-1] x_n = np.where(RECC_total >= max_n)[0][0:-1] CVa[i] = sum( np.sqrt(np.square(x1[i] - x_n) + np.square(y1[i] - y_n))) / 4 origin_x[i] = x1[i] * fx1F origin_y[i] = y1[i] * fy1F dx = (x1 - xof) * ps0F dy = (y1 - yof) * ps0F plt.figure() plt.subplot(1, 2, 1) plt.imshow(Edges0F, cmap='gray') plt.scatter(y0, x0, c='r', s=3) plt.subplot(1, 2, 2) plt.imshow(Edges1F, cmap='gray') plt.scatter(y0, x0, c='r', s=3) plt.scatter(yog, xog, c='g', s=3) plt.scatter(yof, xof, c='b', s=3) ind = np.where(x1 != 0) plt.scatter(y1[ind], x1[ind], c='y', s=3) for i in range(len(y1)): plt.plot([y0[i], yog[i]], [x0[i], xog[i]], c='g', lw=0.5) plt.plot([yog[i], yof[i]], [xog[i], xof[i]], c='b', lw=0.5) if x1[i] != 0 and y1[i] != 0: plt.plot([yof[i], y1[i]], [xof[i], x1[i]], c='y', lw=0.5) plt.figure(7) plt.subplot(1, 2, 1) plt.imshow(Edges0F, cmap='gray') plt.subplot(1, 2, 2) plt.imshow(Edges1F, cmap='gray') plt.figure(8) plt.subplot(1, 2, 1) plt.imshow(Edges0F, cmap='gray') plt.subplot(1, 2, 2) plt.imshow(Edges1F, cmap='gray') return origin_x, origin_y, target_lon, target_lat, x0, y0, xog, yog, xof, yof, x1, y1, CVa, dx, dy
# In[81]: matplotlib.pyplot.scatter([x[0] for x in shapes['1']], [x[1] for x in shapes['1']]) outside=np.array(shapes['1'])[~np.array(contains)] matplotlib.pyplot.scatter([x[0] for x in outside], [x[1] for x in outside]) # In[82]: matplotlib.pyplot.scatter([x[0] for x in shapes['1']], [x[1] for x in shapes['1']]) matplotlib.pyplot.scatter(polygon.exterior.coords.xy[0],polygon.exterior.coords.xy[1]) buffgon = Polygon(polygon.buffer(4500.0).exterior) matplotlib.pyplot.scatter(buffgon.exterior.coords.xy[0],buffgon.exterior.coords.xy[1]) outside=np.array(shapes['1'])[~np.array(contains)] matplotlib.pyplot.scatter([x[0] for x in outside], [x[1] for x in outside]) matplotlib.pyplot.savefig('/wynton/scratch/mtschmitz/BufferPolygon.png') # In[74]: buffgon # In[75]:
# test erosion of polygon from shapely.geometry.polygon import Polygon from shapely.geometry import Polygon p = Polygon([(0, 0), (1, 1), (1, 0)]) x,y = p.boundary.xy plt.plot(x, y, color='r', alpha=0.7, linewidth=3, solid_capstyle='round', zorder=2) p2 = p.buffer(-0.2); x,y = p2.boundary.xy plt.plot(x, y, color='r', alpha=0.7, linewidth=3, solid_capstyle='round', zorder=2) b = p2.boundary; for o in b: x,y = o.xy plt.plot(x, y, color='b', alpha=0.7, linewidth=3, solid_capstyle='round', zorder=2) import numpy as np t = np.linspace(0,10,50); aline = np.vstack([t, np.sin(t)+0.5]).T; aline[0] = [0,0]; aline[-1] = [10,-0.2];
shape = [shape_2J, shape_2H] shape_2HJ = cascaded_union(shape) shape = [shape_2G, shape_2H] shape_2GH = cascaded_union(shape) shape_4R = Polygon(zip(nafo_div['4R']['lon'], nafo_div['4R']['lat'])) shape_4S = Polygon(zip(nafo_div['4S']['lon'], nafo_div['4S']['lat'])) shape_4T = Polygon(zip(nafo_div['4T']['lon'], nafo_div['4T']['lat'])) shape = [shape_4R, shape_4S] shape_4RS = cascaded_union(shape) shape = [shape_4R, shape_4S, shape_4T] shape_4RST = cascaded_union(shape) polygon4Vs = Polygon(zip(nafo_div['4Vs']['lon'], nafo_div['4Vs']['lat'])) polygon4Vn = Polygon(zip(nafo_div['4Vn']['lon'], nafo_div['4Vn']['lat'])) polygon4W = Polygon(zip(nafo_div['4W']['lon'], nafo_div['4W']['lat'])) polygon4X = Polygon(zip(nafo_div['4X']['lon'], nafo_div['4X']['lat'])) shape = [polygon4Vs.buffer(0), polygon4Vn.buffer(0), polygon4W.buffer(0), polygon4X.buffer(0)] shape_4VWX = cascaded_union(shape) shape_5Y = Polygon(zip(nafo_div['5Y']['lon'], nafo_div['5Y']['lat'])) dict_stats_3LNO = {} dict_stats_3M = {} dict_stats_3Ps = {} dict_stats_3K = {} dict_stats_3L = {} dict_stats_3O = {} dict_stats_2J = {} dict_stats_2HJ = {} dict_stats_2GH = {} dict_stats_4R = {} dict_stats_4S = {}
def main(): parser = _argparser() args = parser.parse_args() schema = { 'properties': [('filename', 'str'), ('path', 'str')], 'geometry': 'Polygon' } if args.out_srs is not None: out_crs = fiona.crs.from_epsg(args.out_srs) else: out_crs = fiona.crs.from_epsg(4326) outshape = fiona.open(args.outshape, 'w', crs=out_crs, driver='ESRI Shapefile', schema=schema) if args.processed: flist = glob.glob('AST*/*.zip.met') + glob.glob('AST*/zips/*.zip.met') else: flist = glob.glob('*.zip.met') for mfile in flist: imgpath = os.path.abspath(mfile) dirpath = os.path.dirname(imgpath) clean = [line.strip() for line in open(mfile).read().split('\n')] if os.path.sep in mfile: mfile = mfile.split(os.path.sep)[-1] latinds = [ i for i, line in enumerate(clean) if 'GRingPointLatitude' in line ] loninds = [ i for i, line in enumerate(clean) if 'GRingPointLongitude' in line ] latlines = clean[latinds[0]:latinds[1] + 1] lonlines = clean[loninds[0]:loninds[1] + 1] lonvalstr = lonlines[2] latvalstr = latlines[2] lats = [float(val) for val in latvalstr.strip('VALUE =()').split(',')] lons = [float(val) for val in lonvalstr.strip('VALUE =()').split(',')] coords = zip(lons, lats) footprint = Polygon(coords) if args.out_srs is not None: footprint = reproject_geometry(footprint, 4326, args.out_srs) footprint = footprint.buffer(args.buffer) outshape.write({ 'properties': { 'filename': mfile, 'path': dirpath }, 'geometry': mapping(footprint) }) outshape.close()
def PatchMatch(ps2, w, md, edges1F, gt, fx_F, fy_F, edges0F, gt_0, fx_F0, fy_F0, contour_F0, x_offset, y_offset, CV1): w = int(w / ps2) buffer = 2 * w edges1Fa = np.zeros( (edges1F.shape[0] + buffer * 2, edges1F.shape[1] + 2 * buffer)) edges1Fa[buffer:-buffer, buffer:-buffer] = edges1F if CV1 > 4: md = md / 2 elif CV1 > 1.5: md = md / 3 else: md = md / 4 max_dist = int((md) / (ps2)) contours, hierarchy = cv2.findContours((1 - contour_F0).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-w) v = w while polygon.is_empty or polygon.geom_type == 'MultiPolygon' or polygon.area / ps2 < 100: v -= int(2 / ps2) polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-v) if v != w: print("WARNING : Polygon-buffer: " + str(v) + " < w...") x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt(np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) cv = np.zeros(len(grid)) dist_lon = np.zeros(len(grid)) dist_lat = np.zeros(len(grid)) origin_x = np.zeros(len(grid)) origin_y = np.zeros(len(grid)) target_lon = np.zeros(len(grid)) target_lat = np.zeros(len(grid)) o_x = np.zeros(len(grid)) o_y = np.zeros(len(grid)) t_x = np.zeros(len(grid)) t_y = np.zeros(len(grid)) dx = np.zeros(len(grid)) dy = np.zeros(len(grid)) RECC_total = np.zeros(edges1Fa.shape) RECC_over = np.zeros(edges1Fa.shape) RECC_over.fill(np.NaN) circle1 = np.zeros((2 * w, 2 * w)) for x in range(circle1.shape[0]): for y in range(circle1.shape[1]): if (x - w)**2 + (y - w)**2 < w**2: circle1[x, y] = 1 circle2 = np.zeros((2 * max_dist, 2 * max_dist)) for x in range(circle2.shape[0]): for y in range(circle2.shape[1]): if (x - max_dist)**2 + (y - max_dist)**2 < max_dist**2: circle2[x, y] = 1 circle2[circle2 == 0] = np.NaN for i in tqdm(range(len(grid)), position=0, miniters=int(len(grid) / 10), desc="RECC "): x_i_0 = grid[i][1] y_i_0 = grid[i][0] target = edges0F[x_i_0 - w:x_i_0 + w, y_i_0 - w:y_i_0 + w] if target.shape != (2 * w, 2 * w): continue target = target * circle1 sum_target = np.sum(target) lat_0 = gt_0[3] + gt_0[5] * x_i_0 * fx_F0 lon_0 = gt_0[0] + gt_0[1] * y_i_0 * fy_F0 x_i_0_og = int( round((lat_0 - gt[3]) / (gt[5] * fx_F) + (x_offset / ps2))) y_i_0_og = int( round((lon_0 - gt[0]) / (gt[1] * fy_F) + (y_offset / ps2))) search_wide = np.zeros((2 * (max_dist + w), 2 * (max_dist + w))) search_wide = edges1Fa[buffer + x_i_0_og - max_dist - w:buffer + x_i_0_og + max_dist + w, buffer + y_i_0_og - max_dist - w:buffer + y_i_0_og + max_dist + w] if search_wide.shape != (2 * (max_dist + w), 2 * (max_dist + w)): continue sum_patch = cv2.filter2D(search_wide, -1, circle1) numerator = cv2.filter2D(search_wide, -1, target) RECC_wide = numerator / (sum_patch + sum_target) RECC_area = RECC_wide[w:-w, w:-w] * circle2 RECC_total.fill(np.NaN) RECC_total[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist] = RECC_area if np.nansum(RECC_over[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist]) == 0: RECC_over[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist] = RECC_area max_one = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -1)[-1] max_n = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -4 - 1)[-4 - 1] y_i = np.where(RECC_total >= max_one)[1][0] x_i = np.where(RECC_total >= max_one)[0][0] y_n = np.where(RECC_total >= max_n)[1][0:-1] x_n = np.where(RECC_total >= max_n)[0][0:-1] cv[i] = sum(np.sqrt(np.square(x_i - x_n) + np.square(y_i - y_n))) / 4 lon = gt[0] + gt[1] * y_i * fy_F + gt[2] * x_i * fx_F lat = gt[3] + gt[4] * y_i * fy_F + gt[5] * x_i * fx_F lon_0 = gt_0[0] + gt_0[1] * y_i_0 * fy_F0 + gt_0[2] * x_i_0 * fx_F0 lat_0 = gt_0[3] + gt_0[4] * y_i_0 * fy_F0 + gt_0[5] * x_i_0 * fx_F0 dist_lon[i] = lon_0 - lon dist_lat[i] = lat_0 - lat o_x[i] = x_i o_y[i] = y_i t_x[i] = x_i_0 t_y[i] = y_i_0 dx[i] = (x_i - x_i_0_og) * ps2 dy[i] = (y_i - y_i_0_og) * ps2 # For referencing: origin_x[i] = x_i * fx_F origin_y[i] = y_i * fy_F target_lon[i] = lon_0 target_lat[i] = lat_0 return origin_x, origin_y, target_lon, target_lat, o_x, o_y, t_x, t_y, cv, dx, dy
from shapely.geometry.polygon import Polygon from shapely.geometry import Polygon p = Polygon([(0, 0), (1, 1), (1, 0)]) x, y = p.boundary.xy plt.plot(x, y, color='r', alpha=0.7, linewidth=3, solid_capstyle='round', zorder=2) p2 = p.buffer(-0.2) x, y = p2.boundary.xy plt.plot(x, y, color='r', alpha=0.7, linewidth=3, solid_capstyle='round', zorder=2) b = p2.boundary for o in b: x, y = o.xy plt.plot(x, y,
def extendAllMergedLines(dirPathLines, vectorMask, epsgValue): """ extendAllMergedLines. :param dirPathLines: (text) path :param vectorMask: (text) path :param epsgValue: (text) epsg value :returns: OpenCV version. """ crsEpsgId = {'init': 'epsg:' + str(epsgValue)} crutils.printLogMsg(crglobals.OK_MSG + 'Path Lines: %s' % (dirPathLines)) crutils.printLogMsg(crglobals.OK_MSG + 'Mask: %s' % (vectorMask)) crutils.printLogMsg(crglobals.OK_MSG + 'EPSG: %s' % (epsgValue)) #input merged line file fileNameMergedLines = 'merged_lines.shp' mergedLinesGeoDataFrame = gpd.GeoDataFrame.from_file( os.path.join( dirPathLines, fileNameMergedLines)) #dirPathLines+'/'+fileNameMergedLines) #input mask polygon file boundsMaskGeoDataFrame = gpd.GeoDataFrame.from_file(vectorMask) longLinesArray = [] idLongLinesArray = [] for x in range(0, len(mergedLinesGeoDataFrame.geometry)): linea_bx = (list(mergedLinesGeoDataFrame.geometry[x].coords)) extrapoledLine = getExtrapoledLine(*linea_bx[-2:]) idLongLinesArray.append(x) longLinesArray.append(extrapoledLine) dataFrameLongLines = pd.DataFrame({'id': idLongLinesArray}) longLinesGeoDataFrame = gpd.GeoDataFrame(dataFrameLongLines, crs=crsEpsgId, geometry=longLinesArray) longLinesFileName = os.path.join( dirPathLines, 'merged_lines_long.shp') #dirPathLines+'/'+'merged_lines_long.shp' longLinesGeoDataFrame.to_file(driver='ESRI Shapefile', filename=longLinesFileName) crutils.printLogMsg(crglobals.DONE_MSG + 'Generated long lines !') ####################################################################################### #Get the convex hull lines convexHullFromBoundsMask = boundsMaskGeoDataFrame.convex_hull.iloc[0] x, y = convexHullFromBoundsMask.exterior.xy pointsConvexHullFromBoundsMaskArray = np.array(list(zip(x, y))) minBBoxRect = imboundrect.minimum_bounding_rectangle( pointsConvexHullFromBoundsMaskArray) polygonOMBB = Polygon( [minBBoxRect[0], minBBoxRect[1], minBBoxRect[2], minBBoxRect[3]]) ####################################################################################### #cut lines by ombb #update applying buffer. it fix some strange bug at some corner lines geoDataFrameLineCuttedByBoxBuffer = (longLinesGeoDataFrame.intersection( polygonOMBB.buffer(20))) dataFrameLineCuttedByBoxDf = pd.DataFrame({ 'id': idLongLinesArray, 'len': geoDataFrameLineCuttedByBoxBuffer.length }) geoDataFrameLinesCuttedByBox = gpd.GeoDataFrame( dataFrameLineCuttedByBoxDf, crs=crsEpsgId, geometry=geoDataFrameLineCuttedByBoxBuffer) mergedLinesCuttedByOMBBPolygonFile = os.path.join( dirPathLines, 'merged_lines_long_cut_ombb.shp' ) #dirPathLines+'/'+'merged_lines_long_cut_ombb.shp' geoDataFrameLinesCuttedByBox.to_file( driver='ESRI Shapefile', filename=mergedLinesCuttedByOMBBPolygonFile) crutils.printLogMsg(crglobals.DONE_MSG + 'Cut long lines by OMBB bounds !') ####################################################################################### projectDistance = 1 #enumerate lines in spatial order angle = crutils.getAzimuth( (geoDataFrameLinesCuttedByBox.geometry[0].coords[0][0]), (geoDataFrameLinesCuttedByBox.geometry[0].coords[0][1]), (geoDataFrameLinesCuttedByBox.geometry[0].coords[1][0]), (geoDataFrameLinesCuttedByBox.geometry[0].coords[1][1])) anglep = (angle + 270) #search for the closest geometry line to temporal point temporalXpoint = (geoDataFrameLinesCuttedByBox.geometry[0].centroid.x ) + np.sin(np.deg2rad(anglep)) * 5000 temporalYpoint = (geoDataFrameLinesCuttedByBox.geometry[0].centroid.y ) + np.cos(np.deg2rad(anglep)) * 5000 temporalExternalPoint = Point((temporalXpoint, temporalYpoint)) crutils.printLogMsg(crglobals.DONE_MSG + 'Generate a Temporal Point') #print(temporalExternalPoint) tmpLineDistance = [] for i in range(len(geoDataFrameLinesCuttedByBox)): distanceCalculated = (temporalExternalPoint.distance( geoDataFrameLinesCuttedByBox.geometry[i].centroid)) tmpLineDistance.append(distanceCalculated) #print("i: %s -> distanceCalculated: %s -> %s" % (str(i), str(distanceCalculated) , str(geoDataFrameLinesCuttedByBox.geometry[i]) )) minelem = np.argmin(tmpLineDistance) crutils.printLogMsg(crglobals.DONE_MSG + "Found a closest line id: %s" % (str(minelem))) ####################################################################################### #Calc Distances using the closest line found xp = (geoDataFrameLinesCuttedByBox.geometry[minelem].centroid.x) + np.sin( np.deg2rad(anglep)) * projectDistance yp = (geoDataFrameLinesCuttedByBox.geometry[minelem].centroid.y) + np.cos( np.deg2rad(anglep)) * projectDistance externalPoint = Point((xp, yp)) #print(externalPoint) geoDistance = [] index = [] for i in range(len(geoDataFrameLinesCuttedByBox)): #print('-> %s' % ( str( i))) distanceCalculated = (externalPoint.distance( geoDataFrameLinesCuttedByBox.geometry[i].centroid)) geoDistance.append(distanceCalculated) #print(distanceCalculated) index.append(i) dataFrameLineCuttedByBoxBuffer = pd.DataFrame({ 'len': geoDataFrameLineCuttedByBoxBuffer.length, 'geo_dist': geoDistance, 'idx': index }) geoDataFrameLinesCuttedByBox = gpd.GeoDataFrame( dataFrameLineCuttedByBoxBuffer, crs=crsEpsgId, geometry=geoDataFrameLineCuttedByBoxBuffer) mergedLongLinesCuttedByOMBwDistFileName = os.path.join( dirPathLines, 'merged_lines_long_cut_ombb_wdist.shp' ) #dirPathLines+'/'+'merged_lines_long_cut_ombb_wdist.shp' geoDataFrameLinesCuttedByBox.to_file( driver='ESRI Shapefile', filename=mergedLongLinesCuttedByOMBwDistFileName) ####################################################################################### ####################################################################################### ############## FILTERING LINES LOOKING FOR CANDIDATES ################################# ####################################################################################### ####################################################################################### sortedDistance = np.argsort(geoDistance).astype('int') idByGeo = [x for _, x in sorted(zip(sortedDistance, index))] newObjDistancesSorted = np.sort(geoDistance) #Removing Adjacents and lines duplicates newObjDistancesSorted = crutils.removeAdjacentsInArray( newObjDistancesSorted) #print('====== new distances sorted =====') #print(newObjDistancesSorted) crutils.printLogMsg(crglobals.DONE_MSG + 'Candidate lines: %s ' % str(len(newObjDistancesSorted))) ##Removing Closing Lines #pairsdistances = zip([0]+newObjDistancesSorted, newObjDistancesSorted) #TODO: distancesFiltered #distancesFiltered = [pair[1] for pair in pairsdistances if abs(pair[0]-pair[1]) >=0.5 ] ########################################### ## OTRO APPROACH TO FIND DISTANCES groups, current_group, first = [], [], newObjDistancesSorted[0] for item in newObjDistancesSorted: # Check if this element falls under the current group if item - first <= 1.3: current_group.append(item) else: # If it doesn't, create a new group and add old to the result groups.append(current_group[:]) current_group, first = [item], item # Add the last group which was being gathered to the result groups.append(current_group[:]) distancesFiltered = [np.max(item) for item in groups] #iter 1 removing proximal lines pairsdistances2 = zip([0] + distancesFiltered, distancesFiltered) distancesFiltered = [ pair[1] for pair in pairsdistances2 if abs(pair[0] - pair[1]) >= 0.4 ] #iter 2 removing proximal lines pairsdistances3 = zip([0] + distancesFiltered, distancesFiltered) distancesFiltered = [ pair[1] for pair in pairsdistances3 if abs(pair[0] - pair[1]) >= 0.9 ] #>=0.8 -preff: 0.9 ######################################3 #print('====== distances filtered =====') #print(distancesFiltered) crutils.printLogMsg(crglobals.DONE_MSG + 'Resulting lines: %s ' % str(len(distancesFiltered))) #TODO: final #cut final lines by mask dataFrameCandidateLines = (geoDataFrameLinesCuttedByBox.intersection( boundsMaskGeoDataFrame.geometry.iloc[0])) candidateLinesFileName = os.path.join( dirPathLines, 'candidate_lines.shp') #dirPathLines+'/'+'candidate_lines.shp' dataFrameLineCuttedByMask = pd.DataFrame({ 'distance': dataFrameCandidateLines.length, 'geo_dist': geoDistance, 'idx': index }) geoDataFrameLineCuttedByMask = gpd.GeoDataFrame( dataFrameLineCuttedByMask, crs=crsEpsgId, geometry=dataFrameCandidateLines) geoDataFrameLineCuttedByMask.to_file(driver='ESRI Shapefile', filename=candidateLinesFileName) ##################################### ## NEW CROPROWS - GEOMETRY SEARCH ##################################### #save candidateLinesbuffer candidateLinesBufferFileName = os.path.join(dirPathLines, 'candidate_lines_buffer.shp') candidateLinesBuffer = geoDataFrameLineCuttedByMask.buffer(0.3) s = candidateLinesBuffer #ADDING FEATURE 3-9-2018 #DISOLVE OVERLAPPING BUFFER POLYGONS #https://gis.stackexchange.com/questions/271733/geopandas-dissolve-overlapping-polygons/271735 overlap_matrix = s.apply(lambda x: s.overlaps(x)).values.astype(int) n, ids = connected_components(overlap_matrix) df = gpd.GeoDataFrame({'geometry': s, 'group': ids}, crs=crsEpsgId) res = df.dissolve(by='group') res.to_file(driver='ESRI Shapefile', filename=candidateLinesBufferFileName) candidateLinesBufferCentroidFileName = os.path.join( dirPathLines, 'candidate_lines_buffer_centroid.shp') points = res.copy() points.geometry = res['geometry'].centroid points.crs = res.crs points.head() points.to_file(driver='ESRI Shapefile', filename=candidateLinesBufferCentroidFileName) df_lines = dataFrameCandidateLines.geometry df_points = points.geometry #print(len(df_points)) #print(len(df_lines)) idClosestLineArr = [] #find the closest candidate line to point for x in range(0, len(df_points)): minDistancePointLine = df_lines.distance(df_points[x]).min() allDistanceToLines = df_lines.distance(df_points[x]) idClosestLine = np.where(allDistanceToLines == minDistancePointLine)[0] idClosestLineArr.append(idClosestLine[0]) #print('centroid point: %s - id closest line: ' % (str(x)) , (str(idClosestLine)) ) #print(idClosestLineArr) selcr = [] for x in range(0, len(df_lines)): selcr = df_lines[idClosestLineArr] crf = 0 geoidcr = [] croprowLength = [] for y in range(0, len(selcr)): #print(selcr.geometry.iloc[y]) #print(selcr.geometry.iloc[y].length) croprowLength.append(selcr.geometry.iloc[y].length) geoidcr.append(crf) crf = crf + 1 dataFrameCr = pd.DataFrame({ 'geometry': selcr, 'crlen': croprowLength, 'idg': geoidcr, 'crg': 'Generated by Crop Rows Generator v1' }) geoDataFrameCropRows = gpd.GeoDataFrame(dataFrameCr, crs=crsEpsgId) cropRowsFileNameByGeom = os.path.join(dirPathLines, 'croprows_lines.shp') geoDataFrameCropRows.to_file(driver='ESRI Shapefile', filename=str(cropRowsFileNameByGeom)) ##EXPORT CROP ROWS RESULTS TO WGS84 SHP AND KML FORMATS crsExportID = {'init': 'epsg:' + str(crglobals.EXPORT_EPSG)} exportCropRowsShapeFile = os.path.join( os.path.dirname(os.path.dirname(dirPathLines)), crglobals.EXPORTDIR, 'croprows_wgs84.shp') geoDataFrameCropRowsWGS84 = gpd.GeoDataFrame(dataFrameCr, crs=crsEpsgId) geoDataFrameCropRowsWGS84 = geoDataFrameCropRowsWGS84.to_crs(crsExportID) geoDataFrameCropRowsWGS84.to_file(driver='ESRI Shapefile', filename=str(exportCropRowsShapeFile)) exportCropRowsShapeFileKML = os.path.join( os.path.dirname(os.path.dirname(dirPathLines)), crglobals.EXPORTDIR, 'croprows_wgs84.kml') geoDataFrameCropRowsWGS84.to_file(driver='kml', filename=str(exportCropRowsShapeFileKML)) crutils.printLogMsg( crglobals.DONE_MSG + 'Exported Resulting Crop Rows to KML and SHP format in WGS84 CRS') cropRowsBufferFileName = os.path.join(dirPathLines, 'croprows_lines_buffer.shp') cropRowsLinesBuffer = geoDataFrameCropRows.buffer(0.3) cropRowsLinesBufferGeoData = gpd.GeoDataFrame(crs=crsEpsgId, geometry=cropRowsLinesBuffer) cropRowsLinesBufferGeoData.to_file(driver='ESRI Shapefile', filename=str(cropRowsBufferFileName)) ##################################### ## OLD CROPROWS - STAT SEARCH ##################################### getIndexes = lambda x, xs: [ i for (y, i) in zip(xs, range(len(xs))) if x == y ] cuttedLineArray = [] #look for k = [] flagCounter3 = 0 for x in distancesFiltered: #print(distancesFiltered[i]) #print(getIndexes(distancesFiltered[i],newobjdistances)) k.append(getIndexes(distancesFiltered[flagCounter3], geoDistance)[0]) flagCounter3 = flagCounter3 + 1 #Reindex lines filtered index2 = [] flagCounter2 = 0 m = [] j = 0 croprowLength = [] for x in k: m.append(dataFrameCandidateLines[k[j]]) index2.append(flagCounter2) #line len for each geometry croprowLength.append(m[j].length) flagCounter2 += 1 j = j + 1 #print('index2:') #print(index2) #print('k') #print(k) #print('m') #print(m) sortdistance2 = np.argsort(distancesFiltered).astype('int') idByGeo2 = [x for _, x in sorted(zip(sortdistance2, index2))] #print('idByGeo2') #print(idByGeo2) crutils.printLogMsg(crglobals.DONE_MSG + 'Re-indexing candidate lines !') #Fix distances substracting projectDistance arrayDistances = np.array(distancesFiltered) #fixdist = arrayDistances - projectDistance crutils.printLogMsg(crglobals.DONE_MSG + 'Distances fixed !') #print(croprowLength) #fixdist dataFrameFixedLines = pd.DataFrame({ 'id': k, 'geo_dist': arrayDistances, 'idgeo': idByGeo2, 'crlen': croprowLength }) #dataFrameFixedLines = pd.DataFrame({ }) geoDataFrameFixedLines = gpd.GeoDataFrame(dataFrameFixedLines, crs=crsEpsgId, geometry=m) geoDataFrameFixedLines.dropna() crutils.printLogMsg(crglobals.DONE_MSG + 'Result lines generated !') cropRowsLinesFileName = os.path.join(dirPathLines, 'croprows_lines_stat.shp') geoDataFrameFixedLines.to_file(driver='ESRI Shapefile', filename=str(cropRowsLinesFileName)) crutils.printLogMsg(crglobals.DONE_MSG + 'Writing file with resulting lines : %s ' % (cropRowsLinesFileName)) #saveResultXMLFile(cropRowsLinesFileName) resultingFiles = [ cropRowsFileNameByGeom, cropRowsBufferFileName, exportCropRowsShapeFile, exportCropRowsShapeFileKML, str(epsgValue), str(len(newObjDistancesSorted)), str(len(distancesFiltered)), vectorMask ] saveResultXMLFile(resultingFiles) #saveResultXMLFile(cropRowsFileNameByGeom,cropRowsBufferFileName,exportCropRowsShapeFile,exportCropRowsShapeFileKML) ##################################### return 1
def init_match(ps1, w, md, edges1C, gt, fx_C, fy_C, xb_C, yb_C, edges0C, gt_0, fx_C0, fy_C0, xb_C0, yb_C0, mask_b_C0): w = int(w / ps1) buffer = 2 * w edges1Ca = np.zeros( (edges1C.shape[0] + buffer * 2, edges1C.shape[1] + 2 * buffer)) edges1Ca[buffer:-buffer, buffer:-buffer] = edges1C max_dist = int((md) / ps1) contours, hierarchy = cv2.findContours((1 - mask_b_C0).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-w) v = w while polygon.is_empty or polygon.geom_type == 'MultiPolygon' or polygon.area / ps1 < 100: v -= int(2 / ps1) polygon = Polygon(np.array(biggest_contour[:, 0])) polygon = polygon.buffer(-v) if v != w: print("WARNING : Polygon-buffer: " + str(v * ps1) + " < w...") x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt(np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) x_offset = [] y_offset = [] o_x = np.zeros(len(grid)) o_y = np.zeros(len(grid)) t_x = np.zeros(len(grid)) t_y = np.zeros(len(grid)) cv = np.zeros(len(grid)) RECC_total = np.zeros(edges1Ca.shape) RECC_over = np.zeros(edges1Ca.shape) RECC_over.fill(np.NaN) circle1 = np.zeros((2 * w, 2 * w)) for x in range(circle1.shape[0]): for y in range(circle1.shape[1]): if (x - w)**2 + (y - w)**2 < w**2: circle1[x, y] = 1 circle2 = np.zeros((2 * max_dist, 2 * max_dist)) for x in range(circle2.shape[0]): for y in range(circle2.shape[1]): if (x - max_dist)**2 + (y - max_dist)**2 < max_dist**2: circle2[x, y] = 1 circle2[circle2 == 0] = np.NaN for i in tqdm(range(len(grid)), position=0, miniters=int(len(grid) / 10), desc="RECC "): x_i_0 = grid[i][1] y_i_0 = grid[i][0] target = edges0C[x_i_0 - w:x_i_0 + w, y_i_0 - w:y_i_0 + w] * circle1 if target.shape != (2 * w, 2 * w): continue sum_target = np.sum(target) lat_0 = gt_0[3] + gt_0[5] * x_i_0 * fx_C0 lon_0 = gt_0[0] + gt_0[1] * y_i_0 * fy_C0 x_i_0_og = int(round((lat_0 - gt[3]) / (gt[5] * fx_C))) y_i_0_og = int(round((lon_0 - gt[0]) / (gt[1] * fy_C))) search_wide = np.zeros((2 * (max_dist + w), 2 * (max_dist + w))) search_wide = edges1Ca[buffer + x_i_0_og - max_dist - w:buffer + x_i_0_og + max_dist + w, buffer + y_i_0_og - max_dist - w:buffer + y_i_0_og + max_dist + w] if search_wide.shape != (2 * (max_dist + w), 2 * (max_dist + w)): continue sum_patch = cv2.filter2D(search_wide, -1, circle1) numerator = cv2.filter2D(search_wide, -1, target) RECC_wide = numerator / (sum_patch + sum_target) RECC_area = RECC_wide[w:-w, w:-w] * circle2 RECC_total.fill(np.NaN) RECC_total[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist] = RECC_area if np.nansum(RECC_over[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist]) == 0: RECC_over[x_i_0_og - max_dist:x_i_0_og + max_dist, y_i_0_og - max_dist:y_i_0_og + max_dist] = RECC_area max_one = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -1)[-1] max_n = np.partition(RECC_total[~np.isnan(RECC_total)].flatten(), -4 - 1)[-4 - 1] y_i = np.where(RECC_total >= max_one)[1][0] x_i = np.where(RECC_total >= max_one)[0][0] y_n = np.where(RECC_total >= max_n)[1][0:-1] x_n = np.where(RECC_total >= max_n)[0][0:-1] cv[i] = sum(np.sqrt(np.square(x_i - x_n) + np.square(y_i - y_n))) / 4 x_offset.append(x_i - x_i_0_og) y_offset.append(y_i - y_i_0_og) o_x[i] = x_i o_y[i] = y_i t_x[i] = x_i_0 t_y[i] = y_i_0 x_offset = np.array(x_offset) y_offset = np.array(y_offset) a, b, c = np.histogram2d(x_offset[cv < 4], y_offset[cv < 4], bins=len(x_offset)) d, e = np.where(a == np.max(a)) if len(d) > 1: i = [0, 0] binnnn = len(x_offset) / 10 while len(i) > 1: binnnn -= 1 f, g, h = np.histogram2d(x_offset[cv < 4], y_offset[cv < 4], bins=binnnn) i, j = np.where(f == np.max(f)) diff = (b[d] - g[i])**2 + (c[e] - h[j])**2 ind = np.where(diff == np.min(diff))[0] d = d[ind] e = e[ind] x_offset = (b[d] + b[d + 1]) / 2 y_offset = (c[e] + c[e + 1]) / 2 x_offset = x_offset[0] * ps1 y_offset = y_offset[0] * ps1 o_x = o_x[cv < 4] o_y = o_y[cv < 4] t_x = t_x[cv < 4] t_y = t_y[cv < 4] return x_offset, y_offset, o_x, o_y, t_x, t_y
def ImageJStitchImages(dirname, dirout, stitchchannel, chosenstitchgroup, x1lim, x2lim, y1lim, y2lim, minmax_displace, abs_displace): ray.shutdown() num_cpus = 1 #psutil.cpu_count(logical=False) #set number of cores to use print('cpus:', num_cpus) ray.init(num_cpus=num_cpus) x1lim = float(x1lim) x2lim = float(x2lim) y1lim = float(y1lim) y2lim = float(y2lim) chosenstitchgroup = re.sub('TR_', "1", chosenstitchgroup) chosenstitchgroup = re.sub('TR', "", chosenstitchgroup) protocol = [x for x in os.listdir(dirname) if '.scanprotocol' in x][0] minoverlap = 0 with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: #print(line) if 'MinOverlapPixel' in line: minoverlap = float(line.split('>')[1].split('<')[0]) * 1.1 except: pass n_locations = 0 counting = False with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: if 'LocationIds' in line: counting = ~counting elif counting: n_locations += 1 except: pass n_location = 1 counting = False reference = False shapes = defaultdict(list) with open(os.path.join(dirname, protocol), 'r') as f: for line in f: try: if '<d2p1:ScanLocation>' in line: counting = ~counting if counting and '<d10p1:_x>' in line: x = float(line.split('>')[1].split('<')[0]) if counting and '<d10p1:_y>' in line: y = float(line.split('>')[1].split('<')[0]) shapes[str(n_location)].append((x, y)) if '<d2p1:ReferencePoint ' in line: counting = False reference = True if reference and '<d10p1:_x>' in line: xref = float(line.split('>')[1].split('<')[0]) if reference and '<d10p1:_y>' in line: yref = float(line.split('>')[1].split('<')[0]) reference = False shapes[str(n_location)] = [ (x + xref, y + yref) for x, y in shapes[str(n_location)] ] n_location += 1 xref = 0 yref = 0 except: pass print(shapes) outline = mpltPath.Path(shapes[chosenstitchgroup]) print(outline) outline = outline.transformed(matplotlib.transforms.Affine2D().scale(1.2)) print(outline) tags_to_get = [ 'SizeX', 'SizeY', 'ActualPositionX', 'ActualPositionY', 'Run Index', 'Index', '"field" Index', 'AreaGrid AreaGridIndex', 'Name', '<Image ID="Image:" Name', 'ActualPositionZ' ] def get_tag(x, tp): return (re.search(x + '=' + '"([A-Za-z0-9_\./\\-]*)"', tp).group(1)) @ray.remote def getTiffMetadata(f): f = open(f, 'rb') # Return Exif tags tags = exifread.process_file(f) tp = tags['Image ImageDescription'].values d = {} for tag in tags_to_get: d[tag] = get_tag(tag, tp) return (d) data = [] for fname in sorted(os.listdir(dirname)): if fname.endswith(".TIF"): fpath = os.path.join(dirname, fname) path = os.path.normpath(dirname) d = path.split(os.sep)[-2] data.append((fname, d, fpath)) imageFiles = pd.DataFrame(data, columns=['FileName', 'DirName', 'Path']) #normalize positions so starts at 0,0 #imageFiles['ActualPositionX']=imageFiles['ActualPositionX']-imageFiles['ActualPositionX'].min() #imageFiles['ActualPositionY']=imageFiles['ActualPositionY']-imageFiles['ActualPositionY'].min() imageFiles = imageFiles.loc[['_R_' in x for x in imageFiles['FileName']], :] l = [] for i in imageFiles.index: f = imageFiles.loc[i, 'Path'] #d=getTiffMetadata(f) l.append(getTiffMetadata.remote(f)) #print(d) #imageFiles.loc[i,d.keys()]=list(d.values()) metadf = pd.DataFrame(ray.get(l)) metadf.index = imageFiles.index imageFiles = imageFiles.join(metadf) ray.shutdown() imageFiles.rename(columns={'<Image ID="Image:" Name': 'Channel Name'}, inplace=True) imageFiles['ActualPositionX'] = imageFiles['ActualPositionX'].astype(float) imageFiles['ActualPositionY'] = imageFiles['ActualPositionY'].astype(float) print(imageFiles['ActualPositionX']) print(imageFiles['ActualPositionY']) imageFiles['SizeX'] = imageFiles['SizeX'].astype(float) imageFiles['SizeY'] = imageFiles['SizeY'].astype(float) imageFiles.sort_values(by=['"field" Index', 'Channel Name'], inplace=True) #Max size chif = imageFiles.loc[imageFiles['Channel Name'] == stitchchannel, :] chif['x1pix'] = 0 chif['x2pix'] = 0 chif['y1pix'] = 0 chif['y2pix'] = 0 xsize = imageFiles['SizeX'].value_counts().idxmax() ysize = imageFiles['SizeY'].value_counts().idxmax() xend = len(chif.ActualPositionX.unique()) * xsize yend = len(chif.ActualPositionY.unique()) * ysize #assume adjacent images are taken sequentially xd = [] yd = [] for i in range(len(chif['"field" Index'].unique()) - 1): indi = chif['"field" Index'] == list(chif['"field" Index'])[i] indip1 = chif['"field" Index'] == list(chif['"field" Index'])[i + 1] xdiff = np.abs( list(chif.loc[indi, 'ActualPositionX'])[0] - list(chif.loc[indip1, 'ActualPositionX'])[0]) ydiff = np.abs( list(chif.loc[indi, 'ActualPositionY'])[0] - list(chif.loc[indip1, 'ActualPositionY'])[0]) xd.append(xdiff) yd.append(ydiff) xd = np.array(xd) yd = np.array(yd) #nonzero median is the distance between images xmedian = np.median(xd[xd > 5]) ymedian = np.median(yd[yd > 5]) #for reference xsize-minoverlap=xmedian print('MEDIANS') print(xmedian, ymedian) import shapely from shapely.geometry import Point from shapely.geometry.polygon import Polygon polygon = Polygon(shapes[chosenstitchgroup]) #Buffer expands, scale doesn't work for expanding linear regions with no points buffgon = Polygon(polygon.buffer(min(xmedian, ymedian)).exterior) #polygon=shapely.affinity.scale(polygon,xfact=1.2,yfact=1.2) inside = [ buffgon.contains(Point(x, y)) for x, y in list(zip(chif['ActualPositionX'], chif['ActualPositionY'])) ] matplotlib.pyplot.scatter(list(chif['ActualPositionX']), list(chif['ActualPositionY'])) matplotlib.pyplot.scatter([x[0] for x in shapes[chosenstitchgroup]], [x[1] for x in shapes[chosenstitchgroup]]) matplotlib.pyplot.scatter(buffgon.exterior.coords.xy[0], buffgon.exterior.coords.xy[1]) matplotlib.pyplot.savefig(os.path.join(dirout, 'BufferPolygon.png')) #inside = outline.contains_points(list(zip(chif['ActualPositionX'],chif['ActualPositionY']))) print(inside) print(list(zip(chif['ActualPositionX'], chif['ActualPositionY']))) chif = chif.loc[inside, :] #normalize positions so starts at 0,0 chif['ActualPositionX'] = chif['ActualPositionX'] - chif[ 'ActualPositionX'].min() chif['ActualPositionY'] = chif['ActualPositionY'] - chif[ 'ActualPositionY'].min() xorder = dict( zip(np.sort(chif['ActualPositionX'].unique()), np.sort(chif['ActualPositionX'].unique().argsort()))) yorder = dict( zip(np.sort(chif['ActualPositionY'].unique()), np.sort(chif['ActualPositionY'].unique().argsort()))) for i in chif.index: x = chif.loc[ i, 'ActualPositionX'] / xmedian #xorder[chif.loc[i,'ActualPositionX']] y = chif.loc[ i, 'ActualPositionY'] / ymedian #yorder[chif.loc[i,'ActualPositionY']] print(x, y) x1 = int((xsize * x) - (x * minoverlap)) x2 = x1 + int(xsize) y1 = int((ysize * y) - (y * minoverlap)) y2 = y1 + int(ysize) chif.loc[i, 'x1pix'] = x1 chif.loc[i, 'x2pix'] = x2 chif.loc[i, 'y1pix'] = y1 chif.loc[i, 'y2pix'] = y2 #Incase specific stitchgroups are denoted in my normal way '''l=[] for x in chif['FileName']: if x.startswith('L_'): l.append('1') continue if x.startswith('R_'): l.append('2') continue if '_TR_' in x: l.append('1') continue if '_TD_' in x: l.append('1') continue if 'TR' in x or 'TD' in x: groupnum=re.sub('TR|TD','',re.search('TD[0-9]|TR[0-9]',x).group(0)) l.append(groupnum) continue ###Getting stitch group if len(l)!=imageFiles.shape[0]: #add estimate pixel vals to df for i in chif.index: x=xorder[chif.loc[i,'ActualPositionX']] y=yorder[chif.loc[i,'ActualPositionY']] print(x,y) x1=int((xsize*x)-(x*minoverlap)) x2=x1+int(xsize) y1=int((ysize*y)-(y*minoverlap)) y2=y1+int(ysize) chif.loc[i,'x1pix']=x1 chif.loc[i,'x2pix']=x2 chif.loc[i,'y1pix']=y1 chif.loc[i,'y2pix']=y2 mat=sklearn.metrics.pairwise.euclidean_distances(chif.loc[:,['ActualPositionX','ActualPositionY']]) np.fill_diagonal(mat,9999999999) sortmat=mat.copy() sortmat.sort(1) chif['stitchgroup']='nan' #1.1 is larger than longest acceptable hypotenuse given reasonable aspect ratios G=nx.from_numpy_matrix((mat<=sortmat[:,1].max()).astype(int)) co=nx.algorithms.components.connected_components(G) for i,sg in enumerate(co): chif.loc[chif.index[list(sg)],'stitchgroup']=str(i+1) else: chif['stitchgroup']=l imageFiles['stitchgroup']='nan' for i in chif['"field" Index']: imageFiles.loc[imageFiles['"field" Index']==i,'stitchgroup']=list(chif.loc[chif['"field" Index']==i,'stitchgroup'])[0] chif=chif.loc[chif['stitchgroup']==chosenstitchgroup,:] imageFiles=imageFiles.loc[imageFiles['stitchgroup']==chosenstitchgroup,:] tmppath=os.path.expanduser('~/imagingmetadata.csv') if os.path.exists(tmppath): refdf=pd.read_csv(tmppath,sep='\t') else: refdf=pd.read_csv('https://docs.google.com/spreadsheets/d/e/2PACX-1vSYbvCJpS-GfRKuGgs2IBH7MD1KtDPDqs7ePqQJ1PyrMKp7f7z7ZpY4WtMFGPxU4mWbnRHgBl4PtaeH/pub?output=tsv&gid=1520792104',sep='\t') refdf.to_csv(tmppath,sep='\t') refdf.rename(columns={'Channel0':'GFP','Channel1':'DAPI','Channel2':'CY5','Channel3':'RFP'},inplace=True) imageFiles=pd.merge(imageFiles, refdf, how='left', left_on=['DirName','stitchgroup'], right_on = ['DirName','SlidePosition.1isL']) imageFiles['gene']=list([imageFiles.loc[i,x] for i,x in enumerate(imageFiles['Channel Name'])]) imageFiles['Channel Name']=imageFiles['gene'] xpixdict=dict(zip(chif['"field" Index'],chif['x1pix'])) ypixdict=dict(zip(chif['"field" Index'],chif['y1pix'])) imageFiles=imageFiles.loc[imageFiles['"field" Index'].isin(chif['"field" Index']),:] imageFiles['x1pix']='nan' imageFiles['y1pix']='nan' imageFiles['x1pix']=[xpixdict[x] for x in imageFiles['"field" Index']] imageFiles['y1pix']=[ypixdict[x] for x in imageFiles['"field" Index']] if imageFiles.shape[0]<2: print('No Images!') return(None) imageFiles['xind']=[xorder[x] for x in imageFiles['ActualPositionX']] imageFiles['yind']=[yorder[x] for x in imageFiles['ActualPositionY']] # In[135]: channeldfs={} for c in imageFiles['Channel Name'].unique(): channeldfs[c]=imageFiles.loc[imageFiles['Channel Name']==c,:] channeldfs[c].index=channeldfs[c]['"field" Index'] ''' #Take ordered list of items and break into blocks of size blocksize overlapping by 1 #Used to break image into subblocks for faster stitching def array_to_overlapping_blocks(A, blocksize): import numpy as np size = blocksize step = blocksize - 1 return (np.array([A[i:i + size] for i in range(0, len(A), step)])) # In[14]: print('PIXEL POSITIONS') print('minoverlap', minoverlap) print(chif.loc[:, ['x1pix', 'x2pix', 'y1pix', 'y2pix']], flush=True) xmax = chif['x2pix'].max() ymax = chif['y2pix'].max() inrange = (chif['x2pix'] / xmax > x1lim) & ( chif['x1pix'] / xmax < x2lim) & (chif['y2pix'] / ymax > y1lim) & ( chif['y1pix'] / ymax < y2lim) chif = chif.loc[inrange, :] xmin = chif['x1pix'].min() ymin = chif['y1pix'].min() chif['x1pix'] = chif['x1pix'] - xmin chif['x2pix'] = chif['x2pix'] - xmin chif['y1pix'] = chif['y1pix'] - ymin chif['y2pix'] = chif['y2pix'] - ymin xorder = dict( zip(np.sort(chif['ActualPositionX'].unique()), np.sort(chif['ActualPositionX'].unique().argsort()))) yorder = dict( zip(np.sort(chif['ActualPositionY'].unique()), np.sort(chif['ActualPositionY'].unique().argsort()))) chif['xind'] = [xorder[x] for x in chif['ActualPositionX']] chif['yind'] = [yorder[x] for x in chif['ActualPositionY']] #xblocks=array_to_overlapping_blocks(chif['xind'].unique(),blocksize) #yblocks=array_to_overlapping_blocks(chif['yind'].unique(),blocksize) infile = os.path.join( dirout, str(chosenstitchgroup) + '_' + stitchchannel + '.stitchy') def ijstitch(chdf, infile): #conda create -n imagej -c conda-forge openjdk=8 pyimagej #conda install -c conda-forge maven #conda install -c conda-forge pyjnius #conda install -c conda-forge imglyb import imagej ij = imagej.init(os.path.expanduser('~/utils/Fiji.app/'), new_instance=True) #ij = imagej.init('sc.fiji:fiji',new_instance=True) plugin = 'Grid/Collection stitching' args = { 'type': '[Positions from file]', 'order': '[Defined by TileConfiguration]', 'directory': '[]', 'layout_file': infile, 'regression_threshold': '0.0001', 'fusion_method': '[Linear Blending]', 'max/avg_displacement_threshold': '0.20', 'absolute_displacement_threshold': '0.30', 'subpixel_accuracy': True, #'downsample_tiles':True,'x':'.25', 'y':'.25','interpolation':'Bicubic average',"width":'512','height':'384','outputFile':infile+'.registered.txt', 'compute_overlap': True, 'use_virtual_input_images': True, 'computation_parameters': '[Save memory (but be slower)]', 'image_output': '[Fuse and display]' } #ij.py.run_plugin(plugin, args,ij1_style=False) #ij.py.run_macro('run("Grid/Collection stitching", "type=[Positions from file] order=[Defined by TileConfiguration] directory=[] layout_file=/home/mt/tmp/HOECHST.stitchy fusion_method=Average regression_threshold=0 max/avg_displacement_threshold=2.50 absolute_displacement_threshold=3.50 compute_overlap subpixel_accuracy downsample_tiles use_virtual_input_images computation_parameters=[Save memory (but be slower)] image_output=[Fuse and display] x=.25 y=.25 width=512 height=384 interpolation=Bicubic average");\n') #ij.py.run_script(language='js',script='importClass(Packages.ij.IJ);IJ.run("Grid/Collection stitching", "type=[Positions from file] order=[Defined by TileConfiguration] directory=[] layout_file=/home/mt/tmp/HOECHST.stitchy fusion_method=[Linear Blending] regression_threshold=.01 max/avg_displacement_threshold=.250 absolute_displacement_threshold=.35 compute_overlap subpixel_accuracy downsample_tiles use_virtual_input_images computation_parameters=[Save memory (but be slower)] image_output=[Fuse and display] x=.2 y=.2 width=410 height=307 interpolation=Bicubic average");') ij.getContext().dispose() def callstitching( infile, imagejpath='~/utils/Fiji.app/ImageJ-linux64', scriptpath='~/code/macaque-dev-brain/imaging/Stitching.js'): import sys import subprocess from subprocess import PIPE, STDOUT cmd = [ os.path.expanduser(imagejpath), os.path.expanduser(scriptpath), os.path.expanduser(infile), str(minmax_displace), str(abs_displace) ] cmd = ' '.join(cmd) print(cmd, flush=True) process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT) (stdoutdata, stderrdata) = process.communicate() print(stdoutdata) def write_stitchy(chdf, infile): with open(infile, 'w') as the_file: the_file.write('dim = 2\n') for i in chdf.index: cur = chdf.loc[i, :] the_file.write(cur['Path'] + '; ; (' + str(cur['x1pix']) + ',' + str(cur['y1pix']) + ') \n') def read_stitchy(chdf, infile): print('read_stitchy:') print(infile) df = pd.read_csv(infile, skiprows=4, header=None, sep=';') df.loc[:, ['ActualPositionX', 'ActualPositionY']] = [ re.sub('\(|\)', '', x).split(',') for x in df[2] ] df.index = df[0] print(df) df.loc[:, ['xind', 'yind']] = 0 for i in df.index: df.loc[i, ['xind', 'yind']] = chdf.loc[chdf['FileName'] == i, ['xind', 'yind']].values[0] return (df) def do_ij_stitching(chdf, infile): print('do_ij_stitching') write_stitchy(chdf, infile) #ijstitch(chdf,infile) callstitching(infile) #This would have to be changed for non-evos microscopes with open(infile + '.registered.txt', "r") as sources: lines = sources.readlines() for d in ['d0', 'd1', 'd2', 'd3']: with open( re.sub('DAPI', d, infile) + str(minmax_displace) + '_' + str(abs_displace) + '.registered.txt', "w") as sources: for line in lines: sources.write(re.sub('d1.TIF', d + '.TIF', line)) return (read_stitchy(chdf, infile + '.registered.txt')) df = do_ij_stitching(chif, infile) with open(os.path.join(dirout, 'dummyfile.dummy'), 'w') as fp: pass ray.shutdown() return (df, imageFiles)
def IniMatch(plist, Edges0F, Edges1F, MaskB0F, MaskB1F, x_off, y_off, CV1, gt0F, gt1F): # Nullify impact of OpenOrth + CannyLin + OneMatch: x_off = 0 y_off = 0 CV1 = 1.5 ps0F = 0.05 w = int(25 / ps0F) buff = w Edges1Fa = np.zeros( (Edges1F.shape[0] + buff * 2, Edges1F.shape[1] + 2 * buff)) Edges1Fa[buff:-buff, buff:-buff] = Edges1F Edges1Fa = (Edges1Fa).astype(np.uint8) if CV1 >= 4: md = 5 x_off = 0 y_off = 0 elif CV1 <= 1.5: md = 2 else: md = 2 + 3 * ((CV1 - 1.5) / 2.5) md = 6 md = int(6 / ps0F) contours, hierarchy = cv2.findContours( (1 - MaskB0F).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] poly_base = Polygon(np.array(biggest_contour[:, 0])) contours, hierarchy = cv2.findContours( (1 - MaskB1F).astype(np.uint8), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] poly_file = Polygon(np.array(biggest_contour[:, 0])) if poly_file.area < 0.7 * poly_base.area: sf = 1 print( "Georegistration of small orthomosaic on larger, very cool, preventive move to nrtu folder afterwards..." ) inward = 0 polygon = poly_file.buffer(-w) while polygon.area < 0.6 * poly_file.area: inward += 20 polygon = poly_file.buffer(-w + inward) while polygon.type == 'MultiPolygon': polygon = sorted(list(polygon), key=lambda p: p.area, reverse=True)[0] x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt( np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): lat = gt1F[3] + gt1F[5] * y_regular[i] lon = gt1F[0] + gt1F[1] * x_regular[i] y_regular[i] = (lat - gt0F[3]) / gt0F[5] x_regular[i] = (lon - gt0F[0]) / gt0F[1] grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) elif poly_base.area < 0.4 * poly_file.area: sf = 1 print( "Georegistration of large orthomosaic on smaller, moving to nrtu folder afterwards..." ) polygon = poly_base.buffer(-w) while polygon.type == 'MultiPolygon': polygon = sorted(list(polygon), key=lambda p: p.area, reverse=True)[0] x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt( np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) if polygon.buffer(-3 * w).is_empty == False: polygon = polygon.buffer(-2 * w) while polygon.type == 'MultiPolygon': polygon = sorted(list(polygon), key=lambda p: p.area, reverse=True)[0] x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt( np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 100) x_regular, y_regular = fx(alpha), fy(alpha) for i in range(len(x_regular)): grid.append( (int(round(x_regular[i])), int(round(y_regular[i])))) else: sf = 0 polygon = poly_base.buffer(-w) while polygon.type == 'MultiPolygon': polygon = sorted(list(polygon), key=lambda p: p.area, reverse=True)[0] x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt( np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 200) x_regular, y_regular = fx(alpha), fy(alpha) grid = [] for i in range(len(x_regular)): grid.append((int(round(x_regular[i])), int(round(y_regular[i])))) if polygon.buffer(-3 * w).is_empty == False: polygon = polygon.buffer(-2 * w) while polygon.type == 'MultiPolygon': polygon = sorted(list(polygon), key=lambda p: p.area, reverse=True)[0] x, y = polygon.exterior.xy distance = np.cumsum( np.sqrt( np.ediff1d(x, to_begin=0)**2 + np.ediff1d(y, to_begin=0)**2)) distance = distance / distance[-1] fx, fy = interp1d(distance, x), interp1d(distance, y) alpha = np.linspace(0, 1, 100) x_regular, y_regular = fx(alpha), fy(alpha) for i in range(len(x_regular)): grid.append( (int(round(x_regular[i])), int(round(y_regular[i])))) c1 = np.zeros((2 * w, 2 * w)) for x in range(c1.shape[0]): for y in range(c1.shape[1]): if (x - w)**2 + (y - w)**2 < w**2: c1[x, y] = 1 c1 = (c1).astype(np.uint8) c2 = np.zeros((2 * md, 2 * md)) for x in range(c2.shape[0]): for y in range(c2.shape[1]): if (x - md)**2 + (y - md)**2 < md**2: c2[x, y] = 1 c2 = (c2).astype(np.uint8) return plist, Edges1Fa, x_off, y_off, grid, md, c1, c2, sf