Exemplo n.º 1
0
 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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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']
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
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'}      
Exemplo n.º 9
0
 def __init__(self, context):
     threading.Thread.__init__(self)
     self.context = context
     self.CVModule = CVModule()
     self.ims = ImsES(Elasticsearch())