예제 #1
0
    def __init__(self,
                 need_log: bool = None,
                 engine: typing.Sequence = None,
                 pro_mode: bool = None,
                 *args,
                 **kwargs):
        """
        Init everything. Args here will init the engines too. Read __init__ part in engine.py for details.

        :param need_log: enable or disable logger
        :param engine: choose image processing engine, eg: ['feature', 'template']
        :param pro_mode:
        """
        # template pic dict,
        # { pic_name: pic_cv_object }
        self.template: typing.Dict[str, np.ndarray] = dict()

        # init logger
        self.switch_logger(bool(need_log))

        # init engine
        if not engine:
            # default
            engine = ['template', 'feature']
        self.engine_name_list: typing.List[str] = engine
        self.engine_list: typing.List[FindItEngine] = list()
        self.set_engine(engine, *args, **kwargs)

        # pro mode
        self.pro_mode = bool(pro_mode)
        logger.info(f'in pro mode: {self.pro_mode}')
예제 #2
0
 def switch_logger(status: bool):
     """ enable or disable logger """
     if status:
         logger.enable(LOGGER_FLAG)
         logger.info('logger up')
     else:
         logger.disable(LOGGER_FLAG)
예제 #3
0
    def __init__(self,
                 engine_template_cv_method_name: str = None,
                 engine_template_scale: typing.Sequence = None,
                 engine_template_multi_target_max_threshold: float = None,
                 engine_template_multi_target_distance_threshold: float = None,
                 *_,
                 **__):
        """ eg: engine_template_cv_method_name -> cv_method_name """
        logger.info('engine {} preparing ...'.format(self.get_type()))

        # cv
        self.cv_method_name = engine_template_cv_method_name or self.DEFAULT_CV_METHOD_NAME
        self.cv_method_code = eval(self.cv_method_name)

        # scale
        self.scale = engine_template_scale or self.DEFAULT_SCALE

        # multi target max threshold ( max_val * max_threshold == real threshold )
        self.multi_target_max_threshold = engine_template_multi_target_max_threshold or self.DEFAULT_MULTI_TARGET_MAX_THRESHOLD
        self.multi_target_distance_threshold = engine_template_multi_target_distance_threshold or self.DEFAULT_MULTI_TARGET_DISTANCE_THRESHOLD

        logger.debug(f'cv method: {self.cv_method_name}')
        logger.debug(f'scale: {self.scale}')
        logger.debug(
            f'multi target max threshold: {self.multi_target_max_threshold}')
        logger.debug(
            f'multi target distance threshold: {self.multi_target_distance_threshold}'
        )
        logger.info(f'engine {self.get_type()} loaded')
예제 #4
0
    def __init__(self, engine_sim_interpolation: int = None, *_, **__):
        logger.info(f'engine {self.get_type()} preparing ...')

        self.engine_sim_interpolation = engine_sim_interpolation or self.DEFAULT_INTERPOLATION

        logger.debug(f'interpolation: {self.DEFAULT_INTERPOLATION}')
        logger.info(f'engine {self.get_type()} loaded')
예제 #5
0
파일: core.py 프로젝트: zsg555/findit
    def find(
        self,
        target_pic_name: str,
        target_pic_path: str = None,
        target_pic_object: np.ndarray = None,
        *args,
        **kwargs,
    ) -> dict:
        """
        start match

        :param target_pic_name: eg: 'your_target_picture_1'
        :param target_pic_path: '/path/to/your/target.png'
        :param target_pic_object: your_pic_cv_object (loaded by cv2)

        kwargs here will be used to engine.execute(), which starts with engine_{engine_name}:

            # ocr
            engine_ocr_offset: int = None,
            engine_ocr_deep: bool = None,

            # template
            engine_template_mask_pic_object: np.ndarray = None,
            engine_template_mask_pic_path: str = None,
        :return:
        """

        # pre assert
        assert (target_pic_path
                is not None) or (target_pic_object
                                 is not None), "need path or cv object"

        # load target
        logger.info("start finding ...")
        target_pic_object = toolbox.pre_pic(target_pic_path, target_pic_object)

        if self._need_template():
            find_func = self._find_with_template
        else:
            find_func = self._find_without_template
        result = find_func(
            target_pic_object,
            target_pic_name=target_pic_name,
            target_pic_path=target_pic_path,
            *args,
            **kwargs,
        )
        return {
            "target_name": target_pic_name,
            "target_path": target_pic_path,
            "data": result,
        }
