def __init__(self): self.ims = ImsES(Elasticsearch()) self.CVAlgorithm = CVModule() # Init by configure_runtime.py self.db_path = annoy_index_db_path self.image_search = ImageSearch(self.db_path) self.imageTrain = ImageTrain(self.db_path)
def __init__(self, db_name): """初始化 Args: db_name (string): 需要加载的数据库名称 """ self.MIN_MATCH_COUNT = 10 self.shape = (100, 128) self.cvmodule = CVModule() self.annoyindx = AnnoyIndex_driver(db_name) self.ims = ImsES(Elasticsearch()) try: self.annoyindx.loadDb() except BaseException as e: pass
class Image_Del_API(Resource): def __init__(self): self.ims = ImsES(Elasticsearch()) self.CVAlgorithm = CVModule() # Init by configure_runtime.py self.db_path = annoy_index_db_path self.image_search = ImageSearch(self.db_path) self.imageTrain = ImageTrain(self.db_path) def delete(self): img, self.args = get_image(self.CVAlgorithm) img = self.CVAlgorithm.crop_center(img, dim=dim_800x800) kps, des = self.CVAlgorithm.extract_feature(img) # Init and load search algorithm result_table = self.image_search.search_batch(des) self.image_search.unload() # Collection the id fields result_ids_table = list() [result_ids_table.append(result['id']) for result in result_table] records = self.ims.search_multiple_record(result_ids_table) # Annoy index data found, We also need to match the data one by one for data_index in range(len(result_table)): record = records[data_index]["_source"] data = result_table[data_index] RANSAC_percent = self.CVAlgorithm.findHomgraphy( data['good'], kps, record['kps']) # If it finds any very similar data, it will jump out of the test directly if RANSAC_percent >= 0.5: self.ims.delete_siginle_record({'id': record['id']}) # Loading already dataset and rebuild it! already_dataset = self.ims.search_all_record() for key in already_dataset: self.imageTrain.addMarkerDes(key["_source"]["id"], key["_source"]["des"]) # Rebuild index if self.imageTrain.generateMarkerDB(): return {'msg': success_response} else: return {'msg': 'eror!'} return {'msg': already_img_response}, 202
class ServerWorker(threading.Thread): """ServerWorker""" def __init__(self, context): threading.Thread.__init__(self) self.context = context self.CVModule = CVModule() self.ims = ImsES(Elasticsearch()) def run(self): worker = self.context.socket(zmq.XREQ) worker.connect('inproc://backend') print('Worker started') recvCount = 0 while True: data = worker.recv() if len(data) > 5: img = self.CVModule.read_base64(data) crop_predict_img = self.CVModule.crop_center( img, int(img.shape[0] * 0.8), int(img.shape[0] * 0.8)) kp, des = self.CVModule.extract_feature(crop_predict_img) image_search = ImageSearch("cache/index.db") result_table = image_search.search_batch(des) if len(result_table) > 0: record = self.ims.search_single_record( {'id': result_table['id']}) if len(record) > 0: record.pop('des') result_table = self.merge_dicts(record, result_table) worker.send(json.dumps(result_table).encode('utf8')) else: worker.send(json.dumps({}).encode('utf8')) del data worker.close() def merge_dicts(self, dict1, dict2): dict3 = dict1.copy() dict3.update(dict2) return dict3
class Image_Predict_API(Resource): def __init__(self): self.ims = ImsES(Elasticsearch()) self.CVAlgorithm = CVModule() self.image_search = ImageSearch(annoy_index_db_path) def post(self): try: img, self.args = get_image(self.CVAlgorithm) img = self.CVAlgorithm.crop_center(img, dim=dim_800x800) kps, des = self.CVAlgorithm.extract_feature(img) result_table = self.image_search.search_batch(des) # Collection the id fields result_ids_table = list() [result_ids_table.append(result['id']) for result in result_table] records = self.ims.search_multiple_record(result_ids_table) # Check the result length, when the result length is greater than 0, get the matching data for data_index in range(len(result_table)): record = records[data_index]["_source"] data = result_table[data_index] RANSAC_percent = self.CVAlgorithm.findHomgraphy( data['good'], kps, record['kps']) if len(record) > 0 and RANSAC_percent >= 0.5: # Remove the field of des. Because the des field is storing the image description data record.pop('des') record.pop('kps') data.pop('good') data['confidence'] = RANSAC_percent data = self.merge_dicts(data, record) return data, 200 except Exception as BaseException: print(BaseException) pass return {'data': '', 'message': 'Can not found!'}, 200 def merge_dicts(self, dict1, dict2): dict3 = dict1.copy() dict3.update(dict2) return dict3
class ImageSearch(): def __init__(self, db_name): """初始化 Args: db_name (string): 需要加载的数据库名称 """ self.MIN_MATCH_COUNT = 10 self.shape = (100, 128) self.cvmodule = CVModule() self.annoyindx = AnnoyIndex_driver(db_name) self.ims = ImsES(Elasticsearch()) try: self.annoyindx.loadDb() except BaseException as e: pass def find_vector(self, des): """通过向量匹配对应向量 Args: des (vector): 需匹配向量 Returns: vector: 匹配到的向量 """ return self.annoyindx.find_vector(des) def unload(self): self.annoyindx.unload() def get_item_vector_by_id(self, id): """通过数据库id获取该id对应的向量数据 Args: id (int): 数据库id Returns: vector: 图像描述符向量 """ return self.annoyindx.get_item_vector_by_id(id, self.shape) def get_count(self): """获取当前annoy index数据库的个数 Returns: int: 当前存在数据库内的数据个数 """ return self.annoyindx.get_count() def search_batch(self, targetVector): """批量检索相似向量 Args: targetVector (向量): 图像描述符的向量 Returns: Dict: 检索到最为匹配的图像数据 """ kn_results = self.find_vector(targetVector) result_table = list() good = None # terms检索 避免一次次检索浪费时间 data_caches_es = self.ims.search_multiple_record(kn_results) try: # Tips: 由于查询到的循序与Annoy Index查询到的顺序不一致,故使用ES返回数据id为配准 for data_index in range(len(kn_results)): record = dict() source = data_caches_es[data_index]['_source'] flatten_vector = source['des'] # 避免无法重塑形状 if len(flatten_vector) > 12800: vector = self.annoyindx.reshape( flatten_vector, (int(len(flatten_vector) / 128), 128)) else: vector = self.annoyindx.reshape(flatten_vector, (100, 128)) good = self.cvmodule.match(targetVector, vector) if len(good) >= self.MIN_MATCH_COUNT: record['id'] = source['id'] record['matchscore'] = len(good) record['good'] = good result_table.append(record) except BaseException as ex: print(ex) result_table.sort(key=self.result_sort, reverse=True) return result_table def result_sort(self, e): return e['matchscore']
def __init__(self): self.ims = ImsES(Elasticsearch()) self.CVAlgorithm = CVModule() self.image_search = ImageSearch(annoy_index_db_path) self.imageTrain = ImageTrain(annoy_index_db_path)
class Image_Train_API(Resource): def __init__(self): self.ims = ImsES(Elasticsearch()) self.CVAlgorithm = CVModule() self.image_search = ImageSearch(annoy_index_db_path) self.imageTrain = ImageTrain(annoy_index_db_path) def post(self): img, self.args = get_image(self.CVAlgorithm) img = self.CVAlgorithm.crop_center(img, dim=dim_800x800) if img.shape != dim_800x800: return {'msg': 'Image size is not enough'}, 200 kps,des = self.CVAlgorithm.extract_feature(img) # Init and load search algorithm result_table = self.image_search.search_batch(des) image_count = self.image_search.get_count() self.image_search.unload() if des is None: return {'msg': 'Image description is not enough'}, 200 # Annoy index no data found if len(result_table) == 0: return self.build_record(image_count,kps,des) # Annoy index data found, We also need to match the data one by one for data in result_table: record = self.ims.search_single_record({'id':data['id']}) RANSAC_percent = self.CVAlgorithm.findHomgraphy(data['good'], kps, record['kps']) # If it finds any very similar data, it will jump out of the test directly if RANSAC_percent > 0.5: return {'data':'', 'msg': 'there are already image'}, 202 return self.build_record(image_count,kps,des) def build_record(self,image_count,kps,des): keypoint_serialize = [{'angle': k.angle, 'response': k.response,'octave':k.octave,'class_id':k.class_id,'pt':k.pt,'size':k.size} for k in kps] metadata = self.args['metadata'] if metadata is None: metadata = self.args['image'].filename # Append data to already dataset new_record = {'id': image_count, 'metadata':metadata, 'des': des.flatten(), 'kps': keypoint_serialize} self.ims.insert_single_record(new_record, refresh_after=True) # Loading already dataset already_dataset = self.ims.search_all_record() # Trainning it! for key in already_dataset: self.imageTrain.addMarkerDes(key["_source"]["id"],key["_source"]["des"]) # Rebuild index if self.imageTrain.generateMarkerDB(): return {'msg': 'success'}
def __init__(self, context): threading.Thread.__init__(self) self.context = context self.CVModule = CVModule() self.ims = ImsES(Elasticsearch())