Esempio n. 1
0
def main():
    X = np.loadtxt('data/fish_target.txt')
    Y = np.loadtxt('data/fish_source.txt')

    fig = plt.figure()
    fig.add_axes([0, 0, 1, 1])
    callback = partial(visualize, ax=fig.axes[0])

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    reg.register(callback)
    plt.show()
Esempio n. 2
0
def main():
    X = np.loadtxt('data/bunny_target.txt')
    # synthetic data, equaivalent to X + 1
    Y = np.loadtxt('data/bunny_source.txt')

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    callback = partial(visualize, ax=ax)

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    reg.register(callback)
    plt.show()
Esempio n. 3
0
def test_2D():
    theta = np.pi / 6.0
    R = np.array([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta), np.cos(theta)]])
    t = np.array([0.5, 1.0])

    Y = np.loadtxt('data/fish_target.txt')
    X = np.dot(Y, R) + np.tile(t, (np.shape(Y)[0], 1))

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    TY, (s_reg, R_reg, t_reg) = reg.register()
    assert_almost_equal(1.0, s_reg)
    assert_array_almost_equal(R, R_reg)
    assert_array_almost_equal(t, t_reg)
    assert_array_almost_equal(X, TY)
Esempio n. 4
0
def main():
    fish_target = np.loadtxt('data/fish_target.txt')
    X = np.zeros((fish_target.shape[0], fish_target.shape[1] + 1))
    X[:, :-1] = fish_target

    fish_source = np.loadtxt('data/fish_source.txt')
    Y = np.zeros((fish_source.shape[0], fish_source.shape[1] + 1))
    Y[:, :-1] = fish_source

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    callback = partial(visualize, ax=ax)

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    reg.register(callback)
    plt.show()
Esempio n. 5
0
def _match_points_with_point_cloud_registration(dot_centers_cv : np.ndarray, local_dots_to_project : np.ndarray, approximate_pose_result : PoseResult, camera_matrix : np.ndarray, distortion_coefficients : np.ndarray, matching_style = 'rigid_registration'):
    """Matches projected (from approximate pose result) with found dot center points, using Coherent Point Drift Algorithm registration between the 2D sets of points.
    Returns lists of projected and found indices for matching points."""
    #How to match (in 2D, in particular)? Affine transformations? etc? Match by (relative) dot-to-dot distances?
    #See, for example, https://en.wikipedia.org/wiki/Point_set_registration, http://greatpanic.com/pntmatch.html, or Affine Consistency Check of Features in KLT Tracker http://cecas.clemson.edu/~stb/klt/
    #Implementations can be found in https://pypi.org/project/pycpd/, ...
    #Here we'll try to use RigidRegistration or AffineRegistration as an alternative to matching points directly by distance function
    #While this type of approach can perform fairly well with only a rough approximate pose, we find that a multi-stage matching and pose estimation approach is more consistent.

    local_dots_projected, local_dots_projected_jacobian = cv2.projectPoints(local_dots_to_project, approximate_pose_result.pose_cv.rotation_rodrigues, approximate_pose_result.pose_cv.translation, camera_matrix, distortion_coefficients)
    local_dots_projected = np.squeeze(local_dots_projected)
    registration_dictionary = {'X': dot_centers_cv, 'Y': local_dots_projected}
    
    if matching_style == 'affine_registration':
        registration = AffineRegistration(**registration_dictionary)
    else:
        registration = RigidRegistration(**registration_dictionary)
        
    registration.register()
    registration.transform_point_cloud()
    dot_centers_transformed = registration.TY

    match_cutoff_score = 0.9

    #Registration.P has shape M, N where M is num projected, N num found (in dot_centers_cv)
    projected_indices_assigned, found_indices_assigned = linear_sum_assignment(1 - registration.P)#Returns (row_indices, column_indices)
    registration_match_score_mask = registration.P[projected_indices_assigned, found_indices_assigned] > match_cutoff_score
    projected_indices, found_indices = projected_indices_assigned[registration_match_score_mask], found_indices_assigned[registration_match_score_mask]

    additional_data = { 'dot_centers_transformed' : dot_centers_transformed, 'local_dots_projected' : local_dots_projected}
    return projected_indices, found_indices, additional_data
