diff --git a/docs/imgs/Readme_Related/Image_Classification_apple_pie.png b/docs/imgs/Readme_Related/Image_Classification_apple_pie.png new file mode 100644 index 0000000000000000000000000000000000000000..22de4d52837786bd053f38b1a678b8eb93ea573e Binary files /dev/null and b/docs/imgs/Readme_Related/Image_Classification_apple_pie.png differ diff --git a/modules/thirdparty/image/classification/food_classification/README.md b/modules/thirdparty/image/classification/food_classification/README.md new file mode 100644 index 0000000000000000000000000000000000000000..138bfcf037cc2e6d0f6ef71fb392b2d13cc2b309 --- /dev/null +++ b/modules/thirdparty/image/classification/food_classification/README.md @@ -0,0 +1,84 @@ +# food_classification + +类别 图像 - 图像分类 + +网络 ResNet50_vd_ssld + + +> 模型概述 + +美食分类(food_classification),该模型可识别苹果派,小排骨,烤面包,牛肉馅饼,牛肉鞑靼。该PaddleHub Module支持API预测及命令行预测。 + +> 选择模型版本进行安装 + +```shell +$ hub install food_classification==1.0.0 +``` +> Module API说明 + +```python +def predict(self, + images=None, + paths=None, + batch_size=1, + use_gpu=False, + **kwargs): +``` +美食分类预测接口,输入一张图像,输出该图像上食物的类别 + +参数 + +* images (list[numpy.ndarray]): 图片数据,ndarray.shape 为 [H, W, C],BGR格式; +* paths (list[str]): 图片的路径; +* batch_size (int): batch 的大小; +* use_gpu (bool): 是否使用 GPU; + +返回 + +* res (list[dict]): 识别结果的列表,列表中每一个元素为 dict,各字段为: + * category_id (int): 类别的id; + * category(str): 类别; + * score(float): 准确率; + +## 代码示例 + +### API调用 + +```python +import cv2 +import paddlehub as hub + +module = hub.Module(name="food_classification") + +images = [cv2.imread('PATH/TO/IMAGE')] + +# execute predict and print the result +results = module.predict(images=images) +for result in results: + print(result) +``` + +### 命令行调用 +```shell +$ hub run food_classification --input_path /PATH/TO/IMAGE --use_gpu True +``` + +## 效果展示 + +### 原图 + + +### 输出结果 +```python +[{'category_id': 0, 'category': 'apple_pie', 'score': 0.9985085}] +``` + +## 贡献者 +彭兆帅、郑博培 + +## 依赖 +paddlepaddle >= 2.0.0 + +paddlehub >= 2.0.0 + +paddlex >= 1.3.7 diff --git a/modules/thirdparty/image/classification/food_classification/__init__.py b/modules/thirdparty/image/classification/food_classification/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/modules/thirdparty/image/classification/food_classification/__init__.py @@ -0,0 +1 @@ + diff --git a/modules/thirdparty/image/classification/food_classification/module.py b/modules/thirdparty/image/classification/food_classification/module.py new file mode 100644 index 0000000000000000000000000000000000000000..af42cd40f347c640bc36cc510c606adc28e71ea9 --- /dev/null +++ b/modules/thirdparty/image/classification/food_classification/module.py @@ -0,0 +1,147 @@ +from __future__ import absolute_import +from __future__ import division + +import os +import cv2 +import argparse +import base64 +import paddlex as pdx + +import numpy as np +import paddlehub as hub +from paddlehub.module.module import moduleinfo, runnable, serving + + +def base64_to_cv2(b64str): + data = base64.b64decode(b64str.encode('utf8')) + data = np.fromstring(data, np.uint8) + data = cv2.imdecode(data, cv2.IMREAD_COLOR) + return data + + +def cv2_to_base64(image): + # return base64.b64encode(image) + data = cv2.imencode('.jpg', image)[1] + return base64.b64encode(data.tostring()).decode('utf8') + + +def read_images(paths): + images = [] + for path in paths: + images.append(cv2.imread(path)) + return images + + +@moduleinfo( + name='food_classification', + type='cv/classification', + author='郑博培、彭兆帅', + author_email='2733821739@qq.com, 1084667371@qq.com', + summary='Food classification', + version='1.0.0') +class MODULE(hub.Module): + def _initialize(self, **kwargs): + self.default_pretrained_model_path = os.path.join( + self.directory, 'assets') + self.model = pdx.deploy.Predictor(self.default_pretrained_model_path, + **kwargs) + + def predict(self, + images=None, + paths=None, + data=None, + batch_size=1, + use_gpu=False, + **kwargs): + + all_data = images if images is not None else read_images(paths) + total_num = len(all_data) + loop_num = int(np.ceil(total_num / batch_size)) + + res = [] + for iter_id in range(loop_num): + batch_data = list() + handle_id = iter_id * batch_size + for image_id in range(batch_size): + try: + batch_data.append(all_data[handle_id + image_id]) + except IndexError: + break + out = self.model.batch_predict(batch_data, **kwargs) + res.extend(out) + return res + + @serving + def serving_method(self, images, **kwargs): + """ + Run as a service. + """ + images_decode = [base64_to_cv2(image) for image in images] + results = self.predict(images_decode, **kwargs) + res = [] + for result in results: + if isinstance(result, dict): + # result_new = dict() + for key, value in result.items(): + if isinstance(value, np.ndarray): + result[key] = cv2_to_base64(value) + elif isinstance(value, np.generic): + result[key] = np.asscalar(value) + + elif isinstance(result, list): + for index in range(len(result)): + for key, value in result[index].items(): + if isinstance(value, np.ndarray): + result[index][key] = cv2_to_base64(value) + elif isinstance(value, np.generic): + result[index][key] = np.asscalar(value) + else: + raise RuntimeError('The result cannot be used in serving.') + res.append(result) + return res + + @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) + self.arg_input_group = self.parser.add_argument_group( + title="Input options", description="Input data. Required") + self.arg_config_group = self.parser.add_argument_group( + title="Config options", + description= + "Run configuration for controlling module behavior, not required.") + self.add_module_config_arg() + self.add_module_input_arg() + args = self.parser.parse_args(argvs) + results = self.predict( + paths=[args.input_path], + use_gpu=args.use_gpu) + return results + + def add_module_config_arg(self): + """ + Add the command config options. + """ + self.arg_config_group.add_argument( + '--use_gpu', + type=bool, + default=False, + help="whether use GPU or not") + + def add_module_input_arg(self): + """ + Add the command input options. + """ + self.arg_input_group.add_argument( + '--input_path', type=str, help="path to image.") + +if __name__ == '__main__': + module = MODULE(directory='./new_model') + images = [cv2.imread('./cat.jpg'), cv2.imread('./cat.jpg'), cv2.imread('./cat.jpg')] + res = module.predict(images=images) diff --git a/modules/thirdparty/image/classification/food_classification/requirements.txt b/modules/thirdparty/image/classification/food_classification/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..ad32066430096ff4050dce8930f74eae5eb9d2f0 --- /dev/null +++ b/modules/thirdparty/image/classification/food_classification/requirements.txt @@ -0,0 +1,3 @@ +paddlepaddle >= 2.0.0 +paddlehub >= 2.0.0 +paddlex >= 1.3.7