module.py 7.4 KB
Newer Older
W
wuzewu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
# coding=utf-8
from __future__ import absolute_import
from __future__ import division

import ast
import argparse
import os

import numpy as np
import paddle.fluid as fluid
import paddlehub as hub
from paddle.fluid.core import PaddleTensor, AnalysisConfig, create_paddle_predictor
from paddlehub.module.module import moduleinfo, runnable, serving

from pyramidbox_lite_mobile.data_feed import reader
from pyramidbox_lite_mobile.processor import postprocess, base64_to_cv2


@moduleinfo(
    name="pyramidbox_lite_mobile",
    type="CV/face_detection",
    author="baidu-vis",
    author_email="",
    summary="PyramidBox-Lite-Mobile is a high-performance face detection model.",
    version="1.2.0")
class PyramidBoxLiteMobile(hub.Module):
    def _initialize(self):
W
wuzewu 已提交
28
        self.default_pretrained_model_path = os.path.join(self.directory, "pyramidbox_lite_mobile_face_detection")
W
wuzewu 已提交
29
        self._set_config()
W
wuzewu 已提交
30
        self.processor = self
W
wuzewu 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

    def _set_config(self):
        """
        predictor config setting
        """
        cpu_config = AnalysisConfig(self.default_pretrained_model_path)
        cpu_config.disable_glog_info()
        cpu_config.disable_gpu()
        self.cpu_predictor = create_paddle_predictor(cpu_config)

        try:
            _places = os.environ["CUDA_VISIBLE_DEVICES"]
            int(_places[0])
            use_gpu = True
        except:
            use_gpu = False
        if use_gpu:
            gpu_config = AnalysisConfig(self.default_pretrained_model_path)
            gpu_config.disable_glog_info()
W
wuzewu 已提交
50
            gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0)
W
wuzewu 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
            self.gpu_predictor = create_paddle_predictor(gpu_config)

    def face_detection(self,
                       images=None,
                       paths=None,
                       data=None,
                       use_gpu=False,
                       output_dir='detection_result',
                       visualization=False,
                       shrink=0.5,
                       confs_threshold=0.6):
        """
        API for face detection.

        Args:
            images (list(numpy.ndarray)): images data, shape of each is [H, W, C]
            paths (list[str]): The paths of images.
            use_gpu (bool): Whether to use gpu.
            output_dir (str): The path to store output images.
            visualization (bool): Whether to save image or not.
            shrink (float): parameter to control the resize scale in preprocess.
            confs_threshold (float): confidence threshold.

        Returns:
            res (list[dict]): The result of face detection and save path of images.
        """
        if use_gpu:
            try:
                _places = os.environ["CUDA_VISIBLE_DEVICES"]
                int(_places[0])
            except:
                raise RuntimeError(
83
                    "Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id."
W
wuzewu 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
                )

        # compatibility with older versions
        if data:
            if 'image' in data:
                if paths is None:
                    paths = list()
                paths += data['image']
            elif 'data' in data:
                if images is None:
                    images = list()
                images += data['data']

        res = list()
        # process one by one
        for element in reader(images, paths, shrink):
            image = np.expand_dims(element['image'], axis=0).astype('float32')
            image_tensor = PaddleTensor(image.copy())
W
wuzewu 已提交
102
            data_out = self.gpu_predictor.run([image_tensor]) if use_gpu else self.cpu_predictor.run([image_tensor])
W
wuzewu 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115
            out = postprocess(
                data_out=data_out[0].as_ndarray(),
                org_im=element['org_im'],
                org_im_path=element['org_im_path'],
                image_width=element['image_width'],
                image_height=element['image_height'],
                output_dir=output_dir,
                visualization=visualization,
                shrink=shrink,
                confs_threshold=confs_threshold)
            res.append(out)
        return res

W
wuzewu 已提交
116
    def save_inference_model(self, dirname, model_filename=None, params_filename=None, combined=True):
W
wuzewu 已提交
117 118 119 120 121 122 123 124 125
        if combined:
            model_filename = "__model__" if not model_filename else model_filename
            params_filename = "__params__" if not params_filename else params_filename
        place = fluid.CPUPlace()
        exe = fluid.Executor(place)

        program, feeded_var_names, target_vars = fluid.io.load_inference_model(
            dirname=self.default_pretrained_model_path, executor=exe)

W
wuzewu 已提交
126 127 128
        var = program.global_block().vars['detection_output_0.tmp_1']
        var.desc.set_dtype(fluid.core.VarDesc.VarType.INT32)

W
wuzewu 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
        fluid.io.save_inference_model(
            dirname=dirname,
            main_program=program,
            executor=exe,
            feeded_var_names=feeded_var_names,
            target_vars=target_vars,
            model_filename=model_filename,
            params_filename=params_filename)

    @serving
    def serving_method(self, images, **kwargs):
        """
        Run as a service.
        """
        images_decode = [base64_to_cv2(image) for image in images]
        results = self.face_detection(images_decode, **kwargs)
        return results

    @runnable
    def run_cmd(self, argvs):
        """
        Run as a command.
        """
        self.parser = argparse.ArgumentParser(
            description="Run the {} module.".format(self.name),
            prog='hub run {}'.format(self.name),
            usage='%(prog)s',
            add_help=True)
W
wuzewu 已提交
157
        self.arg_input_group = self.parser.add_argument_group(title="Input options", description="Input data. Required")
W
wuzewu 已提交
158
        self.arg_config_group = self.parser.add_argument_group(
W
wuzewu 已提交
159
            title="Config options", description="Run configuration for controlling module behavior, not required.")
W
wuzewu 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        self.add_module_config_arg()
        self.add_module_input_arg()
        args = self.parser.parse_args(argvs)
        results = self.face_detection(
            paths=[args.input_path],
            use_gpu=args.use_gpu,
            output_dir=args.output_dir,
            visualization=args.visualization,
            shrink=args.shrink,
            confs_threshold=args.confs_threshold)
        return results

    def add_module_config_arg(self):
        """
        Add the command config options.
        """
        self.arg_config_group.add_argument(
W
wuzewu 已提交
177
            '--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not")
W
wuzewu 已提交
178
        self.arg_config_group.add_argument(
W
wuzewu 已提交
179
            '--output_dir', type=str, default='detection_result', help="The directory to save output images.")
W
wuzewu 已提交
180
        self.arg_config_group.add_argument(
W
wuzewu 已提交
181
            '--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.")
W
wuzewu 已提交
182 183 184 185 186

    def add_module_input_arg(self):
        """
        Add the command input options.
        """
W
wuzewu 已提交
187
        self.arg_input_group.add_argument('--input_path', type=str, help="path to image.")
W
wuzewu 已提交
188 189 190 191
        self.arg_input_group.add_argument(
            '--shrink',
            type=ast.literal_eval,
            default=0.5,
W
wuzewu 已提交
192
            help="resize the image to shrink * original_shape before feeding into network.")
W
wuzewu 已提交
193
        self.arg_input_group.add_argument(
W
wuzewu 已提交
194
            '--confs_threshold', type=ast.literal_eval, default=0.6, help="confidence threshold.")