From e301f5677b69f378d52ba74b3da01250810e7b98 Mon Sep 17 00:00:00 2001 From: jm12138 <2286040843@qq.com> Date: Thu, 29 Dec 2022 10:25:53 +0800 Subject: [PATCH] update humanseg_lite (#2181) --- .../humanseg_lite/README.md | 17 +- .../humanseg_lite/README_en.md | 24 +-- .../humanseg_lite/module.py | 151 +++++++++--------- .../humanseg_lite/optimal.py | 4 +- .../humanseg_lite/processor.py | 2 +- .../humanseg_lite/test.py | 98 ++++-------- 6 files changed, 136 insertions(+), 160 deletions(-) diff --git a/modules/image/semantic_segmentation/humanseg_lite/README.md b/modules/image/semantic_segmentation/humanseg_lite/README.md index 6f8cd16c..3bd4bc57 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/README.md +++ b/modules/image/semantic_segmentation/humanseg_lite/README.md @@ -1,7 +1,7 @@ # humanseg_lite |模型名称|humanseg_lite| -| :--- | :---: | +| :--- | :---: | |类别|图像-图像分割| |网络|shufflenet| |数据集|百度自建数据集| @@ -13,7 +13,7 @@ ## 一、模型基本信息 - ### 应用效果展示 - + - 样例结果示例:

@@ -37,7 +37,7 @@ - ```shell $ hub install humanseg_lite ``` - + - 如您安装时遇到问题,可参考:[零基础windows安装](../../../../docs/docs_ch/get_start/windows_quickstart.md) | [零基础Linux安装](../../../../docs/docs_ch/get_start/linux_quickstart.md) | [零基础MacOS安装](../../../../docs/docs_ch/get_start/mac_quickstart.md) @@ -226,6 +226,9 @@ cv2.imwrite("segment_human_lite.png", rgba) ``` +- ### Gradio APP 支持 + + 从 PaddleHub 2.3.1 开始支持使用链接 http://127.0.0.1:8866/gradio/humanseg_lite 在浏览器中访问 humanseg_lite 的 Gradio APP。 ## 五、更新历史 @@ -234,7 +237,7 @@ 初始发布 * 1.1.0 - + 新增视频人像分割接口 新增视频流人像分割接口 @@ -247,6 +250,10 @@ 移除 Fluid API +* 1.3.0 + + 添加 Gradio APP 支持 + ```shell - $ hub install humanseg_lite == 1.2.0 + $ hub install humanseg_lite == 1.3.0 ``` diff --git a/modules/image/semantic_segmentation/humanseg_lite/README_en.md b/modules/image/semantic_segmentation/humanseg_lite/README_en.md index 4240a187..c6a41793 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/README_en.md +++ b/modules/image/semantic_segmentation/humanseg_lite/README_en.md @@ -1,7 +1,7 @@ # humanseg_lite |Module Name |humanseg_lite| -| :--- | :---: | +| :--- | :---: | |Category |Image segmentation| |Network|shufflenet| |Dataset|Baidu self-built dataset| @@ -10,10 +10,10 @@ |Data indicators|-| |Latest update date|2021-02-26| -## I. Basic Information +## I. Basic Information - ### Application Effect Display - + - Sample results:

@@ -39,7 +39,7 @@ - ```shell $ hub install humanseg_lite ``` - + - In case of any problems during installation, please refer to:[Windows_Quickstart](../../../../docs/docs_en/get_start/windows_quickstart.md) | [Linux_Quickstart](../../../../docs/docs_en/get_start/linux_quickstart.md) | [Mac_Quickstart](../../../../docs/docs_en/get_start/mac_quickstart.md) @@ -49,7 +49,7 @@ - ``` hub run humanseg_lite --input_path "/PATH/TO/IMAGE" - + ``` - If you want to call the Hub module through the command line, please refer to: [PaddleHub Command Line Instruction](../../../../docs/docs_en/tutorial/cmd_usage.rst) @@ -122,9 +122,9 @@ - **Return** - * res (list\[dict\]): The list of recognition results, where each element is dict and each field is: + * res (list\[dict\]): The list of recognition results, where each element is dict and each field is: * save\_path (str, optional): Save path of the result. - * data (numpy.ndarray): The result of portrait segmentation. + * data (numpy.ndarray): The result of portrait segmentation. - ```python def video_stream_segment(self, @@ -230,6 +230,8 @@ cv2.imwrite("segment_human_lite.png", rgba) ``` +- ### Gradio APP support + Starting with PaddleHub 2.3.1, the Gradio APP for humanseg_lite is supported to be accessed in the browser using the link http://127.0.0.1:8866/gradio/humanseg_lite. ## V. Release Note @@ -238,7 +240,7 @@ First release - 1.1.0 - + Added video portrait segmentation interface Added video stream portrait segmentation interface @@ -251,6 +253,10 @@ Remove Fluid API +* 1.3.0 + + Add Gradio APP support. + ```shell - $ hub install humanseg_lite == 1.2.0 + $ hub install humanseg_lite == 1.3.0 ``` diff --git a/modules/image/semantic_segmentation/humanseg_lite/module.py b/modules/image/semantic_segmentation/humanseg_lite/module.py index 600d4c28..17a17159 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/module.py +++ b/modules/image/semantic_segmentation/humanseg_lite/module.py @@ -12,32 +12,39 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import argparse import ast import os import os.path as osp -import argparse import cv2 import numpy as np -import paddle import paddle.jit import paddle.static -from paddle.inference import Config, create_predictor -from paddlehub.module.module import moduleinfo, runnable, serving - -from .processor import postprocess, base64_to_cv2, cv2_to_base64, check_dir -from .data_feed import reader, preprocess_v -from .optimal import postprocess_v, threshold_mask - - -@moduleinfo( - name="humanseg_lite", - type="CV/semantic_segmentation", - author="paddlepaddle", - author_email="", - summary="humanseg_lite is a semantic segmentation model.", - version="1.2.0") +from paddle.inference import Config +from paddle.inference import create_predictor + +from .data_feed import preprocess_v +from .data_feed import reader +from .optimal import postprocess_v +from .optimal import threshold_mask +from .processor import base64_to_cv2 +from .processor import check_dir +from .processor import cv2_to_base64 +from .processor import postprocess +from paddlehub.module.module import moduleinfo +from paddlehub.module.module import runnable +from paddlehub.module.module import serving + + +@moduleinfo(name="humanseg_lite", + type="CV/semantic_segmentation", + author="paddlepaddle", + author_email="", + summary="humanseg_lite is a semantic segmentation model.", + version="1.3.0") class ShufflenetHumanSeg: + def __init__(self): self.default_pretrained_model_path = os.path.join(self.directory, "humanseg_lite_inference", "model") self._set_config() @@ -46,8 +53,8 @@ class ShufflenetHumanSeg: """ predictor config setting """ - model = self.default_pretrained_model_path+'.pdmodel' - params = self.default_pretrained_model_path+'.pdiparams' + model = self.default_pretrained_model_path + '.pdmodel' + params = self.default_pretrained_model_path + '.pdiparams' cpu_config = Config(model, params) cpu_config.disable_glog_info() cpu_config.disable_gpu() @@ -64,7 +71,7 @@ class ShufflenetHumanSeg: gpu_config = Config(model, params) gpu_config.disable_glog_info() gpu_config.enable_use_gpu(memory_pool_init_size_mb=1000, device_id=0) - + if paddle.get_cudnn_version() == 8004: gpu_config.delete_pass('conv_elementwise_add_act_fuse_pass') gpu_config.delete_pass('conv_elementwise_add2_act_fuse_pass') @@ -134,13 +141,12 @@ class ShufflenetHumanSeg: output = np.expand_dims(output[:, 1, :, :], axis=1) # postprocess one by one for i in range(len(batch_data)): - out = postprocess( - data_out=output[i], - org_im=batch_data[i]['org_im'], - org_im_shape=batch_data[i]['org_im_shape'], - org_im_path=batch_data[i]['org_im_path'], - output_dir=output_dir, - visualization=visualization) + out = postprocess(data_out=output[i], + org_im=batch_data[i]['org_im'], + org_im_shape=batch_data[i]['org_im_shape'], + org_im_path=batch_data[i]['org_im_path'], + output_dir=output_dir, + visualization=visualization) res.append(out) return res @@ -327,11 +333,10 @@ class ShufflenetHumanSeg: """ 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.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( @@ -339,12 +344,11 @@ class ShufflenetHumanSeg: self.add_module_config_arg() self.add_module_input_arg() args = self.parser.parse_args(argvs) - results = self.segment( - paths=[args.input_path], - batch_size=args.batch_size, - use_gpu=args.use_gpu, - output_dir=args.output_dir, - visualization=args.visualization) + results = self.segment(paths=[args.input_path], + batch_size=args.batch_size, + use_gpu=args.use_gpu, + output_dir=args.output_dir, + visualization=args.visualization) if args.save_dir is not None: check_dir(args.save_dir) self.save_inference_model(args.save_dir) @@ -355,14 +359,22 @@ class ShufflenetHumanSeg: """ Add the command config options. """ - self.arg_config_group.add_argument( - '--use_gpu', type=ast.literal_eval, default=False, help="whether use GPU or not") - self.arg_config_group.add_argument( - '--output_dir', type=str, default='humanseg_lite_output', help="The directory to save output images.") - self.arg_config_group.add_argument( - '--save_dir', type=str, default='humanseg_lite_model', help="The directory to save model.") - self.arg_config_group.add_argument( - '--visualization', type=ast.literal_eval, default=False, help="whether to save output as images.") + self.arg_config_group.add_argument('--use_gpu', + type=ast.literal_eval, + default=False, + help="whether use GPU or not") + self.arg_config_group.add_argument('--output_dir', + type=str, + default='humanseg_lite_output', + help="The directory to save output images.") + self.arg_config_group.add_argument('--save_dir', + type=str, + default='humanseg_lite_model', + help="The directory to save model.") + self.arg_config_group.add_argument('--visualization', + type=ast.literal_eval, + default=False, + help="whether to save output as images.") self.arg_config_group.add_argument('--batch_size', type=ast.literal_eval, default=1, help="batch size.") def add_module_input_arg(self): @@ -371,33 +383,20 @@ class ShufflenetHumanSeg: """ self.arg_input_group.add_argument('--input_path', type=str, help="path to image.") - -if __name__ == "__main__": - m = ShufflenetHumanSeg() - #shuffle.video_segment() - img = cv2.imread('photo.jpg') - # res = m.segment(images=[img], visualization=True) - # print(res[0]['data']) - # m.video_segment('') - cap_video = cv2.VideoCapture('video_test.mp4') - fps = cap_video.get(cv2.CAP_PROP_FPS) - save_path = 'result_frame.avi' - width = int(cap_video.get(cv2.CAP_PROP_FRAME_WIDTH)) - height = int(cap_video.get(cv2.CAP_PROP_FRAME_HEIGHT)) - cap_out = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps, (width, height)) - prev_gray = None - prev_cfd = None - while cap_video.isOpened(): - ret, frame_org = cap_video.read() - if ret: - [img_matting, prev_gray, prev_cfd] = m.video_stream_segment( - frame_org=frame_org, frame_id=cap_video.get(1), prev_gray=prev_gray, prev_cfd=prev_cfd) - img_matting = np.repeat(img_matting[:, :, np.newaxis], 3, axis=2) - bg_im = np.ones_like(img_matting) * 255 - comb = (img_matting * frame_org + (1 - img_matting) * bg_im).astype(np.uint8) - cap_out.write(comb) - else: - break - - cap_video.release() - cap_out.release() + def create_gradio_app(self): + import gradio as gr + import tempfile + import os + from PIL import Image + + def inference(image, use_gpu=False): + with tempfile.TemporaryDirectory() as temp_dir: + self.segment(paths=[image], use_gpu=use_gpu, visualization=True, output_dir=temp_dir) + return Image.open(os.path.join(temp_dir, os.listdir(temp_dir)[0])) + + interface = gr.Interface( + inference, + [gr.inputs.Image(type="filepath"), gr.Checkbox(label='use_gpu')], + gr.outputs.Image(type="ndarray"), + title='humanseg_lite') + return interface diff --git a/modules/image/semantic_segmentation/humanseg_lite/optimal.py b/modules/image/semantic_segmentation/humanseg_lite/optimal.py index da7aa514..aeae7c50 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/optimal.py +++ b/modules/image/semantic_segmentation/humanseg_lite/optimal.py @@ -32,8 +32,8 @@ def human_seg_tracking(pre_gray, cur_gray, prev_cfd, dl_weights, disflow): # 超出边界不跟踪 not_track = (cur_x < 0) + (cur_x >= w) + (cur_y < 0) + (cur_y >= h) flow_bw[~not_track] = flow_bw[cur_y[~not_track], cur_x[~not_track]] - not_track += ( - np.square(flow_fw[:, :, 0] + flow_bw[:, :, 0]) + np.square(flow_fw[:, :, 1] + flow_bw[:, :, 1])) >= check_thres + not_track += (np.square(flow_fw[:, :, 0] + flow_bw[:, :, 0]) + + np.square(flow_fw[:, :, 1] + flow_bw[:, :, 1])) >= check_thres track_cfd[cur_y[~not_track], cur_x[~not_track]] = prev_cfd[~not_track] is_track[cur_y[~not_track], cur_x[~not_track]] = 1 diff --git a/modules/image/semantic_segmentation/humanseg_lite/processor.py b/modules/image/semantic_segmentation/humanseg_lite/processor.py index 9cd53a84..a3e83622 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/processor.py +++ b/modules/image/semantic_segmentation/humanseg_lite/processor.py @@ -1,7 +1,7 @@ # -*- coding:utf-8 -*- +import base64 import os import time -import base64 import cv2 import numpy as np diff --git a/modules/image/semantic_segmentation/humanseg_lite/test.py b/modules/image/semantic_segmentation/humanseg_lite/test.py index df433469..b864da71 100644 --- a/modules/image/semantic_segmentation/humanseg_lite/test.py +++ b/modules/image/semantic_segmentation/humanseg_lite/test.py @@ -3,15 +3,16 @@ import shutil import unittest import cv2 -import requests import numpy as np -import paddlehub as hub +import requests +import paddlehub as hub os.environ['CUDA_VISIBLE_DEVICES'] = '0' class TestHubModule(unittest.TestCase): + @classmethod def setUpClass(cls) -> None: img_url = 'https://unsplash.com/photos/pg_WCHWSdT8/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjYyNDM2ODI4&force=true&w=640' @@ -23,8 +24,7 @@ class TestHubModule(unittest.TestCase): f.write(response.content) fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') img = cv2.imread('tests/test.jpg') - video = cv2.VideoWriter('tests/test.avi', fourcc, - 20.0, tuple(img.shape[:2])) + video = cv2.VideoWriter('tests/test.avi', fourcc, 20.0, tuple(img.shape[:2])) for i in range(40): video.write(img) video.release() @@ -38,101 +38,65 @@ class TestHubModule(unittest.TestCase): shutil.rmtree('humanseg_lite_video_result') def test_segment1(self): - results = self.module.segment( - paths=['tests/test.jpg'], - use_gpu=False, - visualization=False - ) + results = self.module.segment(paths=['tests/test.jpg'], use_gpu=False, visualization=False) self.assertIsInstance(results[0]['data'], np.ndarray) def test_segment2(self): - results = self.module.segment( - images=[cv2.imread('tests/test.jpg')], - use_gpu=False, - visualization=False - ) + results = self.module.segment(images=[cv2.imread('tests/test.jpg')], use_gpu=False, visualization=False) self.assertIsInstance(results[0]['data'], np.ndarray) def test_segment3(self): - results = self.module.segment( - images=[cv2.imread('tests/test.jpg')], - use_gpu=False, - visualization=True - ) + results = self.module.segment(images=[cv2.imread('tests/test.jpg')], use_gpu=False, visualization=True) self.assertIsInstance(results[0]['data'], np.ndarray) def test_segment4(self): - results = self.module.segment( - images=[cv2.imread('tests/test.jpg')], - use_gpu=True, - visualization=False - ) + results = self.module.segment(images=[cv2.imread('tests/test.jpg')], use_gpu=True, visualization=False) self.assertIsInstance(results[0]['data'], np.ndarray) def test_segment5(self): - self.assertRaises( - AssertionError, - self.module.segment, - paths=['no.jpg'] - ) + self.assertRaises(AssertionError, self.module.segment, paths=['no.jpg']) def test_segment6(self): - self.assertRaises( - AttributeError, - self.module.segment, - images=['test.jpg'] - ) + self.assertRaises(AttributeError, self.module.segment, images=['test.jpg']) def test_video_stream_segment1(self): - img_matting, cur_gray, optflow_map = self.module.video_stream_segment( - frame_org=cv2.imread('tests/test.jpg'), - frame_id=1, - prev_gray=None, - prev_cfd=None, - use_gpu=False - ) + img_matting, cur_gray, optflow_map = self.module.video_stream_segment(frame_org=cv2.imread('tests/test.jpg'), + frame_id=1, + prev_gray=None, + prev_cfd=None, + use_gpu=False) self.assertIsInstance(img_matting, np.ndarray) self.assertIsInstance(cur_gray, np.ndarray) self.assertIsInstance(optflow_map, np.ndarray) - img_matting, cur_gray, optflow_map = self.module.video_stream_segment( - frame_org=cv2.imread('tests/test.jpg'), - frame_id=2, - prev_gray=cur_gray, - prev_cfd=optflow_map, - use_gpu=False - ) + img_matting, cur_gray, optflow_map = self.module.video_stream_segment(frame_org=cv2.imread('tests/test.jpg'), + frame_id=2, + prev_gray=cur_gray, + prev_cfd=optflow_map, + use_gpu=False) self.assertIsInstance(img_matting, np.ndarray) self.assertIsInstance(cur_gray, np.ndarray) self.assertIsInstance(optflow_map, np.ndarray) def test_video_stream_segment2(self): - img_matting, cur_gray, optflow_map = self.module.video_stream_segment( - frame_org=cv2.imread('tests/test.jpg'), - frame_id=1, - prev_gray=None, - prev_cfd=None, - use_gpu=True - ) + img_matting, cur_gray, optflow_map = self.module.video_stream_segment(frame_org=cv2.imread('tests/test.jpg'), + frame_id=1, + prev_gray=None, + prev_cfd=None, + use_gpu=True) self.assertIsInstance(img_matting, np.ndarray) self.assertIsInstance(cur_gray, np.ndarray) self.assertIsInstance(optflow_map, np.ndarray) - img_matting, cur_gray, optflow_map = self.module.video_stream_segment( - frame_org=cv2.imread('tests/test.jpg'), - frame_id=2, - prev_gray=cur_gray, - prev_cfd=optflow_map, - use_gpu=True - ) + img_matting, cur_gray, optflow_map = self.module.video_stream_segment(frame_org=cv2.imread('tests/test.jpg'), + frame_id=2, + prev_gray=cur_gray, + prev_cfd=optflow_map, + use_gpu=True) self.assertIsInstance(img_matting, np.ndarray) self.assertIsInstance(cur_gray, np.ndarray) self.assertIsInstance(optflow_map, np.ndarray) def test_video_segment1(self): - self.module.video_segment( - video_path="tests/test.avi", - use_gpu=False, - save_dir='humanseg_lite_video_result' - ) + self.module.video_segment(video_path="tests/test.avi", use_gpu=False, save_dir='humanseg_lite_video_result') def test_save_inference_model(self): self.module.save_inference_model('./inference/model') -- GitLab