def get_coor(img): (x,y),img=roi(img) median = cv2.GaussianBlur(image,(5,5),0) median = cv2.medianBlur(median,15) hsv = cv2.cvtColor(median, cv2.COLOR_BGR2HSV) lower_blue=np.array([91,111,68]) upper_blue=np.array([115,255,255]) mask=cv2.inRange(hsv,lower_blue,upper_blue) edges = cv2.Canny(mask,100,200) (contours,_) = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) #hull = cv2.convexHull(contours,returnPoints = False) #print(hull) arr=[] for contour in contours: (x,y,w,h) = cv2.boundingRect(contour) arr.append([x,y]) arr.append([x+w,y]) arr.append([x,y+h]) arr.append([x+w,y+h]) alpha = 0.4 * alphashape.optimizealpha(arr) hull = alphashape.alphashape(arr, alpha) hull_pts = hull.exterior.coords.xy arr=[] for i in range(len(hull_pts[0])): arr.append([int(hull_pts[0][i]),int(hull_pts[1][i])]) results=[(np.array(z)+np.array([x,y])).tolist() for z in arr] return results
def get_coor(image): X, Y, Z = de_hole1(image) Xk = roi(image)[0] arr_X = [] arr_Y = [] for z in Z: for x in X: if z[0] == x[0] or z[1] == z[1]: if check(z, x): arr_X.append(z) for z in Z: for x in Y: if z[0] == x[0] or z[1] == z[1]: if check(z, x): arr_Y.append(z) output = [] arr = arr_X + arr_Y for x in arr: if x not in output: output.append(x) alpha = 0.3 * alphashape.optimizealpha(output) hull = alphashape.alphashape(output, alpha) hull_pts = hull.exterior.coords.xy arr = [] for i in range(len(hull_pts[0])): arr.append([int(hull_pts[0][i]), int(hull_pts[1][i])]) #r1=[[img[0]+Xk[0],img[1]+Xk[1]] for img in arr] return arr
def test_given_a_point_return_a_point(self): """ Given a point, the alphashape function should return the same point """ alpha = optimizealpha( [(0., 0.), (0., 1.), (1., 1.), (1., 0.), (0.5, 0.25), (0.5, 0.75), (0.25, 0.5), (0.75, 0.5)]) assert alpha > 3. and alpha < 3.5
def get_coor12(image): X, Y, Z = de_hole12(image) if de_hole1(image) is not None: Xk = roi(image)[0] arr_X = [] arr_Y = [] for z in Z: for x in X: if z[0] == x[0] or z[1] == z[1]: if check(z, x): arr_X.append(z) for z in Z: for x in Y: if z[0] == x[0] or z[1] == z[1]: if check(z, x): arr_Y.append(z) output = [] arr = arr_X + arr_Y for x in arr: if x not in output: output.append(x) alpha = 0.3 * alphashape.optimizealpha(output) hull = alphashape.alphashape(output, alpha) hull_pts = hull.exterior.coords.xy arr = [] for i in range(len(hull_pts[0])): arr.append([int(hull_pts[0][i]), int(hull_pts[1][i])]) def check(coor1, coor2): a = abs(coor1[0] - coor2[0]) + abs(coor2[1] - coor1[1]) if a > 10: return False return True hull_pts = hull.exterior.coords.xy arr1 = [] for i in range(len(hull_pts[0])): arr1.append([int(hull_pts[0][i]), int(hull_pts[1][i])]) print(arr1) t = {} for i in range(len(arr1) - 1): t[i] = [arr1[i + 1][0], arr1[i][1]] print(t) count = 1 for i in range(len(t)): if t[i] is not arr1: for v in arr: if check(t[i], v): arr1.insert(count, t[i]) count = count + 1 print(t[i]) break count = count + 1 return arr1
def add_alphashap(points, ax, alpha_value=None, alpha=0.3, fc=None, ec=None): """ Add a alpha shape which corresponds to the ternary scatter plot :param points: A list of 3-tuples that (i, j, k) requires i + j + k = scale :param ax: the ax to plot the alpha shape, supposed to be same as the scatter plot :param alpha_value: float. default None which will calculate the optimize. If zero a Convex hill will be added :param alpha: float 0 to 1 :param fc: fill color :param ec: edge color :return: None """ t_points = to_t_points(points) if alpha_value is None: alpha_value = alphashape.optimizealpha(t_points) alpha_shape = alphashape.alphashape(t_points, alpha_value) ax.add_patch(PolygonPatch(alpha_shape, alpha=alpha, fc=fc, ec=ec))
if counter % 100 == 0: nivo += 1 for i in range(0, len(zdata)): by_nivo[zdata[i]].append((xdata[i], ydata[i])) min_z = min(zdata) max_z = max(zdata) polni_nivo = {} outer_nivo = {} for _nivo in by_nivo: points = by_nivo[_nivo] alpha = 0.25 * alphashape.optimizealpha(points) hull = alphashape.alphashape(points, alpha) hull_pts = hull.exterior.coords.xy hull_points = [] for i in range(0, len(hull_pts[0])): hull_points.append((hull_pts[0][i], hull_pts[1][i])) polyg = Polygon(hull_points) line_polygon = LineString(polyg.exterior.coords) # (minx, miny, maxx, maxy) bounds = list(map(int, list(polyg.bounds))) polni_nivo[_nivo] = [] outer_nivo[_nivo] = [] for i in range(bounds[0], bounds[2]+1):
def cluster_hull(self, alpha0=2.25, minimum_lattice_distance=0.33): timeout_error = False concave_error = False y_fun = np.linspace(0.0, self.Ly, N_SAMPLES_Y) np.savetxt(self.save_fld + '/' + self.fr + 'y.txt', y_fun) mpl.use("Agg") print("[ -- Producing movie of the contact line in (x,y) -- ]") output_file_name = self.movie_name FFMpegWriter = manimation.writers['ffmpeg'] metadata = dict(title='Contact Line', artist='Michele Pellegrino', comment='Contact line x(y) over time') writer = FFMpegWriter(fps=12, metadata=metadata) fig = plt.figure() with writer.saving(fig, output_file_name, N_WRITER): for frame in range(self.frm_ini, self.frm_fin + 1): print("[ ClusterHull: reading frame " + str(frame).zfill(4) + " ]") # Read from .gro and add periodic images file_name = self.read_fld + '/' + self.fr + str(frame).zfill( 4) + '.gro' x = [] y = [] n_lines = count_line(file_name) n = 0 in_file = open(file_name, 'r') for line in in_file: n += 1 if n > 2 and n < n_lines: line_data = read_gro_line(line) if line_data[2] == "OW": x.append(line_data[4]) y.append(line_data[5]) in_file.close() for k in range(len(y)): if y[k] > 0.75 * self.Ly: y.append(y[k] - self.Ly) x.append(x[k]) elif y[k] < 0.25 * self.Ly: y.append(y[k] + self.Ly) x.append(x[k]) # Perform 2D clustering and find the label with the most points x = np.array(x) y = np.array(y) xcom = np.mean(x) points = np.column_stack((x, y)) clustering = DBSCAN(eps=minimum_lattice_distance, min_samples=1).fit(points) cl_label = most_frequent(clustering.labels_) # Obtain a concave hull x_cl = np.take(x, np.where((clustering.labels_==cl_label) * \ ((x<xcom)*self.left_int+(x>xcom)*(1-self.left_int)) )[0]) y_cl = np.take(y, np.where((clustering.labels_==cl_label) * \ ((x<xcom)*self.left_int+(x>xcom)*(1-self.left_int)) )[0]) points_cl = np.column_stack((np.array(x_cl), np.array(y_cl))) if frame == self.frm_ini and alpha0 == 0: print("[ Optimizing alpha, please wait... ]") alpha = alphashape.optimizealpha(points_cl) print("[ alpha = " + '{:05.3f}'.format(alpha) + " ]") else: alpha = alpha0 hull = alphashape.alphashape(points_cl, alpha) # Checking hull object instance if isinstance(hull, shapely.geometry.multipolygon.MultiPolygon): print( "[ Warning: alphashape is returning more than one polygon as concave hull ]" ) print( "[ -> re-optimizing alpha... ]" ) alpha = alphashape.optimizealpha(points_cl) hull = alphashape.alphashape(points_cl, alpha) print("[ alpha = " + '{:05.3f}'.format(alpha) + " ]") if isinstance(hull, shapely.geometry.multipolygon.MultiPolygon): print( "[ Error: cannot obtain an optimal value of alpha for a single polygon ]" ) print( "[ -> try changing clustering epsilon instead ]" ) concave_error = True break print("[ Re-setting alpha to its original value... ]") alpha = alpha0 print("[ alpha = " + '{:05.3f}'.format(alpha) + " ]") hull_pts = hull.exterior.coords.xy # Obtain the cl function x(y) at this frame hull_cl_x = [] hull_cl_y = [] s1 = False s2 = True l = len(hull_pts[0]) hull_pts_x = hull_pts[0][0:l - 1] hull_pts_y = hull_pts[1][0:l - 1] if not (self.left_int): hull_pts_x = np.flip(hull_pts_x) hull_pts_y = np.flip(hull_pts_y) l = len(hull_pts_x) n = 0 # Checking timeout timeout = cpu_time.time() + 5.0 # Five seconds from now while (s2): n_new = n n_old = (n - 1) % l y_old = hull_pts_y[n_old] y_new = hull_pts_y[n_new] if y_old <= self.Ly and y_new >= self.Ly and s1: s2 = False if y_old <= 0 and y_new >= 0: s1 = True hull_cl_x.append(hull_pts_x[n_old]) hull_cl_y.append(hull_pts_y[n_old]) if s1: hull_cl_x.append(hull_pts_x[n_new]) hull_cl_y.append(hull_pts_y[n_new]) n = (n + 1) % l if cpu_time.time() > timeout: print( "[ Error: selection of contact line countour points is taking too long ]" ) print( "[ -> plotting concave hull, you may want to change alpha or eps ]" ) s2 = False timeout_error = True if timeout_error: break x_fun = np.interp(y_fun, hull_cl_y, hull_cl_x) # Saving cl x(y) on a .txt file np.savetxt( self.save_fld + '/' + self.fr + str(frame).zfill(4) + '.txt', x_fun) if self.make_movie: plt.axis('scaled') plt.ylim([self.xmin, self.xmax]) plt.xlim([0.0, self.Ly]) plt.title('CL @t=' + str(frame).zfill(4) + 'ps', fontsize=17.5) plt.fill_between(y_fun, x_fun, y2=self.xmax*self.left_int+self.xmin*(1-self.left_int), \ color='tab:cyan') plt.plot(y, x, 'k.') plt.xlabel("y [nm]", fontsize=15.0) plt.ylabel("x [nm]", fontsize=15.0) plt.xticks(fontsize=12.5) plt.yticks(fontsize=12.5) writer.grab_frame() plt.cla() plt.clf() mpl.use("TkAgg") if timeout_error: fig, ax = plt.subplots() ax.scatter(x, y, c=1 + clustering.labels_, s=150, cmap=cm.Paired) ax.plot(hull_pts[0], hull_pts[1], 'b--') ax.plot(hull_pts[0][0], hull_pts[1][0], 'bo') ax.plot(hull_pts[0][1], hull_pts[1][1], 'bx') ax.plot([self.xmin, self.xmax], [0.0, 0.0], 'r-') ax.plot([self.xmin, self.xmax], [self.Ly, self.Ly], 'r-') plt.xlabel("x [nm]", fontsize=25) plt.ylabel("y [nm]", fontsize=25) plt.xticks(fontsize=20.0) plt.yticks(fontsize=20.0) plt.show() if concave_error: fig, ax = plt.subplots() ax.scatter(x, y, c=1 + clustering.labels_, s=150, cmap=cm.Paired) ax.plot(xcom, 0.5 * self.Ly, 'rx', markersize=25) ax.plot([self.xmin, self.xmax], [0.0, 0.0], 'r-') ax.plot([self.xmin, self.xmax], [self.Ly, self.Ly], 'r-') plt.xlabel("x [nm]", fontsize=25) plt.ylabel("y [nm]", fontsize=25) plt.xticks(fontsize=20.0) plt.yticks(fontsize=20.0) plt.show()
def get_perimeter(srf_file, depth=True, plot=False): """ Like get_bounds but works with roughness where the edges aren't straight. srf_file: assumed to be finite fault depth: work in progress, need to find associated points or do 3d concave hull plot: for testing only, plot points, perimeter and show """ if plot: from matplotlib import pyplot as plt from descartes import PolygonPatch perimeters = [] top_edges = [] if depth: value = "depth" else: value = None with open(srf_file, "r") as sf: planes = read_header(sf, idx=True) points = int(sf.readline().split()[1]) for i in range(len(planes)): a = [] nstk = planes[i]["nstrike"] ndip = planes[i]["ndip"] points = np.array( [get_lonlat(sf, value=None) for j in range(ndip * nstk)]) # The value of alpha parameter determines how tightly points are enclosed # alpha= 0 means we get a convex-hull, but often a concave-hull represents a better fit. # Viktor reported alpha=600 worked ok with SRF (roughness 0.1) but it is too high and often misses points entirely. # if no alpha is given, the optimal value is to be found, but is impractically slow. # The following will try to optimize alpha with 10 iterations (default is 1000), and if no success, alpha=0 (convex hull) alpha = optimizealpha(points, max_iterations=10) ashape = alphashape(points, alpha) perimeters.append(np.dstack(ashape.exterior.coords.xy)[0]) if plot: fig, ax = plt.subplots() ax.scatter(*zip(*points)) ax.add_patch(PolygonPatch(ashape, alpha=0.2)) plt.show() plt.close() # try to find top edges in perimeter # closest point in case corner not in perimeter (srf roughness) # roughness may result in closest point being a couple meters out # euclidian ok, even SRF res is only 100m # TODO: include depth to prevent issues with 90 degree dips c1 = perimeters[-1] - points[0] # minimum sum of squares c1 = np.argmin(np.einsum("ij,ij->i", c1, c1)) c2 = perimeters[-1] - points[nstk - 1] c2 = np.argmin(np.einsum("ij,ij->i", c2, c2)) # assume shorter edge is top edge if abs(c2 - c1) < len(perimeters[-1]) / 2: # edge doesn't wrap array start = min(c1, c2) end = max(c1, c2) top_edges.append(perimeters[-1][start:end + 1]) else: # edge wraps array ends start = max(c1, c2) end = min(c1, c2) top_edges.append( np.vstack( (perimeters[-1][start:], perimeters[-1][:end + 1]))) return perimeters, top_edges
def concaveHull(points, communities, alpha=.018): """ Calculate the concave hull (external boundary) for a set of points, while also keeping track of the communities for each boundary point. Parameters ---------- points : numpy.ndarray or list A set of points of shape (N, 2). communities : numpy.ndarray or list The community assignments for each point in points. alpha : float The alpha parameter for creating the hull; determines how angular or concave the final result is. Default value was choosen by using the alphashape.optimize function. If value is set to None, this method will be run explicitly to find a good value (though it takes a significantly longer period of time). Returns ------- (numpy.ndarray, numpy.ndarray) : The lines that comprise the concave hull (1st element) and the communities that each point in each line belongs to (2nd element). Individual hull lines are formatted as: [[x1, x2], [y1, y2]] """ # Find the total boundary around the shape # The .80 is to say that we don't want the boundary to be crazy angular if alpha == None: alpha = 0.80 * ap.optimizealpha(points) #print(alpha) hull = ap.alphashape(points, alpha) hullPoints = hull.exterior.coords.xy # And convert to a better format hullPoints = [hullPoints[0].tolist(), hullPoints[1].tolist()] # Now we also want to know what communities the points involved # in the boundary are (for creating closed shapes later on) # You can't use a list as a key for a dictionary, so we take the string # that represents the list. Not ideal, but it shouldn't cause any real issues communitiesByPointPosition = {} for i in range(len(points)): communitiesByPointPosition[str([points[i,0], points[i,1]])] = communities[i] # Transform to looking at the lines of the hull (instead of the points) hullLines = np.zeros([len(hullPoints[0]), 2, 2]) hullLineCommunities = np.zeros([len(hullPoints[0]), 2]) for i in range(len(hullPoints[0])): # Each of these lines are of the form: # [[x1, x2], [y1, y2]] hullLines[i] = [[hullPoints[0][i], hullPoints[0][(i+1)%len(hullPoints[0])]], [hullPoints[1][i], hullPoints[1][(i+1)%len(hullPoints[0])]]] # This line is pretty disgusting, but unfortunately it can't really be avoided # because we need to know which communities the boundary lines connect :/ hullLineCommunities[i] = [communitiesByPointPosition[str([hullPoints[0][i], hullPoints[1][i]])], communitiesByPointPosition[str([hullPoints[0][(i+1)%len(hullPoints[0])], hullPoints[1][(i+1)%len(hullPoints[0])]])]] return hullLines, hullLineCommunities
Optimized Alpha Example ======================= Using the optimized alpha function for obtaining the alpha parameter. """ import alphashape import matplotlib.pyplot as plt from descartes import PolygonPatch # Define input points points = [(0., 0.), (0., 1.), (1., 1.), (1., 0.), (0.5, 0.25), (0.5, 0.75), (0.25, 0.5), (0.75, 0.5)] # Determine the optimized alpha parameter alpha = alphashape.optimizealpha(points) # Generate the alpha shape alpha_shape = alphashape.alphashape(points, alpha) # Initialize plot fig, ax = plt.subplots() # Plot input points ax.scatter(*zip(*points)) # Plot alpha shape ax.add_patch(PolygonPatch(alpha_shape, alpha=.2)) plt.show()