예제 #6
0
파일: core.py 프로젝트: zsg555/findit
    def __init__(
        self,
        need_log: bool = None,
        engine: typing.Sequence = None,
        pro_mode: bool = None,
        *args,
        **kwargs,
    ):
        """
        Init everything. Args here will init the engines too. Read __init__ part in engine.py for details.

        :param need_log: enable or disable logger
        :param engine: choose image processing engine, eg: ['feature', 'template']
        :param pro_mode:

        kwargs here will be used to init engine, which starts with engine_{engine_name} :

            # feature
            engine_feature_cluster_num: int = None,
            engine_feature_distance_threshold: float = None,
            engine_feature_min_hessian: int = None,

            # ocr
            engine_ocr_lang: str = None,

            # sim
            engine_sim_interpolation: int = None,

            # template
            engine_template_cv_method_name: str = None,
            engine_template_scale: typing.Sequence = None,
            engine_template_multi_target_max_threshold: float = None,
            engine_template_multi_target_distance_threshold: float = None,
            engine_template_compress_rate: float = None,
        """
        # template manager
        self.template: _TemplateManager = _TemplateManager()

        # init logger
        self.switch_logger(bool(need_log))

        # init engine
        if not engine:
            # default
            engine = ["template", "feature"]
        self.engine_name_list: typing.List[str] = engine
        self.engine_list: typing.List[FindItEngine] = list()
        self.set_engine(engine, *args, **kwargs)

        # pro mode
        self.pro_mode = bool(pro_mode)
        logger.info(f"in pro mode: {self.pro_mode}")
예제 #7
0
    def __init__(self, engine_ocr_lang: str = None, *_, **__):
        logger.info(f'engine {self.get_type()} preparing ...')

        # check language data before execute function, not here.
        self.engine_ocr_lang = engine_ocr_lang or self.DEFAULT_LANGUAGE
        self.engine_ocr_tess_data_dir, self.engine_ocr_available_lang_list = tesserocr.get_languages(
        )

        logger.debug(f'target lang: {self.engine_ocr_lang}')
        logger.debug(f'tess data dir: {self.engine_ocr_tess_data_dir}')
        logger.debug(
            f'available language: {self.engine_ocr_available_lang_list}')
        logger.info(f'engine {self.get_type()} loaded')
예제 #8
0
def start_server():
    logger.info(f"server port: {config.SERVER_PORT}")
    logger.info(f"pic root dir path: {config.PIC_DIR_PATH}")

    # check existed
    assert os.path.exists(
        config.PIC_DIR_PATH
    ), f"dir path not existed: {config.PIC_DIR_PATH}"

    from gevent import monkey, pywsgi

    monkey.patch_all()
    server = pywsgi.WSGIServer(("0.0.0.0", int(config.SERVER_PORT)), app)
    server.serve_forever()
예제 #9
0
    def __init__(self,
                 engine_feature_cluster_num: int = None,
                 engine_feature_distance_threshold: float = None,
                 *_,
                 **__):
        logger.info('engine {} preparing ...'.format(self.get_type()))

        # for kmeans calculation
        self.cluster_num: int = engine_feature_cluster_num or self.DEFAULT_CLUSTER_NUM
        # for feature matching
        self.distance_threshold: float = engine_feature_distance_threshold or self.DEFAULT_DISTANCE_THRESHOLD

        logger.debug('cluster num: {}'.format(self.cluster_num))
        logger.debug('distance threshold: {}'.format(self.distance_threshold))
        logger.info('engine {} loaded'.format(self.get_type()))