def main():
    target_file = '' # put target file name here
    target = np.loadtxt(target_file)
    X = np.zeros((target.shape[0], target.shape[1] + 1))
    X[:, :-1] = target

    source_file = '' # put source file name here
    source = np.loadtxt(source_file)
    Y = np.zeros((source.shape[0], source.shape[1] + 1))
    Y[:, :-1] = source

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    callback = partial(visualize, ax=ax)

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    reg.register(callback)
Esempio n. 7
0
def test_3D():
    theta = np.pi / 6.0
    R = np.array([[np.cos(theta), -np.sin(theta), 0],
                  [np.sin(theta), np.cos(theta), 0], [0, 0, 1]])
    t = np.array([0.5, 1.0, -2.0])

    fish_target = np.loadtxt('data/fish_target.txt')
    Y = np.zeros((fish_target.shape[0], fish_target.shape[1] + 1))
    Y[:, :-1] = fish_target
    X = np.dot(Y, R) + np.tile(t, (np.shape(Y)[0], 1))

    reg = RigidRegistration(**{'X': X, 'Y': Y})
    TY, (s_reg, R_reg, t_reg) = reg.register()
    assert_almost_equal(1.0, s_reg)
    assert_array_almost_equal(R, R_reg)
    assert_array_almost_equal(t, t_reg)
    assert_array_almost_equal(X, TY)
Esempio n. 8
0
def main():
    # fish_target = np.loadtxt('data/fish_target.txt')
    ft='C:/00_work/05_src/data/frm_t/20201015155835/pcd_extracted.ply'
    fs='C:/00_work/05_src/data/frm_t/20201015155844/pcd_extracted.ply'
    pcdt = open3d.io.read_point_cloud(ft)
    pcds = open3d.io.read_point_cloud(fs)
    voxel_size=0.01
    keypoints_src = pcds.voxel_down_sample(voxel_size)
    keypoints_tgt = pcdt.voxel_down_sample(voxel_size)
    fish_source = np.array(keypoints_src.points)
    fish_target = np.array(keypoints_tgt.points)


    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    callback = partial(visualize, ax=ax)
    # callback = partial(save_dt)

    # reg = DeformableRegistration(**{'X': fish_target, 'Y': fish_source})
    reg = RigidRegistration(**{'X': fish_target, 'Y': fish_source})
    # reg = AffineRegistration(**{'X': fish_target, 'Y': fish_source})
    reg.register(callback)
    plt.show()
Esempio n. 9
0
def overlap_animation(reference, student, error):

    # Point set registration of reference and student
    transformed_student = []
    for idx in range(len(reference)):
        rt = RigidRegistration(X=reference[idx], Y=student[idx])
        rt.register()
        rt.transform_point_cloud()
        transformed_student.append(np.expand_dims(rt.TY, axis=0))

    student = np.concatenate(transformed_student, axis=0)

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    error_text = ax.text2D(1, 1, 'Error: 0', transform=ax.transAxes)
    
    # There are 17 joints, therefore 16 limbs
    ref_limbs = [ax.plot3D([], [], [], c='b') for _ in range(16)]
    stu_limbs = [ax.plot3D([], [], [], c='r') for _ in range(16)]
        
    limb_map = [
                [0, 1],  [1, 2], [2, 3],     # Right leg
                [0, 4],  [4, 5], [5, 6],     # Left leg
                [0, 7],  [7, 8],             # Spine
                [8, 14], [14, 15], [15, 16], # Right arm
                [8, 11], [11, 12], [12, 13], # Left arm
                [8, 9],  [9, 10]             # Neck
               ]
        
    def update_animation(idx):
        ref_frame = reference[idx]
        stu_frame = student[idx]
        
        for i in range(len(limb_map)):
            ref_limbs[i][0].set_data(ref_frame[limb_map[i], :2].T)
            ref_limbs[i][0].set_3d_properties(ref_frame[limb_map[i], 2])
            
            stu_limbs[i][0].set_data(stu_frame[limb_map[i], :2].T)
            stu_limbs[i][0].set_3d_properties(stu_frame[limb_map[i], 2])

        if idx < len(error):
            error_text.set_text('Error: {}'.format(int(error[idx])))
        
    iterations = len(reference)
    ani = animation.FuncAnimation(fig, update_animation, iterations,
                                  interval=50, blit=False, repeat=True)
    Writer = animation.writers['ffmpeg']
    writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)

    return ani, writer
