def fast_global_registration(): """ Execute fast global registration Based on http://www.open3d.org/docs/tutorial/Advanced/fast_global_registration.html """ node = hou.pwd() node_geo = node.geometry() node_geo_target = node.inputs()[1].geometry() voxel_size = node.parm("voxel_size").eval() transform = node.parm("transform").eval() has_fpfh_source = bool(node_geo.findPointAttrib("fpfh")) has_fpfh_target = bool(node_geo_target.findPointAttrib("fpfh")) if not has_fpfh_source or not has_fpfh_target: raise hou.NodeError("One of the inputs does not have 'fpfh' attribute.") # to numpy np_pos_str_source = node_geo.pointFloatAttribValuesAsString("P", float_type=hou.numericData.Float32) np_pos_source = np.fromstring(np_pos_str_source, dtype=np.float32).reshape(-1, 3) np_fpfh_str_source = node_geo.pointFloatAttribValuesAsString("fpfh", float_type=hou.numericData.Float32) np_fpfh_size = node_geo.findPointAttrib("fpfh").size() np_fpfh_source = np.fromstring(np_fpfh_str_source, dtype=np.float32).reshape(-1, np_fpfh_size) np_fpfh_source = np.swapaxes(np_fpfh_source, 1, 0) np_pos_str_target = node_geo_target.pointFloatAttribValuesAsString("P", float_type=hou.numericData.Float32) np_pos_target = np.fromstring(np_pos_str_target, dtype=np.float32).reshape(-1, 3) np_fpfh_str_target = node_geo_target.pointFloatAttribValuesAsString("fpfh", float_type=hou.numericData.Float32) np_fpfh_target = np.fromstring(np_fpfh_str_target, dtype=np.float32).reshape(-1, np_fpfh_size) np_fpfh_target = np.swapaxes(np_fpfh_target, 1, 0) # to open3d source = open3d.PointCloud() source.points = open3d.Vector3dVector(np_pos_source.astype(np.float64)) source_fpfh = open3d.registration.Feature() source_fpfh.resize(np_fpfh_source.shape[0], np_fpfh_source.shape[1]) source_fpfh.data = np_fpfh_source.astype(np.float64) target = open3d.PointCloud() target.points = open3d.Vector3dVector(np_pos_target.astype(np.float64)) target_fpfh = open3d.registration.Feature() target_fpfh.resize(np_fpfh_source.shape[0], np_fpfh_source.shape[1]) target_fpfh.data = np_fpfh_target.astype(np.float64) # registration registration = open3d.registration_fast_based_on_feature_matching(source, target, source_fpfh, target_fpfh, open3d.FastGlobalRegistrationOption(maximum_correspondence_distance = voxel_size * 0.5)) registration_xform = hou.Matrix4(registration.transformation) registration_xform = registration_xform.transposed() # to houdini if transform: node_geo.transform(registration_xform) node_geo.addAttrib(hou.attribType.Global, "xform", default_value=(0.0,)*16, create_local_variable=False) node_geo.setGlobalAttribValue("xform", registration_xform.asTuple())
def setText(): folder = hou.pwd().parm("type").evalAsString() file = hou.pwd().parm("file").evalAsString() file = file + ".txt" roots = "/".join([root, folder, file]) try: f = open(roots, "r") n = f.readlines() f.close() except hou.LoadWarning: hou.NodeError("don't exist the file") ctx = "" for nn in n: ctx += nn result = hou.pwd().parm("snippet").eval() if result != "": ctx = result + "\n" + ctx hou.pwd().parm("snippet").set(ctx, follow_parm_reference=True) else: hou.pwd().parm("snippet").set(ctx, follow_parm_reference=True)
def nodeUpdate(): """Cook the node. This method is called by Houdini when the node is cooking. """ # Get a handle to the node self = hou.pwd() # Activate the node's warning/error flag based on the severity # attribute severity = self.parm('severity').evalAsInt() message = self.parm('message').evalAsString() if severity == 1: raise hou.NodeWarning(message) elif severity == 2: raise hou.NodeError(message) # Update the node if it has not beed updated yet and set it's update # flag if not self.cachedUserData('loaded'): hou.phm().loadDataCallback() self.setCachedUserData('loaded', True)
def read(node, geo, child, type): nodePath = node.path() function = inspect.stack()[0][3] try: missingframe = node.evalParm("missingframe") enableTile = node.evalParm("enableTile") skipInput = node.evalParm("skipInput") filePath = node.hm().path.filePath(node) dataList = [] if skipInput or len(node.node("IN").inputs()) == 0: g_dataList = [] if type == "cells": if enableTile: get_cell_num = child.inputs()[2].geometry() g_dataList = get_cell_num.attribValue("dataList") g_dataList = [ str(int(c)).zfill(5) for c in g_dataList.split(',') ] try: _dataList = node.evalParm("dataList").replace(' ', '') dataList = [ str(int(c)).zfill(5) for c in _dataList.split(',') ] dataList += g_dataList except ValueError: if not g_dataList: if missingframe == 0: raise hou.NodeError("Invalid " + type + " parameter") else: raise hou.NodeWarning("Invalid " + type + " parameter") else: dataList = g_dataList elif type == "tiles": get_tile_num = child.inputs()[2].geometry() try: g_dataList = get_tile_num.attribValue("dataList") g_dataList = [ str("x" + t.replace("_", "_y")) for t in g_dataList.split(',') ] except: print("No Data List...exiting") return if not g_dataList: if missingframe == 0: raise hou.NodeError("Invalid " + type + " parameter") else: raise hou.NodeWarning("Invalid " + type + " parameter") else: dataList = g_dataList else: input_geo = child.inputs()[1].geometry() _dataList = input_geo.attribValue("dataList") if not _dataList: if missingframe == 0: raise hou.NodeError( "'dataList' detail attribute not found on input") else: raise hou.NodeWarning( "'dataList' detail attribute not found on input") if type == "cells": dataList = [str(int(c)).zfill(5) for c in _dataList.split(',')] elif type == "tiles": dataList = [ str("x" + t.replace("_", "_y")) for t in _dataList.split(',') ] if not dataList: if missingframe == 0: raise hou.NodeError(type + " parameter is empty") else: raise hou.NodeWarning(type + " parameter is empty") dataList = list(set(dataList)) for data in dataList: if type == "cells": file = filePath.replace("%CELLNUM%", data) elif type == "tiles": file = filePath.replace("%TILENUM%", data) if not os.path.exists(file): continue if os.path.getsize(file) == 594L: continue node.hm().file.load(node, geo, file) except (KeyboardInterrupt, SystemExit): print("Interrupt requested of " + function + " for " + nodePath + "...exiting") return
def readPattern(node, geo, child, type): nodePath = node.path() function = inspect.stack()[0][3] try: missingframe = node.evalParm("missingframe") skipInput = node.evalParm("skipInput") enableTile = node.evalParm("enableTile") folderSubType = node.hm().path.folderSubType(node) label_pattern = node.evalParm("label") prefix_pattern = node.evalParm("prefix") filePath = node.hm().path.filePath(node) dataList = [] if skipInput or len(node.node("IN").inputs()) == 0: g_dataList = [] if type == "cells": if enableTile: get_cell_num = child.inputs()[2].geometry() g_dataList = get_cell_num.attribValue("dataList") g_dataList = [ str(int(c)).zfill(5) for c in g_dataList.split(',') ] try: _dataList = node.evalParm("dataList").replace(' ', '') dataList = [ str(int(c)).zfill(5) for c in _dataList.split(',') ] dataList += g_dataList except ValueError: if not g_list: if missingframe == 0: raise hou.NodeError("Invalid data parameter") else: raise hou.NodeWarning("Invalid data parameter") else: dataList = g_dataList elif type == "tiles": get_tile_num = child.inputs()[2].geometry() g_dataList = get_tile_num.attribValue("dataList") g_dataList = [ str("x" + t.replace("_", "_y")) for t in g_dataList.split(',') ] if not g_dataList: if missingframe == 0: raise hou.NodeError("Invalid data parameter") else: raise hou.NodeWarning("Invalid data parameter") else: dataList = g_dataList else: input_geo = child.inputs()[1].geometry() _dataList = input_geo.attribValue("dataList") if not _dataList: if missingframe == 0: raise hou.NodeError( "'dataList' detail attribute not found on input") else: raise hou.NodeWarning( "'dataList' detail attribute not found on input") if type == "cells": dataList = [ str("x" + t.replace("_", "_y")) for t in _dataList.split(',') ] if type == "tiles": dataList = [str(int(c)).zfill(5) for c in _dataList.split(',')] if not dataList: if missingframe == 0: if missingframe == 0: raise hou.NodeError("data parameter is empty") else: raise hou.NodeWarning("data parameter is empty") try: dataList = list(set(dataList)) path_root = os.path.dirname(filePath) if type == "cells": valid_files = [f for f in os.listdir(path_root) if \ f.split('_')[-1].split('.', 1)[0] in dataList] if type == "tiles": valid_files = [f for f in os.listdir(path_root) if \ f.split('.')[0][-7:] in dataList] for f in valid_files: # check if label matches if label_pattern and label_pattern != '*': current = f.split(folderSubType + '_')[-1] if type == "cells": file_label = current.split("cell")[0] if type == "tiles": current = current.split('.', 1)[0] file_label = current.replace(current[-8:], '') # doesn't have label if not file_label: continue if not hou.patternMatch(label_pattern, file_label): continue # check if prefix matches if prefix_pattern and prefix_pattern != '*': _p = f.split(folderSubType)[0] if not _p: continue if not hou.patternMatch(prefix_pattern, _p): continue file = path_root + '/' + f node.hm().file.load(node, geo, file) except WindowsError: print("Path error: " + filePath) except (KeyboardInterrupt, SystemExit): print("Interrupt requested of " + function + " for " + nodePath + "...exiting") return
def icp_registration(): """ Execute Point-to-plane ICP registration TODO: Add point-to-plane ICP option (and update normals) Based on http://www.open3d.org/docs/tutorial/Basic/icp_registration.html#point-to-plane-icp """ node = hou.pwd() node_geo = node.geometry() node_geo_target = node.inputs()[1].geometry() threshold = node.parm("threshold").eval() transform = node.parm("transform").eval() max_iter = node.parm("max_iter").eval() single_pass = node.parm("single_pass").eval() has_xform_source = bool(node_geo.findGlobalAttrib("xform")) has_n_source = bool(node_geo.findPointAttrib("N")) has_n_target = bool(node_geo_target.findPointAttrib("N")) if not has_xform_source: node_geo.addAttrib(hou.attribType.Global, "xform", default_value=(0.0,)*16, create_local_variable=False) if not has_n_source or not has_n_target: raise hou.NodeError("One of the inputs does not have 'N' attribute.") trans_init = node_geo.floatListAttribValue("xform") trans_init = np.array(trans_init).reshape(4,4).T # to numpy np_pos_str_source = node_geo.pointFloatAttribValuesAsString("P", float_type=hou.numericData.Float32) np_pos_source = np.fromstring(np_pos_str_source, dtype=np.float32).reshape(-1, 3) np_n_str_source = node_geo.pointFloatAttribValuesAsString("N", float_type=hou.numericData.Float32) np_n_source = np.fromstring(np_n_str_source, dtype=np.float32).reshape(-1, 3) np_pos_str_target = node_geo_target.pointFloatAttribValuesAsString("P", float_type=hou.numericData.Float32) np_pos_target = np.fromstring(np_pos_str_target, dtype=np.float32).reshape(-1, 3) np_n_str_target = node_geo_target.pointFloatAttribValuesAsString("N", float_type=hou.numericData.Float32) np_n_target = np.fromstring(np_n_str_target, dtype=np.float32).reshape(-1, 3) # to open3d source = open3d.PointCloud() source.points = open3d.Vector3dVector(np_pos_source.astype(np.float64)) source.normals = open3d.Vector3dVector(np_n_source.astype(np.float64)) target = open3d.PointCloud() target.points = open3d.Vector3dVector(np_pos_target.astype(np.float64)) target.normals = open3d.Vector3dVector(np_n_target.astype(np.float64)) # icp #init_evaluation = open3d.evaluate_registration(source, target, threshold, trans_init) if single_pass: reg_p2l = open3d.registration_icp(source, target, threshold, np.identity(4), open3d.TransformationEstimationPointToPoint(), open3d.ICPConvergenceCriteria(max_iteration=1)) else: reg_p2l = open3d.registration_icp(source, target, threshold, trans_init, open3d.TransformationEstimationPointToPoint(), open3d.ICPConvergenceCriteria(max_iteration=max_iter)) # print init_evaluation # print reg_p2l # to houdini registration_xform = hou.Matrix4(reg_p2l.transformation) registration_xform = registration_xform.transposed() if transform: node_geo.transform(registration_xform) node_geo.setGlobalAttribValue("xform", registration_xform.asTuple())
def track(node): leap = hou.session.leap if not leap.is_enabled(): raise hou.NodeError("Leap Device not enabled") geo = node.geometry() frame = leap.get_frame() if not frame: raise hou.NodeError("Can't read frame") f_group = geo.findPointGroup("fingers") h_group = geo.findPointGroup("hands") a_group = geo.findPointGroup("arms") t_group = geo.findPointGroup("tips") # hands for i, h in enumerate(frame.hands, start=1): if node.parent().evalParm("hands"): p = geo.createPoint() p.setPosition(leap_to_hou(h.palm_position)) p.setAttribValue("dir", leap_to_hou(h.direction)) p.setAttribValue("palm_N", leap_to_hou(h.palm_normal)) p.setAttribValue("palm_width", h.palm_width) p.setAttribValue("hand", i) h_group.add(p) # fingers for j, f in enumerate(h.fingers): bones = [ f.bone(Leap.Bone.TYPE_PROXIMAL), f.bone(Leap.Bone.TYPE_INTERMEDIATE), f.bone(Leap.Bone.TYPE_DISTAL) ] # don't track metacarpal bone for thumbs if j > 0: bones.insert(0, f.bone(Leap.Bone.TYPE_METACARPAL)) prim = geo.createPolygon() prim.setIsClosed(False) # bones for k, bone in enumerate(bones): hou_d = leap_to_hou(bone.direction) p = geo.createPoint() p.setPosition(leap_to_hou(bone.prev_joint)) p.setAttribValue("finger", j) p.setAttribValue("bone", k) p.setAttribValue("hand", i) p.setAttribValue("dir", hou_d) f_group.add(p) prim.addVertex(p) if k == len(bones) - 1: p = geo.createPoint() p.setPosition(leap_to_hou(bone.next_joint)) p.setAttribValue("finger", j) p.setAttribValue("bone", k) p.setAttribValue("hand", i) p.setAttribValue("dir", hou_d) f_group.add(p) t_group.add(p) prim.addVertex(p) if node.parent().evalParm("arms"): prim = geo.createPolygon() prim.setIsClosed(False) p = geo.createPoint() # wrist p.setPosition(leap_to_hou(h.arm.wrist_position)) p.setAttribValue("hand", i) p.setAttribValue("dir", leap_to_hou(h.arm.direction)) p.setAttribValue("arm_width", h.arm.width) a_group.add(p) prim.addVertex(p) p = geo.createPoint() # elbow p.setPosition(leap_to_hou(h.arm.elbow_position)) p.setAttribValue("hand", i) p.setAttribValue("dir", leap_to_hou(h.arm.direction)) a_group.add(p) prim.addVertex(p)
def raise_not_init(node): set_node_comment(node, "Leap not initialized") raise hou.NodeError("Leap not initialized")