예제 #10
0
파일: template.py 프로젝트: zsg555/findit
    def __init__(
        self,
        engine_template_cv_method_name: str = None,
        engine_template_scale: typing.Sequence = None,
        engine_template_multi_target_max_threshold: float = None,
        engine_template_multi_target_distance_threshold: float = None,
        engine_template_compress_rate: float = None,
        *_,
        **__,
    ):
        """ eg: engine_template_cv_method_name -> cv_method_name """
        logger.info(f"engine {self.get_type()} preparing ...")

        # cv
        self.engine_template_cv_method_name = (engine_template_cv_method_name
                                               or self.DEFAULT_CV_METHOD_NAME)
        self.engine_template_cv_method_code = eval(
            self.engine_template_cv_method_name)

        # scale
        self.engine_template_scale = engine_template_scale or self.DEFAULT_SCALE

        # multi target max threshold ( max_val * max_threshold == real threshold )
        self.engine_template_multi_target_max_threshold = (
            engine_template_multi_target_max_threshold
            or self.DEFAULT_MULTI_TARGET_MAX_THRESHOLD)
        self.engine_template_multi_target_distance_threshold = (
            engine_template_multi_target_distance_threshold
            or self.DEFAULT_MULTI_TARGET_DISTANCE_THRESHOLD)

        # compression
        self.engine_template_compress_rate = (engine_template_compress_rate
                                              or self.DEFAULT_COMPRESS_RATE)

        logger.debug(f"cv method: {self.engine_template_cv_method_name}")
        logger.debug(f"scale: {self.engine_template_scale}")
        logger.debug(
            f"multi target max threshold: {self.engine_template_multi_target_max_threshold}"
        )
        logger.debug(
            f"multi target distance threshold: {self.engine_template_multi_target_distance_threshold}"
        )
        logger.debug(f"compress rate: {self.engine_template_compress_rate}")
        logger.info(f"engine {self.get_type()} loaded")
예제 #11
0
    def __init__(self, engine_ocr_lang: str = None, *_, **__):
        logger.info(f"engine {self.get_type()} preparing ...")

        # check language data before execute function, not here.
        self.engine_ocr_lang = engine_ocr_lang or self.DEFAULT_LANGUAGE
        self.engine_ocr_offset = self.DEFAULT_OFFSET
        self.engine_ocr_deep = self.DEFAULT_DEEP

        assert findtext, "findtext should be installed if you want to use OCR engine"
        self._ft = findtext.FindText(lang=engine_ocr_lang)

        self.engine_ocr_tess_data_dir = self._ft.get_data_home()
        self.engine_ocr_available_lang_list = self._ft.get_available_lang()

        logger.debug(f"target lang: {self.engine_ocr_lang}")
        logger.debug(f"tess data dir: {self.engine_ocr_tess_data_dir}")
        logger.debug(
            f"available language: {self.engine_ocr_available_lang_list}")
        logger.info(f"engine {self.get_type()} loaded")
예제 #12
0
파일: template.py 프로젝트: zsg555/findit
    def execute(
        self,
        template_object: np.ndarray,
        target_object: np.ndarray,
        engine_template_mask_pic_object: np.ndarray = None,
        engine_template_mask_pic_path: str = None,
        *_,
        **__,
    ) -> FindItEngineResponse:
        resp = FindItEngineResponse()
        resp.append("conf", self.__dict__)

        # mask
        if (engine_template_mask_pic_path
                is not None) or (engine_template_mask_pic_object is not None):
            logger.info("mask detected")
            engine_template_mask_pic_object = toolbox.pre_pic(
                engine_template_mask_pic_path, engine_template_mask_pic_object)

        # template matching
        min_val, max_val, min_loc, max_loc, point_list = self._compare_template(
            template_object,
            target_object,
            self.engine_template_scale,
            engine_template_mask_pic_object,
        )

        # 'target_point' must existed
        resp.append("target_point", max_loc, important=True)
        resp.append("target_sim", max_val, important=True)
        resp.append(
            "raw",
            {
                "min_val": min_val,
                "max_val": max_val,
                "min_loc": min_loc,
                "max_loc": max_loc,
                "all": point_list,
            },
        )
        resp.append("ok", True, important=True)

        return resp
