def draw(uim): '''Tells the HotSpotterAPI to draw the current selection in the current mode. It will automatically switch tabs to the current view.''' cm, gm = uim.hs.get_managers('cm','gm') #current_tab = uim.hsgui.main_skel.tablesTabWidget.currentIndex if uim.state in ['splash_view']: uim.hs.dm.show_splash() elif uim.state in ['annotate']: if gm.is_valid(uim.sel_gid): uim.hs.dm.show_image(gm.gx(uim.sel_gid)) elif uim.state in ['chip_view']: if cm.is_valid(uim.sel_cid): uim.hs.dm.show_chip(cm.cx(uim.sel_cid)) uim.select_tab('chip', block_draw=True) elif uim.state in ['image_view']: if gm.is_valid(uim.sel_gid): uim.hs.dm.show_image(gm.gx(uim.sel_gid)) uim.select_tab('image', block_draw=True) elif uim.state in ['result_view']: if uim.sel_res != None: logdbg('Drawing Query Results') uim.hs.dm.show_query(uim.sel_res) uim.select_tab('result', block_draw=True) else: logerr('I dont know how to draw in state: '+str(uim.state))
def chip_alloc(cm, nAlloc): 'Allocate room for nAlloc more chips' logdbg('Allocating room for %d more chips' % nAlloc) cm.cx2_cid = np.append(cm.cx2_cid, np.zeros(nAlloc, dtype=np.uint32)) # Implicit Data Local Identifiers cm.cx2_nx = np.append(cm.cx2_nx, np.zeros(nAlloc, dtype=np.uint32)) cm.cx2_gx = np.append(cm.cx2_gx, np.zeros(nAlloc, dtype=np.uint32)) # Explicit Data cm.cx2_roi = np.append(cm.cx2_roi, np.zeros((nAlloc, 4), dtype=np.uint32), axis=0) cm.cx2_theta = np.append(cm.cx2_theta, np.zeros(nAlloc, dtype=np.float32), axis=0) cm.cx2_fpts = np.append(cm.cx2_fpts, np.empty(nAlloc, dtype=object)) cm.cx2_fdsc = np.append(cm.cx2_fdsc, np.empty(nAlloc, dtype=object)) # Feature Representation cm.cx2_dirty_bit = np.append(cm.cx2_dirty_bit, np.ones(nAlloc, dtype=np.bool)) # Reverse Index idAlloc = len(cm.cid2_cx) - len(cm.cx2_cid) if idAlloc > 0: cm.cid2_cx = np.append(cm.cid2_cx, np.zeros(idAlloc, dtype=np.uint32)) # User Properties for prop in cm.user_props.iterkeys(): cm.user_props[prop] = np.append(cm.user_props[prop], np.empty(nAlloc, dtype=object))
def cx2_rr(qm, qcx, qhs=None): hs = qm.hs qhs = hs if qhs is None else qhs rr = RawResults(qcx, hs, qhs) qm.rr = rr # Save in query database. rr_dpath = qhs.iom.ensure_computed_directory('query_results') # Filename points to result database depends = ['chiprep', 'preproc', 'model', 'query'] algo_suffix = hs.am.get_algo_suffix(depends) samp_suffix = hs.vm.get_samp_suffix() rr_suffix = algo_suffix + samp_suffix # Populate raw results force_recompute = False #TODO PREFERENCE if rr.has_result(rr_dpath, rr_suffix) and not force_recompute: logdbg('Loading query.') rr.load_result(rr_dpath, rr_suffix) else: logmsg('Recomputing query.') (qfpts, qfdsc) = qhs.cm.get_feats(qcx) rr.qfpts = qfpts rr.qfdsc = qfdsc rr.qchip_size = qhs.cm.cx2_chip_size(qcx) qm.repopulate_raw_results(rr, hs, qhs) rr.save_result(rr_dpath, rr_suffix) return rr
def add_images(dm, img_list, title_list=[]): fig = dm.get_figure() fig.clf() num_images = len(img_list) # dm.ax_list = [None] * num_images title_list = title_list + ["NoTitle"] * (num_images - len(title_list)) # Fit Images into a grid max_columns = min(num_images, max(1, dm.draw_prefs.num_result_cols)) if max_columns == 0: max_columns = 1 nr = int(ceil(float(num_images) / max_columns)) nc = max_columns if num_images >= max_columns else 1 # gs = gridspec.GridSpec(nr, nc) for i in xrange(num_images): # logdbg(' Adding the '+str(i)+'th Image') # logdbg(' * type(img_list[i]): %s'+str(type(img_list[i]))) # logdbg(' * img_list[i].shape: %s'+str(img_list[i].shape)) dm.ax_list[i] = fig.add_subplot(gs[i]) imgplot = dm.ax_list[i].imshow(img_list[i]) imgplot.set_cmap("gray") dm.ax_list[i].get_xaxis().set_ticks([]) dm.ax_list[i].get_yaxis().set_ticks([]) dm.ax_list[i].set_title(title_list[i]) # transData: data coordinates -> display coordinates # transAxes: axes coordinates -> display coordinates # transLimits: data - > axes # # gs.tight_layout(fig) logdbg("Added " + str(num_images) + " images/axes")
def draw(uim): '''Tells the HotSpotterAPI to draw the current selection in the current mode. It will automatically switch tabs to the current view.''' cm, gm = uim.hs.get_managers('cm', 'gm') #current_tab = uim.hsgui.main_skel.tablesTabWidget.currentIndex if uim.state in ['splash_view']: uim.hs.dm.show_splash() elif uim.state in ['annotate']: if gm.is_valid(uim.sel_gid): uim.hs.dm.show_image(gm.gx(uim.sel_gid)) elif uim.state in ['chip_view']: if cm.is_valid(uim.sel_cid): uim.hs.dm.show_chip(cm.cx(uim.sel_cid)) uim.select_tab('chip', block_draw=True) elif uim.state in ['image_view']: if gm.is_valid(uim.sel_gid): uim.hs.dm.show_image(gm.gx(uim.sel_gid)) uim.select_tab('image', block_draw=True) elif uim.state in ['result_view']: if uim.sel_res != None: logdbg('Drawing Query Results') uim.hs.dm.show_query(uim.sel_res) uim.select_tab('result', block_draw=True) else: logerr('I dont know how to draw in state: ' + str(uim.state))
def cx2_rr(qm, qcx, qhs=None): hs = qm.hs qhs = hs if qhs is None else qhs rr = RawResults(qcx, hs, qhs) qm.rr = rr # Save in query database. rr_dpath = qhs.iom.ensure_computed_directory('query_results') # Filename points to result database depends = ['chiprep', 'preproc', 'model', 'query'] algo_suffix = hs.am.get_algo_suffix(depends) samp_suffix = hs.vm.get_samp_suffix() rr_suffix = algo_suffix + samp_suffix # Populate raw results force_recompute = False #TODO PREFERENCE if rr.has_result(rr_dpath, rr_suffix) and not force_recompute: logdbg('Loading query.') rr.load_result(rr_dpath, rr_suffix) else: logmsg('Recomputing query.') (qfpts, qfdsc) = qhs.cm.get_feats(qcx) rr.qfpts = qfpts rr.qfdsc = qfdsc rr.qchip_size = qhs.cm.cx2_chip_size(qcx) qm.repopulate_raw_results(rr, hs, qhs) rr.save_result(rr_dpath, rr_suffix) return rr
def __image_csv_func(iom, csv_data, csv_headers=None): """ A function which reads a single line of csv image data """ """ gid = None gname = None aif = None if csv_headers != None: pass""" if len(csv_data) == 3: # Format where extension is part of name gid = int(csv_data[0]) gname = csv_data[1] aif = csv_data[2] logdbg("Adding Image") elif len(csv_data) == 4: # Format where extension is its own field gid = int(csv_data[0]) gnameext = csv_data[2] gname_noext = csv_data[1] if gname_noext.find(".") == -1 and gnameext.find(".") == -1: gname = gname_noext + "." + gnameext else: gname = gname_noext + gnameext aif = csv_data[3] logdbg("Adding Image (old way)") iom.hs.gm.add_img(gid, gname, aif)
def _check_altfname(iom, alt_names=None): "Checks for a legacy data table" alt_dirs = [ iom.get_internal_dpath(), iom.hs.db_dpath, join(iom.hs.db_dpath, "data"), join(iom.hs.db_dpath, "data", "..", "data", ".."), ] for adir in iter(alt_dirs): for aname in iter(alt_names): alt_fpath = normpath(join(adir, aname)) logdbg("Checking: " + alt_fpath) if exists(alt_fpath): logwarn("Using Alternative Datatable " + alt_fpath) timestamp = str(time.time()) backup_fpath = normpath(alt_fpath + "." + timestamp + ".bak") logwarn("Creating Backup: " + backup_fpath) shutil.copyfile(alt_fpath, backup_fpath) return alt_fpath if iom.hs.db_dpath.find(iom.internal_dname) >= 0: # Disallow Hotspotter directories inside HotSpotter directories new_db_path = iom.hs.db_dpath[0 : iom.hs.db_dpath.find(iom.internal_dname)] logwarn("Changing this data dir " + iom.hs.db_dpath) logwarn("To that data dir " + new_db_path) iom.hs.db_dpath = new_db_path return "CSV_Name_not_found"
def save_model(vm): # See if the model is savable if not vm.model_prefs.save_load_model: logdbg('Can NOT save the visual model due to preferences') return False if vm.isDirty: raise Exception('Can NOT save the visual model due to dirty index') if vm.flann is None: raise Exception('Can NOT save the visual model without a flann index') logdbg('Building dictionary to save') # TODO: This dictionary should just exist and not be # directly tied to this class. # Build a dictionary of savable model terms to_save_dict = {key : vm.__dict__[key] \ for key in vm.savable_model_fields } # Get the save paths model_fpath = vm.hs.iom.get_model_fpath() flann_index_fpath = vm.hs.iom.get_flann_index_fpath() # Save the Model logio('Saving model to: '+model_fpath) np.savez(model_fpath, **to_save_dict) # Save the Index logio('Saving index to: '+flann_index_fpath) vm.flann.save_index(flann_index_fpath) logio('Model save was sucessfull') return True
def restart(hs, db_dpath=None, autoload=True, save_pref_bit=True): hs.data_loaded_bit = False if hs.db_dpath != None and db_dpath == None: db_dpath = hs.db_dpath db_dpath = hs.smartget_db_dpath(db_dpath) # -- hs.db_dpath = None if hs.is_valid_db_dpath(db_dpath): hs.db_dpath = db_dpath if save_pref_bit: logdbg('Setting db_dpath = '+str(db_dpath)) hs.core_prefs.update('database_dpath',db_dpath) if hs.db_dpath is None: logerr('Invalid Database. '+\ 'Select an existing HotSpotter, StripeSpotter database. '+\ 'To create a new database, select and empty directory. ') hs.gm = ImageManager(hs) hs.nm = NameManager(hs) hs.cm = ChipManager(hs) hs.vm = VisualModel(hs) hs.qm = QueryManager(hs) hs.em = ExperimentManager(hs) if autoload == True: hs.load_tables() else: logdbg('autoload is false.')
def _check_altfname(iom, alt_names=None): 'Checks for a legacy data table' alt_dirs = [iom.get_internal_dpath(), iom.hs.db_dpath, join(iom.hs.db_dpath,'data'), join(iom.hs.db_dpath,'data','..','data','..')] for adir in iter(alt_dirs): for aname in iter(alt_names): alt_fpath = normpath(join(adir,aname)) logdbg('Checking: '+alt_fpath) if exists(alt_fpath): logwarn('Using Alternative Datatable '+alt_fpath) timestamp = str(time.time()) backup_fpath = normpath(alt_fpath+'.'+timestamp+'.bak') logwarn('Creating Backup: '+backup_fpath) shutil.copyfile(alt_fpath, backup_fpath) return alt_fpath if iom.hs.db_dpath.find(iom.internal_dname) >= 0: # Disallow Hotspotter directories inside HotSpotter directories new_db_path = iom.hs.db_dpath[0:iom.hs.db_dpath.find(iom.internal_dname)] logwarn('Changing this data dir '+iom.hs.db_dpath) logwarn('To that data dir '+new_db_path) iom.hs.db_dpath = new_db_path return 'CSV_Name_not_found'
def __image_csv_func(iom, csv_data, csv_headers=None): """ A function which reads a single line of csv image data """ ''' gid = None gname = None aif = None if csv_headers != None: pass''' if len(csv_data) == 3: # Format where extension is part of name gid = int(csv_data[0]) gname = csv_data[1] aif = csv_data[2] logdbg('Adding Image') elif len(csv_data) == 4: # Format where extension is its own field gid = int(csv_data[0]) gnameext = csv_data[2] gname_noext = csv_data[1] if gname_noext.find('.') == -1 and gnameext.find('.') == -1: gname = gname_noext + '.' + gnameext else: gname = gname_noext + gnameext aif = csv_data[3] logdbg('Adding Image (old way)') iom.hs.gm.add_img(gid, gname, aif)
def add_images(dm, img_list, title_list=[]): fig = dm.get_figure(); fig.clf() num_images = len(img_list) # dm.ax_list = [None]*num_images title_list = title_list + ['NoTitle']*(num_images-len(title_list)) # Fit Images into a grid max_columns = min(num_images, max(1,dm.draw_prefs.num_result_cols)) if max_columns == 0: max_columns = 1 nr = int( ceil( float(num_images)/max_columns) ) nc = max_columns if num_images >= max_columns else 1 # gs = gridspec.GridSpec( nr, nc ) for i in xrange(num_images): #logdbg(' Adding the '+str(i)+'th Image') #logdbg(' * type(img_list[i]): %s'+str(type(img_list[i]))) #logdbg(' * img_list[i].shape: %s'+str(img_list[i].shape)) dm.ax_list[i] = fig.add_subplot(gs[i]) imgplot = dm.ax_list[i].imshow(img_list[i]) imgplot.set_cmap('gray') dm.ax_list[i].get_xaxis().set_ticks([]) dm.ax_list[i].get_yaxis().set_ticks([]) dm.ax_list[i].set_title(title_list[i]) # transData: data coordinates -> display coordinates # transAxes: axes coordinates -> display coordinates # transLimits: data - > axes # #gs.tight_layout(fig) logdbg('Added '+str(num_images)+' images/axes')
def populatePrefTreeSlot(epw, pref_struct): 'Populates the Preference Tree Model' logdbg('Bulding Preference Model of: '+repr(pref_struct)) epw.pref_model = pref_struct.createQPreferenceModel() logdbg('Built: '+repr(epw.pref_model)) epw.pref_skel.prefTreeView.setModel(epw.pref_model) epw.pref_skel.prefTreeView.header().resizeSection(0,250)
def select_tab(uim, tabname, block_draw=False): logdbg('Selecting the ' + tabname + ' Tab') if block_draw: prevBlock = uim.hsgui.main_skel.tablesTabWidget.blockSignals(True) tab_index = uim.tab_order.index(tabname) uim.selectTabSignal.emit(tab_index) if block_draw: uim.hsgui.main_skel.tablesTabWidget.blockSignals(prevBlock)
def select_tab(uim, tabname, block_draw=False): logdbg('Selecting the '+tabname+' Tab') if block_draw: prevBlock = uim.hsgui.main_skel.tablesTabWidget.blockSignals(True) tab_index = uim.tab_order.index(tabname) uim.selectTabSignal.emit(tab_index) if block_draw: uim.hsgui.main_skel.tablesTabWidget.blockSignals(prevBlock)
def __init__(iom, hs): super( IOManager, iom ).__init__( hs ) logdbg('Creating IOManager') iom.hs = hs iom._hsroot = None iom.settings_dpath = normpath(join(expanduser('~'),'.hotspotter')) iom.internal_dname = '.hs_internals'; iom.dummy_delete = False #Dont actually delete things iom.find_hotspotter_root_dir()
def _cut_out_roi(cm, img, roi): logdbg('Image shape is: ' + str(img.shape)) [gh, gw] = [x - 1 for x in img.shape[0:2]] [rx1, ry1, rw, rh] = [max(0, x) for x in roi] rx2 = min(gw, rx1 + rw) ry2 = min(gh, ry1 + rh) logdbg('Cutting out chip using: ' + str((ry1, ry2, rx1, rx2))) raw_chip = img[ry1:ry2, rx1:rx2, :] return raw_chip
def delete_model(vm): logdbg('Deleting Sample Index') if vm.flann != None: try: vm.flann.delete_index() vm.flann = None except WindowsError: logwarn('WARNING: FLANN is not deleting correctly') vm.reset()
def __init__(iom, hs): super(IOManager, iom).__init__(hs) logdbg("Creating IOManager") iom.hs = hs iom._hsroot = None iom.settings_dpath = normpath(join(expanduser("~"), ".hotspotter")) iom.internal_dname = ".hs_internals" iom.dummy_delete = False # Dont actually delete things iom.find_hotspotter_root_dir()
def _cut_out_roi(cm, img, roi): logdbg('Image shape is: '+str(img.shape)) [gh, gw] = [ x-1 for x in img.shape[0:2] ] [rx1,ry1,rw,rh] = [ max(0,x) for x in roi] rx2 = min(gw, rx1+rw) ry2 = min(gh, ry1+rh) logdbg('Cutting out chip using: '+str((ry1,ry2,rx1,rx2))) raw_chip = img[ ry1:ry2, rx1:rx2, : ] return raw_chip
def setPlotWidgetVisibleSlot(hsgui, bit=None): #None = toggle if hsgui.plotWidget != None: logdbg('Disabling Plot Widget') if bit is None: bit = not hsgui.plotWidget.isVisible() was_visible = hsgui.plotWidget.setVisible(bit) if was_visible != bit: if bit: hsgui.main_skel.fignumSPIN.setValue(0) else: hsgui.main_skel.fignumSPIN.setValue(1)
def remove_file(iom, fpath): if iom.dummy_delete: logdbg("DummyDelete: %s" % fpath) return False logdbg("Deleting: %s" % fpath) try: os.remove(fpath) except OSError as e: logwarn("OSError: %s,\n Could not delete %s" % (str(e), fpath)) return False return True
def remove_file(iom, fpath): if iom.dummy_delete: logdbg('DummyDelete: %s' % fpath) return False logdbg('Deleting: %s' % fpath) try: os.remove(fpath) except OSError as e: logwarn('OSError: %s,\n Could not delete %s' % (str(e), fpath)) return False return True
def unload_features(cm, cxs): if not np.iterable(cxs): cxs = [cxs] nRequest = len(cxs) nUnload = nRequest - np.sum(cm.cx2_dirty_bit[cxs]) # Print unloaded cxs unless there are more than 3 logdbg('Unloading features: %r' % cxs) logmsg('Unloading %d/%d features: ' % (nUnload, nRequest)) cm.cx2_fpts[cxs] = np.empty(nUnload, dtype=object) cm.cx2_fdsc[cxs] = np.empty(nUnload, dtype=object) cm.cx2_fdsc[cxs] = np.empty(nUnload, dtype=object) cm.cx2_dirty_bit[cxs] = True
def bilateral_filter(img): try: import skimage.filter img_uint8 = img img_float = float32(img_uint8) / 255 #mode = Points outside the boundaries of the input are filled according to the given mode (?constant?, ?nearest?, ?reflect? or ?wrap?). Default is ?constant?. img_bilat = skimage.filter.denoise_bilateral(img_float, win_size=20, sigma_range=1.6, sigma_spatial=1.6, bins=256, mode='reflect', cval='reflect') return img_bilat except Exception as ex: logdbg('Scikits not found: %s' % str(ex)) logwarn('Scikits not found: %s' % str(ex)) return img
def unload_features(cm, cxs): if not np.iterable(cxs): cxs = [cxs] nRequest = len(cxs) nUnload = nRequest - np.sum(cm.cx2_dirty_bit[cxs]) # Print unloaded cxs unless there are more than 3 logdbg('Unloading features: %r' % cxs) logmsg('Unloading %d/%d features: ' % (nUnload, nRequest)) cm.cx2_fpts[cxs] = np.empty(nUnload,dtype=object) cm.cx2_fdsc[cxs] = np.empty(nUnload,dtype=object) cm.cx2_fdsc[cxs] = np.empty(nUnload,dtype=object) cm.cx2_dirty_bit[cxs] = True
def histeq(pil_img): img = asarray(pil_img) try: from skimage import exposure 'Local histogram equalization' # Equalization img_eq_float64 = exposure.equalize_hist(img) return Image.fromarray(uint8(np.round(img_eq_float64 * 255))) except Exception as ex: from hotspotter.tpl.other import imtools logdbg('Scikits not found: %s' % str(ex)) logdbg('Using fallback histeq') return Image.fromarray(imtools.histeq(img)).convert('L')
def remove_files_with_pattern(iom, dpath, fname_pattern, recursive_bit=True): logdbg("Removing files in directory %r %s" % (dpath, ["", ", Recursively"][recursive_bit])) logdbg("Removing files with pattern: %r" % fname_pattern) num_removed = 0 num_matched = 0 for root, dname_list, fname_list in os.walk(dpath): for fname in fnmatch.filter(fname_list, fname_pattern): num_matched += 1 num_removed += iom.remove_file(join(root, fname)) if not recursive_bit: break logmsg("Removed %d/%d files" % (num_removed, num_matched)) return True
def remove_files_with_pattern(iom, dpath, fname_pattern, recursive_bit=True): logdbg('Removing files in directory %r %s' % (dpath, ['', ', Recursively'][recursive_bit])) logdbg('Removing files with pattern: %r' % fname_pattern) num_removed = 0 num_matched = 0 for root, dname_list, fname_list in os.walk(dpath): for fname in fnmatch.filter(fname_list, fname_pattern): num_matched += 1 num_removed += iom.remove_file(join(root, fname)) if not recursive_bit: break logmsg('Removed %d/%d files' % (num_removed, num_matched)) return True
def histeq(pil_img): img = asarray(pil_img) try: from skimage import exposure 'Local histogram equalization' # Equalization img_eq_float64 = exposure.equalize_hist(img) return Image.fromarray(uint8(np.round(img_eq_float64*255))) except Exception as ex: from hotspotter.tpl.other import imtools logdbg('Scikits not found: %s' % str(ex)) logdbg('Using fallback histeq') return Image.fromarray(imtools.histeq(img)).convert('L')
def load_features(cm, _cxs=None, force_recomp=False): if _cxs is None: cxs = cm.get_valid_cxs() elif type(_cxs) is types.ListType: cxs = np.array(_cxs) elif type(_cxs) in [types.IntType, types.LongType, np.uint32]: cxs = np.array([_cxs]) else: cxs = _cxs count_feat = 0 is_dirty = np.bitwise_or(cm.cx2_dirty_bit[cxs], force_recomp) num_samp = cxs.size num_dirty = np.sum(is_dirty) # HACKS if not np.iterable(is_dirty): is_dirty = np.array([is_dirty]) if not np.iterable(cxs): cxs = np.array([cxs]) load_cx = cxs[is_dirty] num_clean = num_samp - num_dirty #logdbg('Loading Features: Dirty=%d ; #Clean=%d' % (num_dirty, num_clean)) if num_dirty == 0: return logio('Loading %d Feature Reps' % num_dirty) am = cm.hs.am for cx in iter(load_cx): cid = cm.cx2_cid[cx] if cid <= 0: logwarn('WARNING: IX=' + str(cx) + ' is invalid') continue chiprep_fpath = cm.hs.iom.get_chiprep_fpath(cid) # Ensure that the features exists if force_recomp or not os.path.exists(chiprep_fpath): logio('Computing and saving features of cid=' + str(cid)) hotspotter.ChipFunctions.precompute_chipreps( cm.hs, [cx], num_procs=1, force_recompute=force_recomp) # Load the features logdbg('Loading features in ' + chiprep_fpath) npz = np.load(chiprep_fpath) fpts = npz['arr_0'] fdsc = npz['arr_1'] npz.close() cm.cx2_fpts[cx] = fpts cm.cx2_fdsc[cx] = fdsc cm.cx2_dirty_bit[cx] = False count_feat += len(fpts) logdbg('* Loaded ' + str(count_feat) + ' keypoints and fdscriptors') return True
def add_image_list(hs, image_list): num_add = len(image_list) logmsg('Selected '+str(num_add)+' images to import') prev_g = hs.gm.num_g logdbg('Prev #g=%d' % prev_g) for src_img in image_list: hs.gm.add_img(gid=None, gname=None, aif=False, src_img=src_img) post_g = hs.gm.num_g num_new = (post_g - prev_g) num_old = num_add - num_new logdbg('Post #g=%d' % post_g) logmsg('Imported '+str(num_new)+' new images') if num_old != 0: logmsg('%d Images had already been copied into the image directory' % num_old)
def load_model(vm): # See if the model is loadable if not vm.model_prefs.save_load_model: logdbg('Can NOT load the visual model') return False if not vm.flann is None: raise Exception('Cannot load a model when FLANN already exists') logdbg('Trying to load visual model') # Check to see if new model on disk model_fpath = vm.hs.iom.get_model_fpath() if not os.path.exists(model_fpath): logdbg(' * A saved model data file was missing: '+ model_fpath); return False flann_index_fpath = vm.hs.iom.get_flann_index_fpath() if not os.path.exists(flann_index_fpath): logdbg(' * A saved flann index file was missing: '+ flann_index_fpath); return False # Model and Flann Exist on disk # Load the model data first # Read model into dictionary logmsg('Loading visual model data: ' + model_fpath) npz = np.load(model_fpath) for _key in npz.files: vm.__dict__[_key] = npz[_key] npz.close() # Read FLANN index logmsg('Loading FLANN index: '+ flann_index_fpath) vm.flann = FLANN() vm.flann.load_index(flann_index_fpath, vm.wx2_fdsc) vm.isDirty = False logmsg('The model was sucessfully loaded') return True
def update_state(uim, new_state): 'Updates the state of the UI' old_state = uim.state logdbg('State Change: from: '+str(old_state)+', to: '+str(new_state)) if old_state == 'annotate': if new_state != 'annotate_done': uim.state = 'annotate_done' logerr('Cannot enter new state while selecting an ROI. Attempting to recover') elif old_state == 'querying': if new_state != 'done_querying': uim.state = 'done_querying' logerr('Cannot enter new state while querying. Attempting to recover') uim.state = new_state uim.updateStateLabelSignal.emit(new_state) return old_state
def load_features(cm, _cxs=None, force_recomp=False): if _cxs is None: cxs = cm.get_valid_cxs() elif type(_cxs) is types.ListType: cxs = np.array(_cxs) elif type(_cxs) in [types.IntType, types.LongType, np.uint32]: cxs = np.array([_cxs]) else: cxs = _cxs count_feat = 0 is_dirty = np.bitwise_or(cm.cx2_dirty_bit[cxs], force_recomp) num_samp = cxs.size num_dirty = np.sum(is_dirty) # HACKS if not np.iterable(is_dirty): is_dirty = np.array([is_dirty]) if not np.iterable(cxs): cxs = np.array([cxs]) load_cx = cxs[is_dirty] num_clean = num_samp - num_dirty #logdbg('Loading Features: Dirty=%d ; #Clean=%d' % (num_dirty, num_clean)) if num_dirty == 0: return logio('Loading %d Feature Reps' % num_dirty) am = cm.hs.am for cx in iter(load_cx): cid = cm.cx2_cid[cx] if cid <= 0: logwarn('WARNING: IX='+str(cx)+' is invalid'); continue chiprep_fpath = cm.hs.iom.get_chiprep_fpath(cid) # Ensure that the features exists if force_recomp or not os.path.exists(chiprep_fpath): logio('Computing and saving features of cid='+str(cid)) hotspotter.ChipFunctions.precompute_chipreps(cm.hs, [cx], num_procs=1, force_recompute=force_recomp) # Load the features logdbg('Loading features in '+chiprep_fpath) npz = np.load(chiprep_fpath) fpts = npz['arr_0'] fdsc = npz['arr_1'] npz.close() cm.cx2_fpts[cx] = fpts cm.cx2_fdsc[cx] = fdsc cm.cx2_dirty_bit[cx] = False count_feat += len(fpts) logdbg('* Loaded '+str(count_feat)+' keypoints and fdscriptors' ) return True
def end_draw(dm): #gray() logdbg('Finalizing Draw with '+str(len(dm.ax_list))+' axes') fig = dm.get_figure() #fig.subplots_adjust(hspace=0.2, wspace=0.2) #fig.tight_layout(pad=.3, h_pad=None, w_pad=None) #fig.tight_layout() if dm.draw_prefs.in_qtc_bit: try: from IPython.back.display import display display(fig) except: logwarn('Cannot Draw in QTConsole') fig.show() dm.hs.uim.redraw_gui() fig.canvas.draw()
def batch_rename(hs, name1, name2): logmsg('Batch Renaming %s to %s' % (name1, name2)) cm, nm = hs.get_managers('cm','nm') if name1 == nm.UNIDEN_NAME(): logerr('Cannot batch rename '+str(name1)+'. It is UNIDENTIFIED and has special meaning') if name1 not in nm.name2_nx.keys(): logerr('Cannot batch rename. '+str(name1)+' does not exist') cx_list = nm.name2_cx_list(name1)[:] # COPY BEFORE YOU CHANGE. Man, sneaky errors num_chips = len(cx_list) if num_chips == 0: logerr('Cannot batch rename. '+str(name1)+' has no chips') logmsg('Renaming '+str(num_chips)+' chips: '+str(cx_list)) for cx in cx_list: logdbg('Batch Rename '+str(cx)) cm.rename_chip(cx, name2) return True
def compute_scores(rr, hs): ' Aggregates the votes for chips into votes for animal names' logdbg('Aggregating Feature Scores ') # get managers nm = hs.nm vm = hs.vm cm = hs.cm # get intermediate results cx2_fm = rr.cx2_fm cx2_fs = rr.cx2_fs cx2_nscore = -np.ones(cm.max_cx + 1, dtype=np.float32) cx2_cscore = compute_cscore(cx2_fs) nx2_fx2_scores = {} # Analyze the freq of a keypoint matching a name later nx2_fx2_freq = {} for (cx, fm) in enumerate(cx2_fm): # Each keypoint votes for the highest scoring match # it had to a particular name. (it can vote for multiple names) fs = cx2_fs[cx] nx = cm.cx2_nx[cx] if nx == nm.UNIDEN_NX(): # UNIDEN is a unique name nx = -int(cx) if not nx in nx2_fx2_scores.keys(): nx2_fx2_scores[nx] = {} nx2_fx2_freq[nx] = {} for qfs, (qfx, fx) in iter(zip(fs, fm)): if qfx in nx2_fx2_scores[nx].keys(): nx2_fx2_scores[nx][qfx] = max(nx2_fx2_scores[nx][qfx], qfs) nx2_fx2_freq[nx][qfx] += 1 else: nx2_fx2_scores[nx][qfx] = qfs nx2_fx2_freq[nx][qfx] = 1 for nx in nx2_fx2_scores.keys(): fx2_scores = nx2_fx2_scores[nx] scores = np.array(fx2_scores.values()) nscore = scores[scores > 0].sum() if nx < 0: # UNIDEN HACK. See -int(cx) above cx2_nscore[-nx] = nscore else: for cx in nm.nx2_cx_list[nx]: cx2_nscore[cx] = nscore rr.cx2_cscore = cx2_cscore rr.cx2_nscore = cx2_nscore
def compute_scores(rr, hs): ' Aggregates the votes for chips into votes for animal names' logdbg('Aggregating Feature Scores ') # get managers nm = hs.nm vm = hs.vm cm = hs.cm # get intermediate results cx2_fm = rr.cx2_fm cx2_fs = rr.cx2_fs cx2_nscore = -np.ones(cm.max_cx + 1, dtype=np.float32) cx2_cscore = compute_cscore(cx2_fs) nx2_fx2_scores = {} # Analyze the freq of a keypoint matching a name later nx2_fx2_freq = {} for (cx, fm) in enumerate(cx2_fm): # Each keypoint votes for the highest scoring match # it had to a particular name. (it can vote for multiple names) fs = cx2_fs[cx] nx = cm.cx2_nx[cx] if nx == nm.UNIDEN_NX(): # UNIDEN is a unique name nx = -int(cx) if not nx in nx2_fx2_scores.keys(): nx2_fx2_scores[nx] = {} nx2_fx2_freq[nx] = {} for qfs, (qfx, fx) in iter(zip(fs, fm)): if qfx in nx2_fx2_scores[nx].keys(): nx2_fx2_scores[nx][qfx] = max(nx2_fx2_scores[nx][qfx], qfs) nx2_fx2_freq[nx][qfx] += 1 else: nx2_fx2_scores[nx][qfx] = qfs nx2_fx2_freq[nx][qfx] = 1 for nx in nx2_fx2_scores.keys(): fx2_scores = nx2_fx2_scores[nx] scores = np.array(fx2_scores.values()) nscore = scores[scores > 0].sum() if nx < 0: # UNIDEN HACK. See -int(cx) above cx2_nscore[-nx] = nscore else: for cx in nm.nx2_cx_list[nx]: cx2_nscore[cx] = nscore rr.cx2_cscore = cx2_cscore rr.cx2_nscore = cx2_nscore
def __init__(res, hs, rr, qhs=None): super(QueryResult, res).__init__(['hs','qhs']) logdbg('Constructing Query Result') res.rr = rr res.hs = hs res.qhs = hs if qhs is None else qhs # Set Result Settings based on preferences result_prefs = hs.am.algo_prefs.results res.score_type = result_prefs.score res.one_result_per_name = result_prefs.one_result_per_name # Return all matches higher than this threshold. Subject to... res.top_thresh = result_prefs.match_threshold # And return between this many results res.num_top_min = result_prefs.min_num_results res.num_top_max = result_prefs.max_num_results # And add extra runners up for context res.num_extra_return = result_prefs.extra_num_results
def start_gui(uim, fac): # Currently needs facade access logdbg('Creating the GUI') uim.hsgui = HotspotterMainWindow(fac) uim.hsgui.connectSignals(fac) logdbg('Connecting Facade >> to >> GUI') uim.updateDBStatsSignal.connect( uim.hsgui.updateDBStatsSlot ) uim.populateChipTblSignal.connect( uim.hsgui.populateChipTblSlot ) uim.populateImageTblSignal.connect( uim.hsgui.populateImageTblSlot ) uim.populateResultTblSignal.connect( uim.hsgui.populateResultTblSlot ) uim.updateStateLabelSignal.connect( uim.hsgui.updateStateLabelSlot ) uim.selectionSignal.connect( uim.hsgui.updateSelSpinsSlot ) uim.redrawGuiSignal.connect( uim.hsgui.redrawGuiSlot ) uim.populatePrefTreeSignal.connect( uim.hsgui.epw.populatePrefTreeSlot ) uim.selectTabSignal.connect( uim.hsgui.main_skel.tablesTabWidget.setCurrentIndex ) uim.setfignumSignal.connect( uim.hsgui.main_skel.fignumSPIN.setValue ) uim.populate_algo_settings()
def adapt_histeq(img): try: from skimage import exposure # input uint8, output uint16 img_uint8 = img img_uint16 = uint16(img)*2**8 img_adapteq_uint16 = exposure.equalize_adapthist(img_uint16,\ ntiles_x=8,\ ntiles_y=8,\ clip_limit=0.01,\ nbins=256) img_adapteq_cropped_uint8 = uint8(img_adapteq_uint16[5:-5][5:-5] / uint16(2)**8 ) return img_adapteq_cropped_uint8 except Exception as ex: logdbg('Scikits not found: %s' % str(ex)) logwarn('Scikits not found: %s' % str(ex)) return img
def end_draw(dm): # gray() logdbg("Finalizing Draw with " + str(len(dm.ax_list)) + " axes") fig = dm.get_figure() # fig.subplots_adjust(hspace=0.2, wspace=0.2) # fig.tight_layout(pad=.3, h_pad=None, w_pad=None) # fig.tight_layout() if dm.draw_prefs.in_qtc_bit: try: from IPython.back.display import display display(fig) except: logwarn("Cannot Draw in QTConsole") fig.show() dm.hs.uim.redraw_gui() fig.canvas.draw()
def __init__(res, hs, rr, qhs=None): super(QueryResult, res).__init__(['hs', 'qhs']) logdbg('Constructing Query Result') res.rr = rr res.hs = hs res.qhs = hs if qhs is None else qhs # Set Result Settings based on preferences result_prefs = hs.am.algo_prefs.results res.score_type = result_prefs.score res.one_result_per_name = result_prefs.one_result_per_name # Return all matches higher than this threshold. Subject to... res.top_thresh = result_prefs.match_threshold # And return between this many results res.num_top_min = result_prefs.min_num_results res.num_top_max = result_prefs.max_num_results # And add extra runners up for context res.num_extra_return = result_prefs.extra_num_results
def annotate_orientation(dm): logmsg('Please select an orientation of the torso (Click Two Points on the Image)') try: # Compute an angle from user interaction sys.stdout.flush() fig = dm.get_figure() pts = np.array(fig.ginput(2)) logdbg('GInput Points are: '+str(pts)) # Get reference point to origin refpt = pts[0] - pts[1] #theta = np.math.atan2(refpt[1], refpt[0]) theta = np.math.atan(refpt[1]/refpt[0]) logmsg('The angle in radians is: '+str(theta)) return theta except Exception as ex: logmsg('Annotate Orientation Failed'+str(ex)) return None
def annotate_orientation(dm): logmsg("Please select an orientation of the torso (Click Two Points on the Image)") try: # Compute an angle from user interaction sys.stdout.flush() fig = dm.get_figure() pts = np.array(fig.ginput(2)) logdbg("GInput Points are: " + str(pts)) # Get reference point to origin refpt = pts[0] - pts[1] # theta = np.math.atan2(refpt[1], refpt[0]) theta = np.math.atan(refpt[1] / refpt[0]) logmsg("The angle in radians is: " + str(theta)) return theta except Exception as ex: logmsg("Annotate Orientation Failed" + str(ex)) return None
def adapt_histeq(img): try: from skimage import exposure # input uint8, output uint16 img_uint8 = img img_uint16 = uint16(img) * 2**8 img_adapteq_uint16 = exposure.equalize_adapthist(img_uint16,\ ntiles_x=8,\ ntiles_y=8,\ clip_limit=0.01,\ nbins=256) img_adapteq_cropped_uint8 = uint8(img_adapteq_uint16[5:-5][5:-5] / uint16(2)**8) return img_adapteq_cropped_uint8 except Exception as ex: logdbg('Scikits not found: %s' % str(ex)) logwarn('Scikits not found: %s' % str(ex)) return img
def bilateral_filter(img): try: import skimage.filter img_uint8 = img img_float = float32(img_uint8) / 255 #mode = Points outside the boundaries of the input are filled according to the given mode (?constant?, ?nearest?, ?reflect? or ?wrap?). Default is ?constant?. img_bilat = skimage.filter.denoise_bilateral(img_float, win_size=20, sigma_range=1.6, sigma_spatial=1.6, bins=256, mode='reflect', cval='reflect') return img_bilat except Exception as ex: logdbg('Scikits not found: %s' % str(ex)) logwarn('Scikits not found: %s' % str(ex)) return img
def is_valid_db_dpath(hs, db_dpath): 'Checks to see if database conforms to expected conventions' if not os.path.exists(db_dpath): logwarn('db_dpath \"'+str(db_dpath)+'\" doesnt exist') return False db_dpath_files = os.listdir(db_dpath) if hs.iom.internal_dname in db_dpath_files: logmsg('Opening a HotSpotter database: '+db_dpath) elif 'images' in db_dpath_files or\ 'data' in db_dpath_files: logmsg('Opening a StripSpotter database: '+db_dpath) elif len(db_dpath_files) == 0: logmsg('Creating a new database: '+db_dpath) else: logwarn('Unknown database type: '+db_dpath) logdbg('Files in dir: '+str(db_dpath_files)) return False return True
def start_gui(uim, fac): # Currently needs facade access logdbg('Creating the GUI') uim.hsgui = HotspotterMainWindow(fac) uim.hsgui.connectSignals(fac) logdbg('Connecting Facade >> to >> GUI') uim.updateDBStatsSignal.connect(uim.hsgui.updateDBStatsSlot) uim.populateChipTblSignal.connect(uim.hsgui.populateChipTblSlot) uim.populateImageTblSignal.connect(uim.hsgui.populateImageTblSlot) uim.populateResultTblSignal.connect(uim.hsgui.populateResultTblSlot) uim.updateStateLabelSignal.connect(uim.hsgui.updateStateLabelSlot) uim.selectionSignal.connect(uim.hsgui.updateSelSpinsSlot) uim.redrawGuiSignal.connect(uim.hsgui.redrawGuiSlot) uim.populatePrefTreeSignal.connect(uim.hsgui.epw.populatePrefTreeSlot) uim.selectTabSignal.connect( uim.hsgui.main_skel.tablesTabWidget.setCurrentIndex) uim.setfignumSignal.connect(uim.hsgui.main_skel.fignumSPIN.setValue) uim.populate_algo_settings()
def annotate_roi(dm): logmsg('Please Select a Rectangular Region of Interest (Click Two Points on the Image)') try: sys.stdout.flush() fig = dm.get_figure() pts = fig.ginput(2) logdbg('GInput Points are: '+str(pts)) (x1, y1, x2, y2) = (pts[0][0], pts[0][1], pts[1][0], pts[1][1]) xm = min(x1,x2) xM = max(x1,x2) ym = min(y1,y2) yM = max(y1,y2) (x, y, w, h) = (xm, ym, xM-xm, yM-ym) roi = array(round([x,y,w,h]),dtype=uint32) logmsg('The new ROI is: '+str(roi)) return roi except Exception as ex: logmsg('Annotate ROI Failed'+str(ex)) return None
def update_state(uim, new_state): 'Updates the state of the UI' old_state = uim.state logdbg('State Change: from: ' + str(old_state) + ', to: ' + str(new_state)) if old_state == 'annotate': if new_state != 'annotate_done': uim.state = 'annotate_done' logerr( 'Cannot enter new state while selecting an ROI. Attempting to recover' ) elif old_state == 'querying': if new_state != 'done_querying': uim.state = 'done_querying' logerr( 'Cannot enter new state while querying. Attempting to recover' ) uim.state = new_state uim.updateStateLabelSignal.emit(new_state) return old_state
def rename_chip(cm, cx, new_name): nm = cm.hs.nm cid = cm.cid(cx) old_nx = cm.cx2_nx[cx] old_name = nm.nx2_name[old_nx] if old_name == new_name: logdbg('new_name == old_name') return logmsg('Renaming cid=' + str(cid) + ' from ' + str(old_name) + ' to ' + new_name) if not new_name in nm.name2_nx.keys(): nm.add_name(-1, new_name) old_nx = cm.cx2_nx[cx] new_nx = nm.name2_nx[new_name] #Debug old_nid = nm.nx2_nid[old_nx] new_nid = nm.nx2_nid[new_nx] logdbg('Old Name Info: cid=%d cx=%d, nid=%d, nx=%d, name=%s' % (cid, cx, old_nid, old_nx, old_name)) logdbg('New Name Info: cid=%d cx=%d, nid=%d, nx=%d, name=%s' % (cid, cx, new_nid, new_nx, new_name)) #EndDebug nm.nx2_cx_list[old_nx].remove(cx) nm.nx2_cx_list[new_nx].append(cx) cm.cx2_nx[cx] = new_nx