def dragCB(view, data): vi = view.drag_data #print 'dragCB',data,vi offset = (view.mouseDx * view.toolRX + view.mouseDy * view.toolRY) move_vertex(view, vi, offset[:2], delta=True) State.push('move vertex') QApp.app.updateMenus()
def buildOps(self, filename, win): # Check if the state contains a recipe as we can't continue without it since the order (graph) is unknown if not State.hasKey('/recipe'): return # Get the recipe and available ops recipe = State.getKey('/recipe') registeredOps = Registry.getRegisteredOps() # Go through the recipe in order for op in recipe: opName, opType = op # Look up the corresponding State data and check if the type corresponds to a registered Op opTypeKey = opName + '/type' if not State.hasKey(opName) or not State.hasKey(opTypeKey): return opType_state = State.getKey(opTypeKey)[1:] if opType_state not in registeredOps: continue # Get the Op from the registration factory and create the op (without duplicating the State entry) self._addOp(registeredOps[opType_state], win, initialiseState=False, name=opName) self.interface.reset() self.cookOps(win, self.getFrame(), forceRecook=True) if win: win.updateGL() win.updateLayers()
def images_shapes_not_all_labels_unmarked(): images = State.getKey('/images') shapes = State.getKey('/shapes') labels = State.getKey('/labels') which = np.where(np.sum(np.int32(labels) == 0, axis=1) == 0)[0] return [JPEG.decompress(images[x]) for x in which ], [shapes[x] for x in which], [labels[x] for x in which]
def train(): images, shapes, labels = images_shapes_not_all_labels_unmarked() flip = State.getKey('/flip', None) Face.double_data(images, shapes, flip_order=flip) predictor = Face.train_shape_predictor(images, shapes) State.setKey('/predictor', predictor) State.push('train predictor')
def boot_face(): fi = frame_number() img = get_frame_image(fi) predictor = get_predictor() shp = Face.detect_face(img, predictor) if shp is not None: set_frame_markup(fi, shp) State.push('boot face markup')
def saveAs(self, filename = None): if self.saveCB: self.saveCB(filename) if filename is None or filename == '': filename, filtr = QtGui.QFileDialog.getSaveFileName(self, 'Choose a file name to save as', '.', 'SCN (*.scn)') if filename == '': return # did not save State.save(filename) self.setFilename(filename)
def updateFieldKey(self, key): #print 'updateFieldKey',key if not State.hasKey(key): return # TODO maybe need to remove something from UI sel = State.getSel() if sel is None: return self.qfields.setKeyValue(key, State.getKey(key)) s = '/%s/attrs/'%sel.strip('/') #print 'updateFieldKey',s,key if key.startswith(s): self.qfields.setKeyValue(key[len(s):], State.getKey(key))
def import_image(): image_fn, _ = QApp.app.loadFilename( 'Choose an image to open', cwd(), 'Image Files (*.jpg *.jpeg *.png *.bmp *.tif)') if image_fn == '': return # cancel img = Face.load_image(image_fn) images, shapes = [], [] add_image(img) State.push('Import image')
def set_frame_cb(fi): view = QApp.view() # TODO should be part of the callback? if fi != frame_number(): State.setKey('/frame_number', fi) State.push('change frame') img = get_frame_image(fi) update_gui_image(view, img) update_markup_mesh(view) QApp.app.updateMenus() # trigger a full refesh here (TODO not needed?)
def train_aam(): images, shapes, labels = images_shapes_not_all_labels_unmarked() flip = State.getKey('/flip', None) aam_model = Face.train_aam_model(images, shapes, flip_order=flip, texture_rank=20) State.setKey('/aam', aam_model) State.push('train aam')
def load(self, filename=None): if not self.sure(): return if filename is None: filename, filtr = QtGui.QFileDialog.getOpenFileName(self, 'Choose a file to open', '.', 'SCN (*.scn)') if filename == '': return # did not load if self.preLoadCB: self.preLoadCB(filename, self) State.load(filename) self.setFilename(filename) if self.loadCB: self.loadCB(filename, self)
def update_flip_order_last2(): '''A hacky method that makes the last two added points be each others flip.''' flip = State.getKey('/flip', [16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,\ 26,25,24,23,22,21,20,19,18,17,27,28,29,30,35,34,33,32,31,45,44,43,42,47,46,\ 39,38,37,36,41,40,54,53,52,51,50,49,48,59,58,57,56,55,64,63,62,61,60,67,66,65]) flip = list(flip) flip.extend([len(flip) + 1, len(flip)]) print flip flip = np.int32(flip) State.setKey('/flip', flip) State.push('update flip last 2')
def setAttrs(self, attrs, location=None): if location is None: location = self.name # if State.hasKey(location): # locationAttrs = State.getKey(location) # for k, v in attrs.iteritems(): # locationAttrs[k] = v # else: # locationAttrs = attrs State.setKey(location, {'type': location, 'attrs': attrs})
def new(self): del self.view().primitives[:] del self.view().primitives2D[:] self.view().points = None grid = GLGrid() self.view().primitives.append(grid) self.view().setLayer('grid', grid) self.view().camera.reset2D() self.view().camera.reset3D() self.qtimeline.setRange(1, 100) State.new() self.updateMenus()
def toggle_unreal(): global g_TIS_server streaming_TIS = State.getKey('/root/ui/attrs/streaming_TIS') if streaming_TIS: g_TIS_server.Stop() State._setKey('/root/ui/attrs/streaming_TIS', False) print "Stopping Server" else: print 'Trying to start Server' if g_TIS_server.Start('',6500): State._setKey('/root/ui/attrs/streaming_TIS', True) else: print 'ARGH!!! Failed to start server'
def getAttrs(self, location=None, onlyDirty=False): if location is None: location = self.name op = State.getKey(location) if onlyDirty: op = State.getKey(location) attrs = { name: value for name, value in op['attrs'].iteritems() if self.isDirty(name) } return attrs return op['attrs']
def getAttr(self, attrName, defaultValue=None, location=None, onlyDirty=False): if location is None: location = self.name if not State.hasKey(location): return defaultValue op = State.getKey(location) if not op or 'attrs' not in op: return defaultValue attrs = op['attrs'] if not attrName in attrs: return defaultValue if onlyDirty and not self.isDirty(attrName, location): return defaultValue return attrs[attrName]
def updateMenus(self): '''Keeps the GUI menus and the attribute editor in sync with the actual state.''' undoCmd = State.getUndoCmd() self.undoItem.setText('&Undo' if undoCmd is None else '&Undo [%s]' % undoCmd) redoCmd = State.getRedoCmd() self.redoItem.setText('Re&do' if redoCmd is None else 'Re&do [%s]' % redoCmd) #print undoCmd, redoCmd if self.attributeEditor is not None: sel = State.getSel() if sel is None: self.qfields.setFields('',[],{}) else: st = State.getKey(sel+'/type',None) sa = State.getKey(sel+'/attrs',{}) global fields self.qfields.setFields(sel, fields.get(st,[]), sa) self.attributeEditor.setWidget(self.qfields) self.updateGL()
def dirty_cb(dirty): if '/root/ui/attrs/movie_filename' in dirty: fn = State.getKey('/root/ui/attrs/movie_filename') global g_md g_md = MovieReader.open_file(fn) QApp.app.qtimeline.setRange(0,g_md['vmaxframe']) for dk in dirty: if dk.startswith('/root/ui/attrs/'): QApp.app.refresh() global g_mode, g_frame, g_rbfn if g_mode == 1 and not '/root/sliders/attrs' in dirty: # RBFN view; changing frame sets all the sliders; we avoid that case for key in dirty: if key.startswith('/root/sliders/attrs'): si = g_rbfn['slider_names'].index(key[len('/root/sliders/attrs/'):]) group,gn,pn,slider_indices,slider_names,pose_splits = rbfn_info_from_frame(g_frame[g_mode]) print 'rbfn slider value changed:',key,si,'from',group['slider_data'][pn][si],'to',State.getKey(key) group['slider_data'][pn][si] = State.getKey(key) rbfn_view_cb(g_frame[g_mode]) # TODO, force an update of the geo
def pickedCB(view, data, clearSelection=True): #print 'pickedCB',view,data,clearSelection if data is None: QApp.app.select(None) # TODO achievable through the view? else: primitive_type, pn, pi, distance = data if primitive_type is '3d': p = view.primitives[pn] if isinstance(p, GLPoints3D): if pi == -1: # edge print 'picked edge' return #name = p.names[pi] print "Picked:", pi if p is view.getLayer('ref_mesh'): move_vertex(view, pi, p.vertices[pi, :2]) select_vertex(view, pi) State.push('select vertex') QApp.app.updateMenus()
def sync(self): '''synchronize the selection with the State selection''' index = self.selectionModel().currentIndex() key = State.getSel() if key is None: return if index.isValid(): item = self.index_to_item(index) if item.data() == key: return item = self.generate_path_to(key) self.selectionModel().setCurrentIndex(self.item_to_index(item), QtGui.QItemSelectionModel.ClearAndSelect)
def setFieldValueCommand(self, field, value): '''Be careful, this is usually called from a qt callback, so we mustn't rebuild qt objects here.''' if self.value_is_adjusting: return #print 'setFieldValueCommand', repr(field), repr(value) #print '/%s/attrs/%s' % (State.getSel(),field) State.setKey('/%s/attrs/%s' % (State.getSel(),field),value) self.edit_signal.emit(State.getSel(),field,value) # DH self.clean_state() # if changing the field has side effects, these should happen before the push (I think) State.push('Set %s' % str(field)) undoCmd = State.getUndoCmd() self.undoItem.setText('&Undo' if undoCmd is None else '&Undo [%s]' % undoCmd) redoCmd = State.getRedoCmd() self.redoItem.setText('Re&do' if redoCmd is None else 'Re&do [%s]' % redoCmd)
def createChild(self, name, type, atLocation=None, attrs=None): if atLocation is None: atLocation = self.path if atLocation not in self.scenegraph: self.scenegraph[atLocation] = { 'type': 'group' } if not name: location = atLocation else: location = '/'.join([atLocation, name]) if location not in self._cookedLocations: self._cookedLocations.append(location) self.registerCook(atLocation) if attrs is None: self.scenegraph[location] = {} else: self.scenegraph[location] = attrs self.scenegraph[location]['type'] = type State.setKey('/interface' + location, {'dirty': True}) return self.scenegraph[location]
def generate_item_children(self, parent): root = self.root if parent is self.model() else str(parent.data()) parent.setRowCount(0) # remove any pre-existing stubs or rows elements = State.subkeys(root) if elements and isinstance(elements[0], str): for text in sorted(elements): # TODO order should match sort mode key = '%s/%s'%(root,text) sk = State.subkeys(key) item = QtGui.QStandardItem(self.tr(text)) item.setData(key) if isinstance(sk, list): #item.appendRow(QtGui.QStandardItem(self.tr(''))) # make a stub for subkeys self.generate_item_children(item) # TODO the whole point is to evaluate this lazily; # but it causes crashes of course when synchronizing the treeview to match the # state selection (which changed by the user clicking on a geo). parent.appendRow(item) else: v = State.g_state[key] v = v[0] if v[0] in '<{[(' else str(State.thaw(v)) item2 = QtGui.QStandardItem(self.tr(v)) parent.appendRow([item,item2])
def dirtyCB(dirty): # triggered by a state change, this allows the app to synch with the state # TODO this is the correct place to deal with changes due to eg menu items or hot keys # should be able to remove eg updateGL from everywhere else, really #print 'dirty',dirty if dirty: outliner = QApp.app.qoutliner outliner.set_root(outliner.root) # TODO this causes a total rebuild global g_predictor, g_aam_model if '/predictor' in dirty: g_predictor = None if '/aam' in dirty: g_aam_model = None if '/vnames' in dirty: #print 'setting names',State.getKey('/vnames') QApp.view().getLayer('markup_mesh').names = State.getKey('/vnames', []) if '/markup_mesh_sel' in dirty: QApp.view().getLayer('markup_mesh').selectedIndex = State.getKey( '/markup_mesh_sel', -1) if '/edges' in dirty: QApp.view().getLayer('markup_mesh').edges = State.getKey( '/edges', None) QApp.view().getLayer('ref_mesh').edges = State.getKey('/edges', None)
def get_frame_image(fi): img = State.getKey('/images/%d' % fi, None) if isinstance(img, np.ndarray): print 'compressing image', fi set_frame_image(fi, img) img = JPEG.decompress(img) if img is not None and (len(img.shape) != 3 or img.shape[2] != 3 or img.dtype != np.uint8): print 'repairing img', fi, img.shape, img.dtype ret = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8) ret[:, :, :3] = img.reshape(img.shape[0], img.shape[1], -1)[:, :, :3] img = ret print 'repaired img', fi, img.shape, img.dtype set_frame_image(fi, img) return img
def rbfn_view_cb(fi, attrs): # g_mode = 1 global g_rbfn group,gn,pn,slider_indices,slider_names,pose_splits = rbfn_info_from_frame(fi) QApp.view().displayText = [(10, 100, gn), (10,125, pn)] img = group['images'][pn] img = JPEG.decompress(img) h,wm = img.shape[0]*0.5,img.shape[1]*0.5 out_shape = extract_x2ds(group, pn, g_rbfn['marker_names']) svs = group['slider_data'][pn][slider_indices] State._setKey('/root/sliders/attrs', dict(zip(slider_names, svs))) # NO UNDO # compensate for roll, translation and scale norm_shape, head_pan, head_tilt, A = stabilize_shape(out_shape) # extract angles from the measured values mirror_scale = -1 if attrs['mirroring'] else 1 new_pose = np.degrees(np.arctan2([head_pan*mirror_scale, head_tilt, -mirror_scale*A[1][0]],[2,2,A[1][1]])) head_roll = -np.arctan2(A[1][0],A[1][1]) head_pan = np.arctan2(head_pan, 2.0) head_tilt = np.arctan2(head_tilt, 2.0) #print head_roll, head_pan, head_tilt slider_names, slider_values = applyRetarget(g_rbfn, norm_shape) svs[np.where(svs < 1e-4)] = 0 slider_values[np.where(slider_values < 1e-4)] = 0 #print zip(slider_values,svs) slider_names.extend(['NeckRoll','NeckPan','NeckTilt']) svs = np.clip(svs,0,1) slider_values = np.float32(list(svs)+list(np.degrees([head_roll,head_pan,head_tilt]))) return new_pose,out_shape,norm_shape,img,slider_names,slider_values,A
def import_movie_frames(): movie_fn, _ = QApp.app.loadFilename( 'Choose a movie to open', cwd(), 'Movie Files (*.mp4 *.mov *.avi *.flv *.mpg)') if movie_fn == '': return # cancel set_cwd(movie_fn) txt_fn, _ = QApp.app.loadFilename( 'Choose a text file of frame indices to open', cwd(), 'Text Files (*.txt)') md = MovieReader.open_file(movie_fn, audio=False) images, shapes = [], [] if txt_fn == '': frames = range(0, md['vmaxframe'], 100) #if txt_fn == '': frames = range(30000, 38300, 100) else: frames = [int(l.split(':')[1]) for l in open(txt_fn, 'r').readlines()] for fi in frames: print fi, '/', frames[-1] MovieReader.readFrame(md, fi) add_image( np.frombuffer(md['vbuffer'], dtype=np.uint8).reshape(md['vheight'], md['vwidth'], 3).copy()) State.push('Import movie frames')
def initialiseOpState(self, op): attrs = op.getStateAttrs() opName = State.addKey(op.getName(), { 'type': self.findRegisteredOpName(op), 'attrs': attrs }) # print self.id, '| Initialise Op State: Op name =', opName op.setName(opName) self.collect[opName] = [] self.collectFrames[opName] = [] if 'locations' in attrs: locations = op.resolveLocations(attrs['locations']) if opName not in self.cookRelationships: self.cookRelationships[opName] = [] self.cookRelationships[opName].extend(locations)
def retriangulate(): shp = get_predictor()['ref_shape'] edges = [] tris = Face.triangulate_2D(shp) for p0, p1, p2 in tris: edges.append((p0, p1)) edges.append((p1, p2)) edges.append((p2, p0)) edges = np.int32(edges) tris = np.int32(tris) State.setKey('/edges', edges) State.setKey('/tris', tris) State.push('triangulate')