예제 #13
0
    def __init__(self,
                 engine_feature_cluster_num: int = None,
                 engine_feature_distance_threshold: float = None,
                 engine_feature_min_hessian: int = None,
                 *_,
                 **__):
        logger.info(f'engine {self.get_type()} preparing ...')

        # for kmeans calculation
        self.engine_feature_cluster_num: int = engine_feature_cluster_num or self.DEFAULT_CLUSTER_NUM
        # for feature matching
        self.engine_feature_distance_threshold: float = engine_feature_distance_threshold or self.DEFAULT_DISTANCE_THRESHOLD
        # for determining if a point is a feature point
        # higher threshold, less points
        self.engine_feature_min_hessian: int = engine_feature_min_hessian or self.DEFAULT_MIN_HESSIAN

        logger.debug(f'cluster num: {self.engine_feature_cluster_num}')
        logger.debug(
            f'distance threshold: {self.engine_feature_distance_threshold}')
        logger.debug(f'hessian threshold: {self.engine_feature_min_hessian}')
        logger.info(f'engine {self.get_type()} loaded')
예제 #14
0
파일: core.py 프로젝트: zsg555/findit
    def load_template(self,
                      pic_name: str,
                      pic_path: str = None,
                      pic_object: np.ndarray = None):
        """
        load template picture

        :param pic_name: use pic name as result's key, eg: 'your_picture_1'
        :param pic_path: eg: '../your_picture.png'
        :param pic_object: eg: your_pic_cv_object)
        :return:
        """
        assert (pic_path
                is not None) or (pic_object
                                 is not None), "need path or cv object"

        if pic_object is not None:
            logger.info("load template from picture object directly ...")
            self.template.save(pic_name, pic_object)
        else:
            logger.info("load template from picture path ...")
            abs_path = os.path.abspath(pic_path)
            self.template.save(pic_name, abs_path)

        logger.info(f"load template [{pic_name}] successfully")
예제 #15
0
    def load_template(self,
                      pic_name: str,
                      pic_path: str = None,
                      pic_object: np.ndarray = None):
        """
        load template picture

        :param pic_name: use pic name as result's key, eg: 'your_picture_1'
        :param pic_path: eg: '../your_picture.png'
        :param pic_object: eg: your_pic_cv_object)
        :return:
        """
        assert (pic_path
                is not None) or (pic_object
                                 is not None), 'need path or cv object'

        if pic_object is not None:
            logger.info('load template from picture object directly ...')
            self.template[pic_name] = toolbox.load_grey_from_cv2_object(
                pic_object)
        else:
            logger.info('load template from picture path ...')
            abs_path = os.path.abspath(pic_path)
            self.template[pic_name] = toolbox.load_grey_from_path(abs_path)
        logger.info(f'load template [{pic_name}] successfully')
예제 #16
0
    def find(self,
             target_pic_name: str,
             target_pic_path: str = None,
             target_pic_object: np.ndarray = None,
             *args,
             **kwargs) -> dict:
        """
        start match

        :param target_pic_name: eg: 'your_target_picture_1'
        :param target_pic_path: '/path/to/your/target.png'
        :param target_pic_object: your_pic_cv_object (loaded by cv2)
        :return:
        """

        # pre assert
        assert (target_pic_path
                is not None) or (target_pic_object
                                 is not None), 'need path or cv object'

        # load target
        logger.info('start finding ...')
        target_pic_object = toolbox.pre_pic(target_pic_path, target_pic_object)

        if self._need_template():
            find_func = self._find_with_template
        else:
            find_func = self._find_without_template
        result = find_func(target_pic_object,
                           target_pic_name=target_pic_name,
                           target_pic_path=target_pic_path,
                           *args,
                           **kwargs)
        return {
            'target_name': target_pic_name,
            'target_path': target_pic_path,
            'data': result
        }
예제 #17
0
    def execute(self,
                template_object: np.ndarray,
                target_object: np.ndarray,
                mask_pic_object: np.ndarray = None,
                mask_pic_path: str = None,
                *_,
                **__) -> dict:
        # mask
        if (mask_pic_path is not None) or (mask_pic_object is not None):
            logger.info('mask detected')
            mask_pic_object = toolbox.pre_pic(mask_pic_path, mask_pic_object)

        # template matching
        min_val, max_val, min_loc, max_loc, point_list = self._compare_template(
            template_object, target_object, self.scale, mask_pic_object)

        # 'target_point' must existed
        return {
            'target_point': max_loc,
            'target_sim': max_val,
            'conf': {
                'engine_template_cv_method_name':
                self.cv_method_name,
                'engine_template_scale':
                self.scale,
                'engine_template_multi_target_max_threshold':
                self.multi_target_max_threshold,
                'engine_template_multi_target_distance_threshold':
                self.multi_target_distance_threshold
            },
            'raw': {
                'min_val': min_val,
                'max_val': max_val,
                'min_loc': min_loc,
                'max_loc': max_loc,
                'all': point_list,
            }
        }