Esempio n. 10
0
def initial_rigid_registration(segmentation_list, save_path, n_target=500, n_source=800, keep_id=4): 

	print "rigid registration"

	# prepare the source point cloud
	seg_path, identifier = segmentation_list[0]
	identifier = identifier.replace(" ", "")
	target_cloud = np.load(save_path + identifier + "_" + str(keep_id) + ".npy")
	indices = np.random.randint(0, target_cloud.shape[0]-1, size=n_target)
	target_cloud = target_cloud - np.mean(target_cloud, axis=0)
	target_cloud = target_cloud[indices]

	# data structures for storing transformations, correspondences
	ss = []
	Rs = []
	ts = []
	Ps = []
	corresponded_sources = []
	disparities = []
	transformed_sources = []

	# iterate over the target point clouds
	for seg_path, identifier in segmentation_list[1:]:
		
		identifier = identifier.replace(" ", "")

		print '-- ' + identifier 

		source_cloud = np.load(save_path + identifier + "_" + str(keep_id) + ".npy")
		indices_source = np.random.randint(0, source_cloud.shape[0]-1, size=n_source)
		source_cloud = source_cloud - np.mean(source_cloud, axis=0)
		if "LT" in identifier: 
			source_cloud[:,0] = -1.*source_cloud[:,0]

		source_cloud = source_cloud[indices_source]

		reg = RigidRegistration(**{'X': target_cloud, 'Y': source_cloud})
		reg.register()
		s, R, t = reg.get_registration_parameters()
		P = reg.P

		ss.append(s)
		Rs.append(R)
		ts.append(t)
		Ps.append(P)
		
		corresponded = source_cloud[np.argmax(P, axis=0), :]
		corresponded_sources.append(corresponded) 

		transformed = s*np.dot(source_cloud, R) + t
		transformed = transformed[np.argmax(P, axis=0), :]
		transformed_sources.append(transformed)

		disparity = compute_disparity(corresponded, transformed)
		disparities.append(disparity)

	transformed_sources.append(target_cloud)
	all_initial = np.array(transformed_sources)

	mean_shape = np.mean(all_initial, axis=0)

	return ss, Rs, ts, Ps, corresponded_sources, disparities, transformed_sources, mean_shape
