def search(self, gallery_name, probes, max_results, threshold): ''' search the gallery using the index. ''' score_type = self.score_type probe_mat = [ pt.vector_proto2np(face_rec.template.data) for face_rec in probes.face_records ] probe_mat = np.array(probe_mat, dtype=np.float32) gal_mat = self.indexes[gallery_name] # Compute the distance if score_type == fsd.L1: scores = spat.distance_matrix(probe_mat, gal_mat, 1) elif score_type == fsd.L2: scores = spat.distance_matrix(probe_mat, gal_mat, 2) elif score_type == fsd.NEG_DOT: scores = -np.dot(probe_mat, gal_mat.T) else: NotImplementedError("ScoreType %s is not implemented." % (score_type, )) face_ids = self.face_ids[gallery_name] for p in range(scores.shape[0]): #probe = probes.face_records[p] #out = result.probes.face_records[p].search_results matches = [] for g in range(scores.shape[1]): score = scores[p, g] if score > threshold: continue face = self.getFaceRecord(gallery_name, face_ids[g]) matches.append([score, face]) matches.sort(key=lambda x: x[0]) if max_results > 0: matches = matches[:max_results] for score, face in matches: probes.face_records[p].search_results.face_records.add( ).CopyFrom(face) probes.face_records[p].search_results.face_records[ -1].score = score return probes
def score(self, score_request): '''Compare templates to produce scores.''' score_type = self.scoreType() result = geo.Matrix() # Check that this is a known score type if score_type not in [fsd.L1, fsd.L2, fsd.NEG_DOT]: raise NotImplementedError("Score type <%s> not implemented." % (score_type, )) # Check to make sure the probe and gallery records are correct if min(len(score_request.face_probes.face_records), len(score_request.template_probes.templates)) != 0: raise ValueError( "probes argument cannot have both face_probes and template_probes defined." ) if max(len(score_request.face_probes.face_records), len(score_request.template_probes.templates)) == 0: raise ValueError("no probe templates were found in the arguments.") if min(len(score_request.face_gallery.face_records), len(score_request.template_gallery.templates)) != 0: raise ValueError( "gallery argument cannot have both face_gallery and template_gallery defined." ) if max(len(score_request.face_gallery.face_records), len(score_request.template_gallery.templates)) == 0: raise ValueError( "no gallery templates were found in the arguments.") # Generate probe and gallery matrices if len(score_request.face_probes.face_records) > len( score_request.template_probes.templates): probe_mat = [ pt.vector_proto2np(face_rec.template.data) for face_rec in score_request.face_probes.face_records ] else: probe_mat = [ pt.vector_proto2np(template.data) for template in score_request.template_probes.templates ] probe_mat = np.array(probe_mat, dtype=np.float32) if len(score_request.face_gallery.face_records) > len( score_request.template_gallery.templates): gal_mat = [ pt.vector_proto2np(face_rec.template.data) for face_rec in score_request.face_gallery.face_records ] else: gal_mat = [ pt.vector_proto2np(template.data) for template in score_request.template_gallery.templates ] gal_mat = np.array(gal_mat, dtype=np.float32) # Compute the distance if score_type == fsd.L1: dist_mat = spat.distance_matrix(probe_mat, gal_mat, 1) elif score_type == fsd.L2: dist_mat = spat.distance_matrix(probe_mat, gal_mat, 2) elif score_type == fsd.NEG_DOT: dist_mat = -np.dot(probe_mat, gal_mat.T) else: NotImplementedError("ScoreType %s is not implemented." % (score_type, )) # Return the result return pt.matrix_np2proto(dist_mat)
def addFaceToGallery(self, gallery_name, gallery_key, face): ''' Enrolls the faces in the gallery. ''' import h5py global STORAGE replaced = 0 print('Gallery name:', gallery_name) print(list(STORAGE.keys())) if gallery_name not in STORAGE: path = os.path.join(self.gallery_storage, gallery_name + '.h5') print('adding new gallery at ', path) STORAGE[gallery_name] = h5py.File(path, 'a') STORAGE[gallery_name].create_group('faces') STORAGE[gallery_name].create_group('sources') STORAGE[gallery_name].create_group('detections') STORAGE[gallery_name].create_group('tags') STORAGE[gallery_name].create_group('logs') enrolled = 0 face_id = faro.generateFaceId(face) face.gallery_key = face_id enrolled += 1 if face_id in STORAGE[gallery_name]['faces']: del STORAGE[gallery_name]['faces'][ face_id] # delete so it can be replaced. replaced += 1 STORAGE[gallery_name]['faces'][face_id] = np.bytes_( face.SerializeToString()) template = pt.vector_proto2np(face.template.data) temp_length = template.shape[0] print('template shape: ', template.shape) if 'templates' not in STORAGE[gallery_name]: # Create an empty dataset f = STORAGE[gallery_name] dset = f.create_dataset('templates', data=np.zeros((0, temp_length)), maxshape=(None, temp_length), dtype=np.float32) if 'facelist' not in STORAGE[gallery_name]: # Create an empty dataset f = STORAGE[gallery_name] dt = h5py.special_dtype(vlen=str) dset = f.create_dataset('facelist', (0, ), maxshape=(None, ), dtype=dt) # Append to the end dset = STORAGE[gallery_name]['templates'] size = dset.shape print('dataset size 2:', size) dset.resize((size[0] + 1, size[1])) dset[-1, :] = template dset = STORAGE[gallery_name]['facelist'] size = dset.shape dset.resize((size[0] + 1, )) dset[-1] = face_id STORAGE[gallery_name].flush() self.clearIndex(gallery_name) return enrolled, replaced
def generateIndex(self, gallery_name): ''' Process the gallery to generate a fast index. ''' import h5py #try: # print("Gallery Names:",list(STORAGE[gallery_name])) # self.clearIndex(gallery_name) #except: # print("Problem clearing index.") if gallery_name not in STORAGE: raise ValueError("Unknown gallery: " + gallery_name) if gallery_name in self.indexes: # This seems to exist and be loaded into memory so just continue return if 'index' in STORAGE[gallery_name]: # Use the existing index self.indexes[gallery_name] = np.array( STORAGE[gallery_name]['index'], dtype=np.float32) self.face_ids[gallery_name] = list( STORAGE[gallery_name]['face_ids']) return else: # Generate the index start = time.time() gsize = self.size(gallery_name) dset = None print("Building Gallery Index...") i = 0 for key in STORAGE[gallery_name]['faces']: i += 1 if i % 1000 == 0: print("Scanning ", i, " of ", gsize) tmp = STORAGE[gallery_name]['faces'][key] face = FaceRecord() face.ParseFromString(np.array(tmp).tobytes()) vec = pt.vector_proto2np(face.template.data) # Figure out the size of the vectors assert len(vec.shape) == 1 cols = vec.shape[0] # Store into an h5 datasets to keep memory requirements low if dset is None: try: del STORAGE[gallery_name]['index'] except: pass dset = STORAGE[gallery_name].create_dataset( "index", (0, cols), maxshape=(None, cols), dtype='f4') dt = None try: dt = h5py.string_dtype() # h5py > 2.10.0 except: dt = h5py.special_dtype(vlen=str) # h5py==2.9.0 try: del STORAGE[gallery_name]['face_ids'] except: pass fset = STORAGE[gallery_name].create_dataset( "face_ids", (0, ), maxshape=(None, ), dtype=dt) r, c = dset.shape dset.resize((r + 1, cols)) dset[r, :] = vec fset.resize((r + 1, )) fset[r] = key stop = time.time() # save the index in memory self.indexes[gallery_name] = np.array( STORAGE[gallery_name]['index'], dtype=np.float32) self.face_ids[gallery_name] = list( STORAGE[gallery_name]['face_ids']) print(" Index Complete: %d faces in %0.3fs Total Size: %s" % (self.size(gallery_name), stop - start, STORAGE[gallery_name]['index'].shape))
def addTemplate(self, temp): self.faces.append(temp) self.vectors.append(pt.vector_proto2np(temp.template)) self.vector_cache = None