def getAngle(self, a1, a2, a3): """Get the angle """ x1 = self.atoms[a1 - 1].x x2 = self.atoms[a2 - 1].x x3 = self.atoms[a3 - 1].x ang = get_angle(x1, x2, x3) return ang
def getAngle(self, a1, a2, a3): """Get the angle """ x1 = self.atoms[a1-1].x x2 = self.atoms[a2-1].x x3 = self.atoms[a3-1].x ang = get_angle(x1, x2, x3) return ang
def inverse_velocity_edge_collision(self, hit_x_limit): vel_x = math.cos(self.direction_angle) * self.velocity vel_y = math.sin(self.direction_angle) * self.velocity if hit_x_limit: vel_x = -1 * vel_x else: vel_y = -1 * vel_y new_angle = utilities.get_angle((0, 0), (vel_x, vel_y)) self.direction_angle = new_angle
def check_cone_collision(self, target_object, scan_radius, scan_angle): if not self.check_radius_collision(target_object, scan_radius): return False target_coord = (target_object.x, target_object.y) collision_angle = utilities.get_angle((self.x, self.y), target_coord) min_collision_angle = self.direction_angle - scan_angle / 2.0 max_collision_angle = self.direction_angle + scan_angle / 2.0 above_min = collision_angle >= min_collision_angle below_max = collision_angle <= max_collision_angle if above_min and below_max: return True return False
def test_angle_negative(self): point_a = (0, 0) point_b = (-1, 1) angle = get_angle(point_a, point_b) self.assertEqual(angle, (3/4)*math.pi)
def test_angle_positive(self): point_a = (0, 0) point_b = (1, 1) angle = get_angle(point_a, point_b) self.assertEqual(angle, math.pi / 4)
def state_info(filename, compute_energies=True, compute_charge=False, compute_turns=False, compute_projections=False, compute_periods=True, compute_negative=False, compute_skyrmion_size=False, compute_localisation=False): data = {} container = magnes.io.load(str(filename)) system = container.extract_system() if "PATH" in container: s = list(container["PATH"])[0] # print('state from path') else: s = container["STATE"] # print('state from state') state = system.field3D() state.upload(s) if compute_energies: try: data['energy'] = state.energy_contributions_sum()['total'] \ - s.shape[0] * s.shape[1] * (s.shape[2] - 2) * 3 - s.shape[0] * s.shape[1] * 5 data['energy_per_unit'] = data['energy'] / ( s.shape[0] * s.shape[1] * s.shape[2]) except: () try: data['energy_original'] = state.energy_contributions_sum()['total'] except: () try: data['energy_J'] = state.energy_contributions_sum()['Heisenberg'] except: () try: data['energy_D'] = state.energy_contributions_sum()['DM'] except: () try: data['energy_K'] = state.energy_contributions_sum()['anisotropy'] except: () try: data['energy_H'] = state.energy_contributions_sum()['Zeeman'] except: () try: if True: data['energy_if_xsp'] = data['energy_per_unit'] except: () if compute_charge: try: data['centre_charge'] = toplogical_charge(system, s, int(s.shape[2] / 2)) except: () try: data['border_charge'] = toplogical_charge(system, s, 0) except: () if compute_turns: try: data['border_turn'] = (s[:, :, 0, :, 2] > 0.1).sum() + ( s[:, :, -1, :, 2] > 0.1).sum() except: () if compute_projections: try: data['mean_z_projection'] = np.sum( np.dot(s, np.array([0., 0., 1.]))) / (s.size / 3) except: () try: data['mean_z_centre_projection'] = np.sum( np.dot(s[:, :, int(s.shape[2] / 2)], np.array( [0., 0., 1.]))) / (s.shape[0] * s.shape[1]) except: () try: data['mean_z_centre_abs_projection'] = np.sum( np.abs( np.dot(s[:, :, int(s.shape[2] / 2)], np.array( [0., 0., 1.])))) / (s.shape[0] * s.shape[1]) except: () try: data['mean_x_projection'] = np.sum( np.dot(s, np.array([1., 0., 0.]))) / (s.size / 3) except: () try: data['mean_x_abs_projection'] = np.sum( np.abs(np.dot(s, np.array([1., 0., 0.])))) / (s.size / 3) except: () try: data['mean_x_centre_abs_projection'] = np.sum( np.abs( np.dot(s[:, :, int(s.shape[2] / 2)], np.array( [1., 0., 0.])))) / (s.shape[0] * s.shape[1]) except: () try: data['mean_x_centre_abs_projection_angle'] = np.arccos( data['mean_x_centre_abs_projection']) * 360 / (2 * np.pi) except: () try: data['mean_z_abs_projection'] = np.sum( np.abs(np.dot(s, np.array([0., 0., 1.])))) / (s.size / 3) except: () if compute_periods: try: data['angle'] = utilities.get_angle(s) except: () try: data['zperiod'] = utilities.get_zperiod(s) except: () try: data['zturns'] = np.min([s.shape[2] / data['zperiod'], 5]) except: () try: data['xperiod'] = s.shape[0] except: () try: data['x_tilted_period'] = data['xperiod'] * np.sin( data['angle'] * np.pi / 180) except: () if compute_skyrmion_size: try: if compute_skyrmion_size == 'fast': # print('fast skyrmion size') data['skyrmion_size'], data['bober_size'], data[ 'topbober_size'], data[ 'bottombober_size'] = skyrmion_profile.fast_skyrmion_size_compute( s) if data['skyrmion_size'] > 0.1 and data['bober_size'] > 1.: data['is_skyrmion'] = True elif data['skyrmion_size'] > 0.1 and data['bober_size'] <= 1.: data['is_toron'] = True elif data['skyrmion_size'] <= 0.1 and data['bober_size'] > 1.: data['is_bober'] = True if data['skyrmion_size'] > 0.1 and np.logical_xor( data['topbober_size'] > 1., data['bottombober_size'] > 1.): data['is_leech'] = True # print(f'{skyrmion_size'] = }\t{bober_size'] = }') elif compute_skyrmion_size == 'full': # print('full skyrmion size') r_min, r_max, skyrmion_mask_sum = skyrmion_profile.skyrmion_profile( filename, show=False) data['skyrmion_size'] = r_max[int(s.shape[2] / 2)] if np.isnan(data['skyrmion_size']): data['skyrmion_size'] = 0. # print(f'{r_max = }') # print(f'{data['skyrmion_size'] = }') except: () if compute_negative: try: print('computing negative') rate, negative, normal2d, oper, first, second = \ magnes.rate.dynamic_prefactor_htst(system, state, normal=None, tolerance=1e-5, number_of_modes=1) negative = np.array(negative)[0] data['smallest_eigenvalue'] = negative data['eigenvalue_positive'] = 1 if negative >= 0 else 0 print(f'{negative = }') except: () if compute_localisation: try: data['local'] = localisation(s) except: () try: if data['local'] < 1: if abs(data['centre_charge']) < 0.3 and abs( data['border_charge'] ) < 0.3 and data['border_turn'] < 20: data['state_type'] = 'cone' elif abs(data['centre_charge']) < 0.3 and ( abs(abs(data['border_charge']) - 1) < 0.3 or data['border_turn'] > 20): data['state_type'] = 'bober' elif abs(abs(data['centre_charge']) - 1) < 0.3 and abs( data['border_charge'] ) < 0.3 and data['border_turn'] < 20: data['state_type'] = 'toron' elif abs(abs(data['centre_charge']) - 1) < 0.3 and ( abs(abs(data['border_charge']) - 1) < 0.3 or data['border_turn'] > 20): data['state_type'] = 'skyrmion' else: print(f'{data["local"] = }') data['state_type'] = np.nan except: () return data
def detect(self, image): best_transformation = self.transformer.get_playground_transformation(image) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_2_best_transformation.png", utilities.as_uint8(best_transformation)) # return best_transformation = utilities.as_uint8(best_transformation) middle = utilities.get_middle(best_transformation) box = utilities.get_box(best_transformation, middle, 100) if np.average(box) > np.average(best_transformation): print("Inverting image") best_transformation = 255 - best_transformation box = utilities.get_box(best_transformation, middle, 100) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_3_invert.png", utilities.as_uint8(best_transformation)) blur_size = 5 best_transformation = cv2.blur(best_transformation, (blur_size, blur_size)) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_4_blur.png", utilities.as_uint8(best_transformation)) box_hist = utilities.get_histogram(box) box_hist /= sum(box_hist) argmax = np.argmax(box_hist) cur = argmax low = argmax high = argmax tot_sum = 0.0 while tot_sum < 0.9: tot_sum += box_hist[cur] if high == 255: cur = low - 1 elif low == 0: cur = high + 1 else: if box_hist[high+1] > box_hist[low-1]: cur = high + 1 else: cur = low - 1 low = min(low, cur) high = max(high, cur) def threshold_range(img, lo, hi): th_lo = cv2.threshold(img, lo, 255, cv2.THRESH_BINARY)[1] th_hi = cv2.threshold(img, hi, 255, cv2.THRESH_BINARY_INV)[1] return cv2.bitwise_and(th_lo, th_hi) print("Thresholding between {} and {}".format(low, high)) best_transformation = threshold_range(best_transformation, low, high) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_5_threshold.png", utilities.as_uint8(best_transformation)) # ret, best_transformation = cv2.threshold(best_transformation, idx, 255, cv2.THRESH_TOZERO) box = utilities.get_box(best_transformation, middle, 100) box[:,:] = 255 best_transformation[np.where(best_transformation == 255)] = 254 num_filled, best_transformation, _, _ = cv2.floodFill(best_transformation, None, middle, 255, upDiff=0, loDiff=0, flags=cv2.FLOODFILL_FIXED_RANGE) best_transformation[np.where(best_transformation != 255)] = 0 # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_6_flood_fill.png", utilities.as_uint8(best_transformation)) kernel_size = 3 iterations = 1 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (kernel_size,kernel_size)) best_transformation = cv2.erode(best_transformation, kernel, iterations=iterations) best_transformation = cv2.dilate(best_transformation, kernel, iterations=iterations-1) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_7_opening.png", utilities.as_uint8(best_transformation)) best_transformation[np.where(best_transformation == 255)] = 254 num_filled, best_transformation, _, _ = cv2.floodFill(best_transformation, None, middle, 255, upDiff=0, loDiff=0, flags=cv2.FLOODFILL_FIXED_RANGE) best_transformation[np.where(best_transformation != 255)] = 0 # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_8_flood_fill_2.png", utilities.as_uint8(best_transformation)) im2, contours, hierarchy = cv2.findContours(best_transformation.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) if len(contours) > 0: # IDEA: For each vertex, see if the density inside the triangle made by connecting this vertex with the previous # and next vertices are much less than the density of the entire convex hull. # If it is, we should probably remove this vertex as it is the result # of a "thin arm" that the flood fill followed. polygon = contours[0] for idx in range(1, len(contours)): polygon = np.concatenate((polygon, contours[idx])) convex_hull = cv2.convexHull(polygon) convex_hull = cv2.approxPolyDP(convex_hull, 5, True) original_convex_hull = convex_hull.copy() convex_hull_as_list = [] for idx in range(len(convex_hull)): vertex = convex_hull[idx][0] convex_hull_as_list.append((vertex[0], vertex[1])) temp = best_transformation.copy() temp[np.where(temp == 255)] = 120 for idx, v1 in enumerate(convex_hull_as_list): cv2.line(temp, v1, convex_hull_as_list[(idx+1)%len(convex_hull_as_list)], 255, 3) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_9_convex_hull.png", utilities.as_uint8(temp)) convex_hull_mask = utilities.poly2mask(convex_hull, best_transformation) best_transformation[np.where(convex_hull_mask == 0)] = 0 convex_hull_n = np.count_nonzero(convex_hull_mask) convex_hull_n_white = np.count_nonzero(best_transformation[np.where(convex_hull_mask != 0)]) convex_hull_density = convex_hull_n_white / convex_hull_n # print("Convex hull density:", convex_hull_density) copy = best_transformation.copy() # utilities.show(convex_hull_mask, time_ms=10) outside_convex_hull_color = 0 outside_triangle_not_filled_color = int(1/6 * 255) outside_triangle_filled_color = int(2/3 * 255) inside_triangle_not_filled_color = int(2/6 * 255) inside_triangle_filled_color = 255 copy[np.where(convex_hull_mask == 0)] = outside_convex_hull_color copy[np.where((convex_hull_mask != 0) & (copy != 0))] = outside_triangle_filled_color copy[np.where((convex_hull_mask != 0) & (copy == 0))] = outside_triangle_not_filled_color # utilities.show(best_transformation, time_ms=0) new_convex_hull = [] #import transformer #from image import Image #light_mask = transformer.Transformer.get_light_mask(Image(image_data=img)) idx = 0 isd = 0 while idx < len(convex_hull_as_list): temp = best_transformation.copy() temp[np.where(temp == 255)] = 120 v1 = convex_hull_as_list[(idx-1)%len(convex_hull_as_list)] v2 = convex_hull_as_list[idx] v3 = convex_hull_as_list[(idx+1)%len(convex_hull_as_list)] triangle_mask = utilities.poly2mask([v1, v2, v3], best_transformation) # temp[np.where((triangle_mask != 0) & (temp != 0))] = 255 # temp[np.where((triangle_mask != 0) & (temp == 0))] = 60 # utilities.show(temp) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_10_{}_convex_hull_refinement.png".format(isd), utilities.as_uint8(temp)) isd += 1 copy[np.where((triangle_mask == 0) & (copy == inside_triangle_filled_color))] = outside_triangle_filled_color copy[np.where((triangle_mask == 0) & (copy == inside_triangle_not_filled_color))] = outside_triangle_not_filled_color copy[np.where((triangle_mask != 0) & (copy == outside_triangle_filled_color))] = inside_triangle_filled_color copy[np.where((triangle_mask != 0) & (copy == outside_triangle_not_filled_color))] = inside_triangle_not_filled_color triangle_n_white = np.count_nonzero(best_transformation[np.where(triangle_mask != 0)]) triangle_n = np.count_nonzero(triangle_mask) triangle_density = triangle_n_white / triangle_n #light_density = np.count_nonzero(light_mask[np.where(triangle_mask != 0)]) / triangle_n limit = 0.4*convex_hull_density# + light_density / 2 # utilities.show(copy, text="Triangle density: {}, limit: {}".format(round(triangle_density, 2), round(limit, 2))) if triangle_density > limit: new_convex_hull.append(v2) idx += 1 else: best_transformation[np.where(triangle_mask != 0)] = 0 convex_hull_as_list.remove(v2) copy[np.where(triangle_mask != 0)] = outside_convex_hull_color def show_lines(image, pts): # to_show = image.get_bgr().copy() to_show = utilities.as_float32(image.original_bgr) # to_show = image.copy() # to_show[:,:] = 0 for idx, pt1 in enumerate(pts): if idx % 2 == 0: color = (0, 0, 1) else: color = (1, 0, 0) pt2 = pts[(idx+1) % len(pts)] cv2.line(to_show, pt1, pt2, color, 3) # cv2.imwrite("/home/anders/UNIK4690/project/report/playground_detection_pipeline/step_11_result_2.png", utilities.as_uint8(to_show)) utilities.show(to_show, text=image.filename, time_ms=30) # show_lines(best_transformation, new_convex_hull) convex_hull = [] for idx, pt in enumerate(new_convex_hull): angle = utilities.get_angle(new_convex_hull[(idx-1)%len(new_convex_hull)], pt, new_convex_hull[(idx+1)%len(new_convex_hull)]) if 15 < angle < 180-15: convex_hull.append(pt) new_convex_hull = convex_hull # show_lines(image, new_convex_hull) angles = [] for idx, pt in enumerate(new_convex_hull): angles.append((pt, utilities.get_angle(new_convex_hull[(idx-1)%len(new_convex_hull)], pt, new_convex_hull[(idx+1)%len(new_convex_hull)]))) angles.sort(key=lambda x: x[1], reverse=True) lines = [] for idx, pt in enumerate(new_convex_hull): pt2 = new_convex_hull[(idx+1)%len(new_convex_hull)] lines.append((pt, pt2, idx)) # sort by line length lines.sort(key=lambda x: utilities.distance(x[0], x[1])) top_four = list(lines[-4:]) top_four.sort(key=lambda x: x[2]) points = [] for idx, line in enumerate(top_four): next = top_four[(idx+1) % len(top_four)] l1_p1, l1_p2, line_idx = line[0], line[1], line[2] l2_p1, l2_p2, next_idx = next[0], next[1], next[2] #print("From", l1_p1, "to", l1_p2) #print("From", l2_p1, "to", l2_p2) #print() # cv2.circle(img, l1_p1, 9, (0,0,255), 5) # cv2.circle(img, l1_p2, 9, (0,255,0), 5) l1_p1x, l1_p2x = l1_p1[0], l1_p2[0] l2_p1x, l2_p2x = l2_p1[0], l2_p2[0] l1_p1y, l1_p2y = l1_p1[1], l1_p2[1] l2_p1y, l2_p2y = l2_p1[1], l2_p2[1] def intersection(x1, y1, x2, y2, x3, y3, x4, y4): Px_upper = np.array([x1, y1, x1, 1, x2, y2, x2, 1, x3, y3, x3, 1, x4, y4, x4, 1]).reshape((4,4)) lower = np.array([x1, 1, y1, 1, x2, 1, y2, 1, x3, 1, y3, 1, x4, 1, y4, 1]).reshape((4,4)) Py_upper = Px_upper.copy() Py_upper[:,2] = Py_upper[:,1].copy() _det = np.linalg.det def det(mat): return _det(mat[:2, :2]) * _det(mat[2:, 2:]) - _det(mat[2:, :2]) * _det(mat[:2, 2:]) return (int(round(det(Px_upper) / det(lower), 0)), int(round(det(Py_upper) / det(lower), 0))) point = intersection(l1_p1x, l1_p1y, l1_p2x, l1_p2y, l2_p1x, l2_p1y, l2_p2x, l2_p2y) points.append(point) # print(points) lines = [] for idx, pt1 in enumerate(points): lines.append((pt1, points[(idx + 1) % len(points)])) # sort by line length lines.sort(key=lambda x: (x[0][0]-x[1][0])**2 + (x[0][1]-x[1][1])**2) # print("Lines:", lines) # shortest line is probably one of the short sides short_side = lines[0] # sides_in_order: First one of the short sides, then a long side, then the other short side, then the last long side sides_in_order = [short_side[0], short_side[1]] while len(sides_in_order) < 4: for line in lines: if len(sides_in_order) >= 4: break if sides_in_order[-1] == line[0]: sides_in_order.append(line[1]) show_lines(image, sides_in_order) reversed = sides_in_order[::-1] return reversed[1:] + reversed[:1] return