Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
 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
Пример #4
0
 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
Пример #5
0
 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)
Пример #6
0
 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)
Пример #7
0
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
Пример #8
0
    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