def write(self): """ Writes stable pose data for meshes in the input directory to an stp file. path -- path to directory containing meshes to be converted to .stp """ min_prob_str = sys.argv[1] min_prob = float(min_prob_str) mesh_index = 1 mesh_files = [filename for filename in os.listdir(sys.argv[2]) if filename[-4:] == ".obj"] for filename in mesh_files: print "Writing file: " + sys.argv[2] + "/" + filename ob = obj_file.ObjFile(sys.argv[2] + "/" + filename) mesh = ob.read() mesh.remove_unreferenced_vertices() prob_mapping, cv_hull = st.compute_stable_poses(mesh), mesh.convex_hull() R_list = [] for face, p in prob_mapping.items(): if p >= min_prob: vertices = [cv_hull.vertices()[i] for i in face] basis = st.compute_basis(vertices, cv_hull) R_list.append([p, basis]) self.write_mesh_stable_poses(mesh, filename, min_prob)
def write_mesh_stable_poses(self, mesh, filename, min_prob=0, vis=False): prob_mapping, cv_hull = st.compute_stable_poses(mesh), mesh.convex_hull() R_list = [] for face, p in prob_mapping.items(): if p >= min_prob: x0 = np.array(cv_hull.vertices()[face[0]]) R_list.append([p, st.compute_basis([cv_hull.vertices()[i] for i in face], cv_hull), x0]) if vis: print 'P', R_list[0][0] mv.figure() mesh.visualize() mv.axes() mv.figure() cv_hull_tf = cv_hull.transform(stf.SimilarityTransform3D(tfx.transform(R_list[0][1], np.zeros(3)))) cv_hull_tf.visualize() mv.axes() mv.show() f = open(filename[:-4] + ".stp", "w") f.write("#############################################################\n") f.write("# STP file generated by UC Berkeley Automation Sciences Lab #\n") f.write("# #\n") f.write("# Num Poses: %d" %len(R_list)) for _ in range(46 - len(str(len(R_list)))): f.write(" ") f.write(" #\n") f.write("# Min Probability: %s" %str(min_prob)) for _ in range(40 - len(str(min_prob))): f.write(" ") f.write(" #\n") f.write("# #\n") f.write("#############################################################\n") f.write("\n") # adding R matrices to .stp file pose_index = 1 for i in range(len(R_list)): f.write("p %f\n" %R_list[i][0]) f.write("r %f %f %f\n" %(R_list[i][1][0][0], R_list[i][1][0][1], R_list[i][1][0][2])) f.write(" %f %f %f\n" %(R_list[i][1][1][0], R_list[i][1][1][1], R_list[i][1][1][2])) f.write(" %f %f %f\n" %(R_list[i][1][2][0], R_list[i][1][2][1], R_list[i][1][2][2])) f.write("x0 %f %f %f\n" %(R_list[i][2][0], R_list[i][2][1], R_list[i][2][2])) f.write("\n\n")
def transform_meshes(path): """ Transforms meshes in the directory given by path based on their highest probability stable poses. path -- path leading to directory containing meshes num_poses -- variable denoting number of desired poses per object """ f = open() # write header f.write('###########################################################\n') f.write('# POSE TRANSFORM DATA file generated by UC Berkeley Automation Sciences Lab\n') f.write('#\n') min_prob = sys.argv[1] for filename in os.listdir(path): if filename[-4:] == ".obj": ob = obj_file.ObjFile(path + "/" + filename) mesh = ob.read() mesh.remove_unreferenced_vertices() prob_mapping, cv_hull = compute_stable_poses(mesh), mesh.convex_hull() R_list = [] for face, p in prob_mapping.items(): if p >= min_prob: R_list.append([p, compute_basis([cv_hull.vertices()[i] for i in face])]) # write necessary data to compute each pose (R and pose probability) for i in range(len(R_list)): f.write('# Pose ' + str(i + 1) + ':\n') f.write('# Probability: ' + str(R_list[i][0]) + '\n') for p in range(3): f.write(str(R_list[i][1][p][0]) + ' ' + str(R_list[i][1][p][1]) + ' ' + str(R_list[i][1][p][2]) + '\n') f.write('#\n') f.write('###########################################################\n') f.write('\n')
def compute_stable_poses(mesh): """ Computes convex hull of the input mesh and returns stable final faces along with corresponding probabilities. mesh -- a 3D Mesh object """ convex_hull = mesh.convex_hull() cm = mesh.center_of_mass # mapping each edge in the convex hull to the two faces it borders triangles, vertices, edge_to_faces, triangle_to_vertex = convex_hull.triangles(), convex_hull.vertices(), {}, {} max_tri = None max_area = 0 i = 0 for triangle in triangles: triangle_vertices = [vertices[i] for i in triangle] e1, e2, e3 = Segment(triangle_vertices[0], triangle_vertices[1]), Segment(triangle_vertices[0], triangle_vertices[2]), Segment(triangle_vertices[1], triangle_vertices[2]) for edge in [e1, e2, e3]: # order vertices for consistent hashing p_1, p_2 = tuple(edge.endpoint_1), tuple(edge.endpoint_2) k = (p_1, p_2) if p_1[0] < p_2[0]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] < p_2[1]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] == p_2[1] and p_1[2] < p_2[2]: k = (p_2, p_1) if k in edge_to_faces: edge_to_faces[k] += [triangle] else: edge_to_faces[k] = [triangle] v = np.array(triangle_vertices) n = np.cross(v[1,:] - v[0,:], v[2,:] - v[0,:]) n = n / np.linalg.norm(n) t1 = np.array([n[1], -n[0], 0]) t1 = t1 / np.linalg.norm(t1) t2 = np.cross(t1, n) A = np.c_[t1, t2] x = v.dot(A) x = np.c_[x, np.ones(3)] area = abs(np.linalg.norm(x)) if area > max_area: max_area = area max_tri = [triangle[0], triangle[1], triangle[2]] p_i = compute_projected_area(triangle_vertices, cm) / (4 * math.pi) vt = Vertex(p_i, triangle) triangle_to_vertex[tuple(triangle)] = vt """ print p_i print triangle[0], triangle[1], triangle[2] if abs(n.dot(np.array([0,0,1]))) > 0.95: mv.figure() convex_hull.visualize() mv.points3d(cm[0], cm[1], cm[2], scale_factor=0.005, color=(1,0,0)) mv.points3d(v[:,0], v[:,1], v[:,2], scale_factor=0.005) mv.axes() mv.show() """ # determining if landing on a given face implies toppling, and initializes a directed acyclic graph # a directed edge between two graph nodes implies that landing on one face will lead to toppling onto its successor # an outdegree of 0 for any graph node implies it is a sink (the object will come to rest if it topples to this face) for triangle in triangles: triangle_vertices = [vertices[i] for i in triangle] # computation of projection of cm onto plane of face v_0 = np.subtract(triangle_vertices[2], triangle_vertices[0]) v_1 = np.subtract(triangle_vertices[1], triangle_vertices[0]) w = np.array(triangle_vertices).T v_0 = v_0 / np.linalg.norm(v_0) v_1 = v_1 / np.linalg.norm(v_1) normal_vector = np.cross(v_0, v_1) origin_point = np.array(triangle_vertices[0]) normal_vector = normal_vector / np.linalg.norm(normal_vector) proj_vector = np.subtract(cm, origin_point) dist = np.dot(normal_vector, proj_vector) proj_cm = np.subtract(cm, dist*normal_vector) # barycentric coordinates/minimum distance analysis (adapted from implementation provided at http://www.blackpawn.com/texts/pointinpoly/) dim = 3 P = cvx.matrix(2 * w.T.dot(w)) q = cvx.matrix(-2 * proj_cm.T.dot(w)) G = cvx.matrix(-np.eye(dim)) h = cvx.matrix(np.zeros(dim)) A = cvx.matrix(np.ones((1, dim))) b = cvx.matrix(np.ones(1)) sol = cvx.solvers.qp(P, q, G, h, A, b) u = np.array(sol['x']) norm_diff = np.sqrt(sol['primal objective'] + proj_cm.T.dot(proj_cm)) p = w.dot(u) proj_cm_in_triangle = norm_diff < 1e-4 """ if triangle[0] == 807 and triangle[1] == 742 and triangle[2] == 739: mv.figure() convex_hull.visualize() mv.points3d(cm[0], cm[1], cm[2], scale_factor=0.005, color=(1,0,0)) mv.points3d(proj_cm[0], proj_cm[1], proj_cm[2], scale_factor=0.005, color=(0,1,0)) mv.points3d(w[0,:], w[1,:], w[2,:], scale_factor=0.005) mv.points3d(p[0], p[1], p[2], scale_factor=0.005, color=(0,0,1)) mv.axes() mv.show() IPython.embed() """ # update list of top vertices, add edges between vertices as needed if not proj_cm_in_triangle: s1, s2, s3 = Segment(triangle_vertices[0], triangle_vertices[1]), Segment(triangle_vertices[0], triangle_vertices[2]), Segment(triangle_vertices[1], triangle_vertices[2]) closest_edges, common_endpoint = closest_segment(proj_cm, [s1, s2, s3]) if len(closest_edges) > 1: index = triangle_vertices.index(common_endpoint) if index == len(triangle_vertices) - 1: index = 0 else: index = index + 1 closest_edge = Segment(common_endpoint, triangle_vertices[index]) else: closest_edge = closest_edges[0] # order vertices for consistent hashing p_1, p_2 = tuple(closest_edge.endpoint_1), tuple(closest_edge.endpoint_2) k = (p_1, p_2) if p_1[0] < p_2[0]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] < p_2[1]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] == p_2[1] and p_1[2] < p_2[2]: k = (p_2, p_1) for face in edge_to_faces[k]: if list(face) != list(triangle): topple_face = face #if triangle[0] == 807 and triangle[1] == 742 and triangle[2] == 739: # IPython.embed() predecessor, successor = triangle_to_vertex[tuple(triangle)], triangle_to_vertex[tuple(topple_face)] predecessor.add_edge(successor) probabilities = propagate_probabilities(triangle_to_vertex.values()) return probabilities
def main (argv): nodule_model = Model(FLAGS.prob, FLAGS.mode, FLAGS.fts, FLAGS.channels, FLAGS.prob_dropout, FLAGS.fts_dropout) with open(os.path.join('models', FLAGS.score), 'rb') as f: score_model = pickle.load(f) case = FsCase(FLAGS.input) case.normalizeHU() case = case.rescale3D(SPACING) lung, _ = mesh.segment_lung(case.images) save_mesh(lung, os.path.join(FLAGS.output, 'lung')) mask = mesh.convex_hull(lung) #body, _ = mesh.segment_body(case.images) #save_mesh(body, os.path.join(FLAGS.output, 'body')) case.standardize_color() case.round_stride(FLAGS.stride) mask = case.copy_replace_images(mask) mask.round_stride(FLAGS.stride) mask = mask.images views = [case.transpose(AXIAL), case.transpose(SAGITTAL), case.transpose(CORONAL)] if FLAGS.dilate > 0: ksize = FLAGS.dilate * 2 + 1 mask = grey_dilation(mask, size=(ksize, ksize, ksize), mode='constant') pass if True: with tf.Session() as sess: tf.global_variables_initializer().run() nodule_model.load(sess) dim, nodules = nodule_model.apply(sess, views, mask) pass pass else: dim = 11 nodules = [] fts = [] pos = [] #print(nodules) fts.append(pyramid(dim, nodules)) # global pos.append(None) # global for nodule in nodules: fts.append(pyramid(dim, [nodule])) pos.append(nodule[3]) pass Nt = np.array(fts, dtype=np.float32) Ny = score_model.predict_proba(Nt)[:,1] global_score = float(Ny[0]) #print('GLOBAL SCORE:', global_score) pw = sorted(zip(pos, list(Ny)), key=lambda x:x[1], reverse=True) gal = Gallery(FLAGS.output, cols=5, header=['nodule','score','axial','sagittal','coronal']) anno = Annotations() C = 1 for box, score in pw: if box is None: continue if score < 0.1: break anno.add(box, str(score)) gal.text('%d' % C) gal.text('%.4f' % score) for v in VIEWS: cc, (y0, x0, y1, x1) = box_center(box, v) view = views[v] image = get3c(view.images, cc) cv2.rectangle(image, (x0,y0), (x1,y1), (0,255,255)) if v == AXIAL: image = cv2.flip(image, 1) elif v == SAGITTAL: image = cv2.transpose(image) image = cv2.flip(image, 0) elif v == CORONAL: image = cv2.flip(image, -1) cv2.imwrite(gal.next(), image) pass C += 1 pass gal.flush('plumo.html', extra={'score':global_score}) Papaya(os.path.join(FLAGS.output, 'papaya'), case, annotations=anno) pass
def compute_stable_poses(mesh): """ Computes convex hull of the input mesh and returns stable final faces along with corresponding probabilities. mesh -- a 3D Mesh object """ convex_hull, cm = mesh.convex_hull(), mesh.vertex_mean_ # mapping each edge in the convex hull to the two faces it borders triangles, vertices, edge_to_faces, triangle_to_vertex = convex_hull.triangles(), convex_hull.vertices(), {}, {} for triangle in triangles: triangle_vertices = [vertices[i] for i in triangle] e1, e2, e3 = Segment(triangle_vertices[0], triangle_vertices[1]), Segment(triangle_vertices[0], triangle_vertices[2]), Segment(triangle_vertices[1], triangle_vertices[2]) for edge in [e1, e2, e3]: # order vertices for consistent hashing p_1, p_2 = tuple(edge.endpoint_1), tuple(edge.endpoint_2) k = (p_1, p_2) if p_1[0] < p_2[0]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] < p_2[1]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] == p_2[1] and p_1[2] < p_2[2]: k = (p_2, p_1) if k in edge_to_faces: edge_to_faces[k] += [triangle] else: edge_to_faces[k] = [triangle] p_i = compute_projected_area(triangle_vertices, cm) / (4 * math.pi) v = Vertex(p_i, triangle) triangle_to_vertex[tuple(triangle)] = v # determining if landing on a given face implies toppling, and initializes a directed acyclic graph # a directed edge between two graph nodes implies that landing on one face will lead to toppling onto its successor # an outdegree of 0 for any graph node implies it is a sink (the object will come to rest if it topples to this face) for triangle in triangles: triangle_vertices = [vertices[i] for i in triangle] # computation of projection of cm onto plane of face v_0 = np.subtract(triangle_vertices[2], triangle_vertices[0]) v_1 = np.subtract(triangle_vertices[1], triangle_vertices[0]) v_0 = v_0 / np.linalg.norm(v_0) v_1 = v_1 / np.linalg.norm(v_1) normal_vector = np.cross(v_0, v_1) origin_point = np.array(triangle_vertices[0]) normal_vector = normal_vector / np.linalg.norm(normal_vector) proj_vector = np.subtract(cm, origin_point) dist = np.dot(normal_vector, proj_vector) proj_cm = np.subtract(cm, dist*normal_vector) other_dist = np.linalg.norm(cm - np.array(triangle_vertices[1])) # barycentric coordinates/minimum distance analysis (adapted from implementation provided at http://www.blackpawn.com/texts/pointinpoly/) v_2 = np.subtract(proj_cm, triangle_vertices[0]) dot_00 = np.dot(v_0, v_0) dot_01 = np.dot(v_0, v_1) dot_02 = np.dot(v_0, v_2) dot_11 = np.dot(v_1, v_1) dot_12 = np.dot(v_1, v_2) inv_denom = 1.0 / (dot_00 * dot_11 - dot_01 * dot_01) u = (dot_11 * dot_02 - dot_01 * dot_12) * inv_denom v = (dot_00 * dot_12 - dot_01 * dot_02) * inv_denom proj_cm_in_triangle = (u >= 0) and (v >= 0) and (u + v < 1) # update list of top vertices, add edges between vertices as needed if not proj_cm_in_triangle: s1, s2, s3 = Segment(triangle_vertices[0], triangle_vertices[1]), Segment(triangle_vertices[0], triangle_vertices[2]), Segment(triangle_vertices[1], triangle_vertices[2]) closest_edges, common_endpoint = closest_segment(proj_cm, [s1, s2, s3]) if len(closest_edges) > 1: index = triangle_vertices.index(common_endpoint) if index == len(triangle_vertices) - 1: index = 0 else: index = index + 1 closest_edge = Segment(common_endpoint, triangle_vertices[index]) else: closest_edge = closest_edges[0] # order vertices for consistent hashing p_1, p_2 = tuple(closest_edge.endpoint_1), tuple(closest_edge.endpoint_2) k = (p_1, p_2) if p_1[0] < p_2[0]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] < p_2[1]: k = (p_2, p_1) elif p_1[0] == p_2[0] and p_1[1] == p_2[1] and p_1[2] < p_2[2]: k = (p_2, p_1) for face in edge_to_faces[k]: if list(face) != list(triangle): topple_face = face predecessor, successor = triangle_to_vertex[tuple(triangle)], triangle_to_vertex[tuple(topple_face)] predecessor.add_edge(successor) probabilities = propagate_probabilities(triangle_to_vertex.values()) return probabilities