예제 #18
0
    def execute(self,
                template_object: np.ndarray,
                target_object: np.ndarray,
                engine_template_mask_pic_object: np.ndarray = None,
                engine_template_mask_pic_path: str = None,
                *_,
                **__) -> FindItEngineResponse:
        resp = FindItEngineResponse()
        resp.append('conf', self.__dict__)

        # mask
        if (engine_template_mask_pic_path
                is not None) or (engine_template_mask_pic_object is not None):
            logger.info('mask detected')
            engine_template_mask_pic_object = toolbox.pre_pic(
                engine_template_mask_pic_path, engine_template_mask_pic_object)

        # template matching
        min_val, max_val, min_loc, max_loc, point_list = self._compare_template(
            template_object, target_object, self.engine_template_scale,
            engine_template_mask_pic_object)

        # 'target_point' must existed
        resp.append('target_point', max_loc, important=True)
        resp.append('target_sim', max_val, important=True)
        resp.append(
            'raw', {
                'min_val': min_val,
                'max_val': max_val,
                'min_loc': min_loc,
                'max_loc': max_loc,
                'all': point_list,
            })
        resp.append('ok', True, important=True)

        return resp
예제 #19
0
    def find(self,
             target_pic_name: str,
             target_pic_path: str = None,
             target_pic_object: np.ndarray = None,
             mark_pic: bool = None,
             *args,
             **kwargs):
        """
        start match

        :param target_pic_name: eg: 'your_target_picture_1'
        :param target_pic_path: '/path/to/your/target.png'
        :param target_pic_object: your_pic_cv_object (loaded by cv2)
        :param mark_pic: enable this, and you will get a picture file with a mark of result
        :return:
        """

        # pre assert
        assert self.template, 'template is empty'
        assert (target_pic_path
                is not None) or (target_pic_object
                                 is not None), 'need path or cv object'

        # load target
        logger.info('start finding ...')
        target_pic_object = toolbox.pre_pic(target_pic_path, target_pic_object)

        start_time = toolbox.get_timestamp()
        result = dict()
        for each_template_name, each_template_object in self.template.items():
            logger.debug(
                'start analysing: [{}] ...'.format(each_template_name))

            current_result = dict()
            for each_engine in self.engine_list:
                each_result = each_engine.execute(each_template_object,
                                                  target_pic_object, *args,
                                                  **kwargs)

                # need mark?
                if mark_pic:
                    target_pic_object_with_mark = toolbox.mark_point(
                        target_pic_object,
                        each_result['target_point'],
                        cover=False)
                    os.makedirs(start_time, exist_ok=True)
                    mark_pic_path = '{}/{}_{}.png'.format(
                        start_time, each_template_name, each_engine.get_type())
                    cv2.imwrite(mark_pic_path, target_pic_object_with_mark)
                    logger.debug(
                        'save marked picture to {}'.format(mark_pic_path))

                # result filter
                each_result = self._prune_result(each_result)

                current_result[each_engine.get_type()] = each_result

            logger.debug('result for [{}]: {}'.format(
                each_template_name, json.dumps(current_result)))
            result[each_template_name] = current_result

        final_result = {
            'target_name': target_pic_name,
            'target_path': target_pic_path,
            'data': result,
        }
        logger.info('result: {}'.format(json.dumps(final_result)))
        return final_result
예제 #20
0
 def set_engine(self, engine_name_list, *args, **kwargs):
     logger.info(f'set engine: {engine_name_list}')
     self.engine_list = [
         engine_dict[each](*args, **kwargs) for each in engine_name_list
     ]
예제 #21
0
 def clear(self):
     """ reset template, target and result """
     self.template = dict()
     logger.info('findit clear successfully')
예제 #22
0
 def set_engine(self, engine_name_list, *args, **kwargs):
     logger.info('set engine: {}'.format(engine_name_list))
     self.engine_list = [
         engine_dict[each](*args, **kwargs) for each in engine_name_list
     ]