Esempio n. 11
0
    def rigid_registration(self, pcl_data):
        """READ BOTH POINTCLOUDS"""
        self.ros_cloud = self.full_pcl
        pcl_header = pcl_data.header
        pointcloud_data = pcl_data
        xyz_array = ros_numpy.point_cloud2.pointcloud2_to_xyz_array(
            pointcloud_data)
        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(xyz_array)

        dir_path = os.path.dirname(os.path.realpath(__file__))
        #print("CURRENT PATH",dir_path)

        pcd_2 = o3d.io.read_point_cloud("container_big_upper.ply")
        pcd_2_copy = o3d.io.read_point_cloud("container_big_upper.ply")
        pcd_box = o3d.io.read_point_cloud("container_big_downsampled.ply")

        upper_1, upper_2, upper_3, upper_4 = [0.23, -0.87, 0.24], [
            -0.13, -0.93, 0.23
        ], [-0.13, -0.95, -0.53], [0.23, -0.91, -0.52]
        down_1, down_2, down_3, down_4 = [0.35, -1.3,
                                          0.27], [-0.1, -1.4, 0.26
                                                  ], [-0.093, -1.4, -0.54
                                                      ], [0.34, -1.4, -0.53]

        octapoint_array = [
            upper_1, upper_2, upper_3, upper_4, down_1, down_2, down_3, down_4
        ]

        octapoint_hull = o3d.geometry.PointCloud()
        octapoint_hull.points = o3d.utility.Vector3dVector(octapoint_array)
        """PLANE SEGMENTATION"""
        plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
                                                 ransac_n=5,
                                                 num_iterations=250)

        plane_model_2, inliers_2 = pcd_2.segment_plane(distance_threshold=0.01,
                                                       ransac_n=5,
                                                       num_iterations=250)

        plane_model_2_copy, inliers_2_copy = pcd_2_copy.segment_plane(
            distance_threshold=0.01, ransac_n=5, num_iterations=250)
        """SAVING INLIERS"""
        inlier_cloud = pcd.select_down_sample(inliers)
        inlier_cloud_2 = pcd_2.select_down_sample(inliers_2)
        inlier_cloud_2_copy = pcd_2_copy.select_down_sample(inliers_2_copy)
        """DOWNSAMPLING POINTCLOUDS"""
        downpcd = inlier_cloud
        downpcd_2 = inlier_cloud_2.voxel_down_sample(voxel_size=0.1)
        downpcd_2_copy = inlier_cloud_2_copy.voxel_down_sample(voxel_size=0.1)
        downpcd_box = pcd_box  #.voxel_down_sample(voxel_size=0.1)
        """PREPARATION OF DATA AND POINTSET REGISTRATION"""
        downpcd_as_array = np.asarray(downpcd.points)
        downpcd_2_as_array = np.asarray(downpcd_2.points)
        downpcd_2_copy_as_array = np.asarray(downpcd_2_copy.points)
        downpcd_box_as_array = np.asarray(downpcd_box.points)
        pcd_box_as_array = np.asarray(pcd_box.points)
        octapoint_hull_as_array = np.asarray(octapoint_hull.points)

        X = downpcd_as_array
        Y = downpcd_2_as_array

        reg = RigidRegistration(**{'X': X, 'Y': Y})
        reg.register()
        #plt.close(fig)

        rotation = reg.R
        translation = reg.t
        scale = reg.s

        copied_Y = np.dot(scale, downpcd_2_copy_as_array) + translation
        copied_Y = np.dot(copied_Y, rotation)
        copied_box = np.dot(scale, downpcd_box_as_array) + translation
        copied_box = np.dot(copied_box, rotation)
        troti_box = np.dot(scale, pcd_box_as_array) + translation
        troti_box = np.dot(troti_box, rotation)
        octapoint = np.dot(scale, octapoint_hull_as_array) + translation
        octapoint = np.dot(octapoint, rotation)

        wonder_container = o3d.geometry.PointCloud()
        wonder_container.points = o3d.utility.Vector3dVector(copied_Y)
        wonder_container_2 = o3d.geometry.PointCloud()
        wonder_container_2.points = o3d.utility.Vector3dVector(reg.TY)
        woner_box = o3d.geometry.PointCloud()
        woner_box.points = o3d.utility.Vector3dVector(copied_box)
        troted_box = o3d.geometry.PointCloud()
        troted_box.points = o3d.utility.Vector3dVector(troti_box)

        octabox = o3d.geometry.PointCloud()
        octabox.points = o3d.utility.Vector3dVector(octapoint)

        original_translation_2 = wonder_container.get_center(
        ) - woner_box.get_center()

        wonder_container.translate(wonder_container_2.get_center(),
                                   relative=False)
        woner_box.translate(wonder_container_2.get_center(), relative=False)
        octabox.translate(wonder_container_2.get_center(), relative=False)

        woner_box.translate(original_translation_2, relative=True)
        woner_box.rotate([[-1, 0, 0], [0, -1, 0], [0, 0, -1]], center=True)
        octabox.translate(original_translation_2, relative=True)
        octabox.rotate([[-1, 0, 0], [0, -1, 0], [0, 0, -1]], center=True)
        #woner_box.translate([0.05,0.0,0.0], relative=True)
        """PUBLISH RESULT IN ROS"""

        numpy_open3d_box = np.asarray(woner_box.points)
        self.array_to_pcd = pc2.create_cloud_xyz32(pcl_header,
                                                   numpy_open3d_box)
        self.publisher_container.publish(self.array_to_pcd)

        numpy_open3d = np.asarray(octabox.points)
        self.scaled_polygon_pcl = pc2.create_cloud_xyz32(
            pcl_header, numpy_open3d)
        self.publisher.publish(self.scaled_polygon_pcl)
Esempio n. 12
0
             horizontalalignment='center',
             verticalalignment='center',
             transform=ax.transAxes,
             fontsize='x-large')
    ax.legend(loc='upper left', fontsize='x-large')
    plt.draw()
    plt.pause(0.001)


BUFFER_SAVE_PATH = "/Users/jamesashford/Data Store/ThompsonData/lidar_scans"
with open(f'{BUFFER_SAVE_PATH}/angle1.json') as set1:
    xs, ys = json.load(set1)
    X = np.array([[x, y] for (x, y) in zip(xs, ys)])
with open(f'{BUFFER_SAVE_PATH}/angle2.json') as set2:
    xs, ys = json.load(set2)
    Y = np.array([[x, y] for (x, y) in zip(xs, ys)])

fig = plt.figure()
fig.add_axes([0, 0, 1, 1])
callback = partial(visualize, ax=fig.axes[0])

reg = RigidRegistration(**{'X': X, 'Y': Y})
reg.register(callback)
params = reg.get_registration_parameters()
print(params)

# IT WORKS!

#TODO; Use these parameters to transform the target set
#TODO; Merge the sets by nearest neighbours
#TODO; Store the params in a way that meaningfully describes the movement
Esempio n. 13
0
def compareMesh(src_mesh, tgt_mesh, tolerance):
    
    src_points = src_mesh.points(copy=True)
    tgt_points = tgt_mesh.points(copy=True)
    
    #Sample points over surface of both meshes
    src_samples = generateSamples(src_mesh, 2000)
    tgt_samples = generateSamples(tgt_mesh, 2000)

    hull_pt1, hull_pt2 = furthest_pts(src_samples)
    cnt_pnt = (hull_pt1+hull_pt2)/2
    src_points = src_points - cnt_pnt
    src_samples = src_samples - cnt_pnt
    pt_a, pt_b = furthest_pts(tgt_samples)
    orig_dist = pt_dist(pt_a, pt_b)
    new_dist = pt_dist(hull_pt1, hull_pt2)
    const_mult = orig_dist/new_dist
    src_points = src_points*const_mult
    src_samples = src_samples*const_mult
    
    
    vp = Plotter(interactive=0, axes=7, size='fullscreen', bg='bb')
    vp.legendBC = (0.22, 0.22, 0.22)
    vp.legendPos = 1
    txt = Text2D("Loading Models...", pos = 8, c='gray', s=1.31)
    vp += txt
    tgt_pts = Points(tgt_samples, r=6, c='deepskyblue', alpha= 1).legend("Target")
    vp += tgt_pts
    vp.show()
    txt.SetText(7, "Initiating Alignment")
    src_pts = Points(src_samples, r=6, c='yellow', alpha = 1).legend("Source")
    vp += src_pts
    vp.show()

    #Roughly align both meshes (global registration)
    spacing = np.mean(distance.pdist(src_samples))
    src_samples, src_points = perform_global_registration(src_samples,tgt_samples,src_points, spacing)

    
    txt.SetText(7, "Refining Alignment")
    vp.show()

    #Refine mesh alignment (local registration)
    cpd_ittr = 60
    callback = partial(visualize, vp=vp, pts = src_pts, text = txt, max_ittr = cpd_ittr)
    reg = RigidRegistration(max_iterations = cpd_ittr, **{ 'X': tgt_samples, 'Y': src_samples })
    src_samples, [s,R,t] = reg.register(callback)
    src_points = s*np.dot(src_points, R) + t
    src_pts.points(src_samples)

    
    vp.renderer.RemoveAllViewProps()
    txt.SetText(7, "Alignment Complete")
    vp.show()

    
    for i in range(360):
        if i == 60:
            txt.SetText(7, "")
        vp.camera.Azimuth(.75)
        vp.show()


    src_mesh.points(src_points)

    tgt_samples = generateSamples(tgt_mesh, 6000)
    txt.SetText(7,"Performing Added Surface Analysis...")
    vp.show()


    ratio = 2000/min(len(tgt_points), len(src_points))
    spacing = 3*spacing*ratio
    #Generate distances for heat map
    dists = distance.cdist(src_points,tgt_samples).min(axis=1)
    txt.SetText(7,"Press Q to Continue")
    vp.show(interactive=1)
    show_mesh(src_mesh, dists, vp, spacing/2, tolerance=tolerance)
    txt2 = Text2D("Displaying Input Object 1 \n \nUse slider to isolate \ndefective/added surfaces")
    vp += txt2
    vp.addGlobalAxes(axtype=8, c='white')
    vp.show(axes=8, interactive=1)
    txt.SetText(7,"Performing Missing Surface Analysis...")
    vp += txt
    vp.show(interactive=0)
    src_mesh.points(src_points)
    src_samples = generateSamples(src_mesh, 6000)
    #Generate distances for heat map
    dists = distance.cdist(tgt_points,src_samples).min(axis=1)
    show_mesh(tgt_mesh, dists, vp, spacing/2, tolerance=tolerance)
    txt2.SetText(2,"Displaying Input Object 2 \n \nUse slider to isolate \ndefective/missing surfaces")
    vp += txt2
    vp.addGlobalAxes(axtype=8, c='white')
    vp.show(axes=8, interactive=1)