diff --git a/contrib/ACE2P/config.py b/contrib/ACE2P/config.py index f6ad509581a84d04bc1b6badca83648505c19444..a1fad0ec1e6c50493a0a8dfab0c5301add410ad0 100644 --- a/contrib/ACE2P/config.py +++ b/contrib/ACE2P/config.py @@ -6,13 +6,13 @@ args = get_arguments() cfg = AttrDict() # 待预测图像所在路径 -cfg.data_dir = os.path.join(args.example , "data", "testing_images") +cfg.data_dir = os.path.join("data", "testing_images") # 待预测图像名称列表 -cfg.data_list_file = os.path.join(args.example , "data", "test_id.txt") +cfg.data_list_file = os.path.join("data", "test_id.txt") # 模型加载路径 -cfg.model_path = os.path.join(args.example , "ACE2P") +cfg.model_path = args.example # 预测结果保存路径 -cfg.vis_dir = os.path.join(args.example , "result") +cfg.vis_dir = "result" # 预测类别数 cfg.class_num = 20 diff --git a/contrib/ACE2P/download_ACE2P.py b/contrib/ACE2P/download_ACE2P.py new file mode 100644 index 0000000000000000000000000000000000000000..bb4d33771dbd879a2d77664d2e0e45ed33b9bcb2 --- /dev/null +++ b/contrib/ACE2P/download_ACE2P.py @@ -0,0 +1,31 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License" +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 sys +import os + +LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) +TEST_PATH = os.path.join(LOCAL_PATH, "..", "..", "test") +sys.path.append(TEST_PATH) + +from test_utils import download_file_and_uncompress + +if __name__ == "__main__": + download_file_and_uncompress( + url='https://paddleseg.bj.bcebos.com/models/ACE2P.tgz', + savepath=LOCAL_PATH, + extrapath=LOCAL_PATH, + extraname='ACE2P') + + print("Pretrained Model download success!") diff --git a/contrib/ACE2P/imgs/117676_2149260.jpg b/contrib/ACE2P/imgs/117676_2149260.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8314d8f8cc723b6f96785053bdcfe39d867755d5 Binary files /dev/null and b/contrib/ACE2P/imgs/117676_2149260.jpg differ diff --git a/contrib/ACE2P/imgs/117676_2149260.png b/contrib/ACE2P/imgs/117676_2149260.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a9529644ead2013748431a3ade2f34264f19de Binary files /dev/null and b/contrib/ACE2P/imgs/117676_2149260.png differ diff --git a/contrib/ACE2P/infer.py b/contrib/ACE2P/infer.py new file mode 100644 index 0000000000000000000000000000000000000000..16eddc1eab8628eec7e38d27b1f18df13dd480d7 --- /dev/null +++ b/contrib/ACE2P/infer.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +import os +import cv2 +import numpy as np +from utils.util import get_arguments +from utils.palette import get_palette +from PIL import Image as PILImage +import importlib + +args = get_arguments() +config = importlib.import_module('config') +cfg = getattr(config, 'cfg') + +# paddle垃圾回收策略FLAG,ACE2P模型较大,当显存不够时建议开启 +os.environ['FLAGS_eager_delete_tensor_gb']='0.0' + +import paddle.fluid as fluid + +# 预测数据集类 +class TestDataSet(): + def __init__(self): + self.data_dir = cfg.data_dir + self.data_list_file = cfg.data_list_file + self.data_list = self.get_data_list() + self.data_num = len(self.data_list) + + def get_data_list(self): + # 获取预测图像路径列表 + data_list = [] + data_file_handler = open(self.data_list_file, 'r') + for line in data_file_handler: + img_name = line.strip() + name_prefix = img_name.split('.')[0] + if len(img_name.split('.')) == 1: + img_name = img_name + '.jpg' + img_path = os.path.join(self.data_dir, img_name) + data_list.append(img_path) + return data_list + + def preprocess(self, img): + # 图像预处理 + if cfg.example == 'ACE2P': + reader = importlib.import_module('reader') + ACE2P_preprocess = getattr(reader, 'preprocess') + img = ACE2P_preprocess(img) + else: + img = cv2.resize(img, cfg.input_size).astype(np.float32) + img -= np.array(cfg.MEAN) + img /= np.array(cfg.STD) + img = img.transpose((2, 0, 1)) + img = np.expand_dims(img, axis=0) + return img + + def get_data(self, index): + # 获取图像信息 + img_path = self.data_list[index] + img = cv2.imread(img_path, cv2.IMREAD_COLOR) + if img is None: + return img, img,img_path, None + + img_name = img_path.split(os.sep)[-1] + name_prefix = img_name.replace('.'+img_name.split('.')[-1],'') + img_shape = img.shape[:2] + img_process = self.preprocess(img) + + return img, img_process, name_prefix, img_shape + + +def infer(): + if not os.path.exists(cfg.vis_dir): + os.makedirs(cfg.vis_dir) + palette = get_palette(cfg.class_num) + # 人像分割结果显示阈值 + thresh = 120 + + place = fluid.CUDAPlace(0) if cfg.use_gpu else fluid.CPUPlace() + exe = fluid.Executor(place) + + # 加载预测模型 + test_prog, feed_name, fetch_list = fluid.io.load_inference_model( + dirname=cfg.model_path, executor=exe, params_filename='__params__') + + #加载预测数据集 + test_dataset = TestDataSet() + data_num = test_dataset.data_num + + for idx in range(data_num): + # 数据获取 + ori_img, image, im_name, im_shape = test_dataset.get_data(idx) + if image is None: + print(im_name, 'is None') + continue + + # 预测 + if cfg.example == 'ACE2P': + # ACE2P模型使用多尺度预测 + reader = importlib.import_module('reader') + multi_scale_test = getattr(reader, 'multi_scale_test') + parsing, logits = multi_scale_test(exe, test_prog, feed_name, fetch_list, image, im_shape) + else: + # HumanSeg,RoadLine模型单尺度预测 + result = exe.run(program=test_prog, feed={feed_name[0]: image}, fetch_list=fetch_list) + parsing = np.argmax(result[0][0], axis=0) + parsing = cv2.resize(parsing.astype(np.uint8), im_shape[::-1]) + + # 预测结果保存 + result_path = os.path.join(cfg.vis_dir, im_name + '.png') + if cfg.example == 'HumanSeg': + logits = result[0][0][1]*255 + logits = cv2.resize(logits, im_shape[::-1]) + ret, logits = cv2.threshold(logits, thresh, 0, cv2.THRESH_TOZERO) + logits = 255 *(logits - thresh)/(255 - thresh) + # 将分割结果添加到alpha通道 + rgba = np.concatenate((ori_img, np.expand_dims(logits, axis=2)), axis=2) + cv2.imwrite(result_path, rgba) + else: + output_im = PILImage.fromarray(np.asarray(parsing, dtype=np.uint8)) + output_im.putpalette(palette) + output_im.save(result_path) + + if (idx + 1) % 100 == 0: + print('%d processd' % (idx + 1)) + + print('%d processd done' % (idx + 1)) + + return 0 + + +if __name__ == "__main__": + infer() diff --git a/contrib/ACE2P/reader.py b/contrib/ACE2P/reader.py index 0a266637f3cf425a1bc3d61ad7377ff30de55723..ef5cc370738daf8550adfc20c227f942f1dd300f 100644 --- a/contrib/ACE2P/reader.py +++ b/contrib/ACE2P/reader.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import numpy as np import paddle.fluid as fluid -from ACE2P.config import cfg +from config import cfg import cv2 def get_affine_points(src_shape, dst_shape, rot_grad=0): diff --git a/contrib/utils/__init__.py b/contrib/ACE2P/utils/__init__.py similarity index 100% rename from contrib/utils/__init__.py rename to contrib/ACE2P/utils/__init__.py diff --git a/contrib/utils/palette.py b/contrib/ACE2P/utils/palette.py similarity index 100% rename from contrib/utils/palette.py rename to contrib/ACE2P/utils/palette.py diff --git a/contrib/utils/util.py b/contrib/ACE2P/utils/util.py similarity index 100% rename from contrib/utils/util.py rename to contrib/ACE2P/utils/util.py diff --git a/contrib/imgs/Human.jpg b/contrib/HumanSeg/imgs/Human.jpg similarity index 100% rename from contrib/imgs/Human.jpg rename to contrib/HumanSeg/imgs/Human.jpg diff --git a/contrib/imgs/HumanSeg.jpg b/contrib/HumanSeg/imgs/HumanSeg.jpg similarity index 100% rename from contrib/imgs/HumanSeg.jpg rename to contrib/HumanSeg/imgs/HumanSeg.jpg diff --git a/contrib/infer.py b/contrib/HumanSeg/infer.py similarity index 98% rename from contrib/infer.py rename to contrib/HumanSeg/infer.py index 8f939c8455cd3868120781a7a8d96ace0ff772b1..971476933c431977ce80c73e1d939fe079e1af19 100644 --- a/contrib/infer.py +++ b/contrib/HumanSeg/infer.py @@ -8,7 +8,7 @@ from PIL import Image as PILImage import importlib args = get_arguments() -config = importlib.import_module(args.example+'.config') +config = importlib.import_module('config') cfg = getattr(config, 'cfg') # paddle垃圾回收策略FLAG,ACE2P模型较大,当显存不够时建议开启 diff --git a/contrib/HumanSeg/utils/__init__.py b/contrib/HumanSeg/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/contrib/HumanSeg/utils/palette.py b/contrib/HumanSeg/utils/palette.py new file mode 100644 index 0000000000000000000000000000000000000000..2186203cbc2789f6eff70dfd92f724b4fe16cdb7 --- /dev/null +++ b/contrib/HumanSeg/utils/palette.py @@ -0,0 +1,38 @@ +##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +## Created by: RainbowSecret +## Microsoft Research +## yuyua@microsoft.com +## Copyright (c) 2018 +## +## This source code is licensed under the MIT-style license found in the +## LICENSE file in the root directory of this source tree +##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import numpy as np +import cv2 + + +def get_palette(num_cls): + """ Returns the color map for visualizing the segmentation mask. + Args: + num_cls: Number of classes + Returns: + The color map + """ + n = num_cls + palette = [0] * (n * 3) + for j in range(0, n): + lab = j + palette[j * 3 + 0] = 0 + palette[j * 3 + 1] = 0 + palette[j * 3 + 2] = 0 + i = 0 + while lab: + palette[j * 3 + 0] |= (((lab >> 0) & 1) << (7 - i)) + palette[j * 3 + 1] |= (((lab >> 1) & 1) << (7 - i)) + palette[j * 3 + 2] |= (((lab >> 2) & 1) << (7 - i)) + i += 1 + lab >>= 3 + return palette diff --git a/contrib/HumanSeg/utils/util.py b/contrib/HumanSeg/utils/util.py new file mode 100644 index 0000000000000000000000000000000000000000..7394870e7c94c1fb16169e314696b931eecdc3b2 --- /dev/null +++ b/contrib/HumanSeg/utils/util.py @@ -0,0 +1,47 @@ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +import argparse +import os + +def get_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("--use_gpu", + action="store_true", + help="Use gpu or cpu to test.") + parser.add_argument('--example', + type=str, + help='RoadLine, HumanSeg or ACE2P') + + return parser.parse_args() + + +class AttrDict(dict): + def __init__(self, *args, **kwargs): + super(AttrDict, self).__init__(*args, **kwargs) + + def __getattr__(self, name): + if name in self.__dict__: + return self.__dict__[name] + elif name in self: + return self[name] + else: + raise AttributeError(name) + + def __setattr__(self, name, value): + if name in self.__dict__: + self.__dict__[name] = value + else: + self[name] = value + +def merge_cfg_from_args(args, cfg): + """Merge config keys, values in args into the global config.""" + for k, v in vars(args).items(): + d = cfg + try: + value = eval(v) + except: + value = v + if value is not None: + cfg[k] = value + diff --git a/dataset/download_mini_mechanical_industry_meter.py b/contrib/MechanicalIndustryMeter/download_mini_mechanical_industry_meter.py similarity index 95% rename from dataset/download_mini_mechanical_industry_meter.py rename to contrib/MechanicalIndustryMeter/download_mini_mechanical_industry_meter.py index 3049df25219df7641990cedd409566779012a08d..f0409581ea9454417c545aa616b98ee8ece4dc53 100644 --- a/dataset/download_mini_mechanical_industry_meter.py +++ b/contrib/MechanicalIndustryMeter/download_mini_mechanical_industry_meter.py @@ -16,7 +16,7 @@ import sys import os LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) -TEST_PATH = os.path.join(LOCAL_PATH, "..", "test") +TEST_PATH = os.path.join(LOCAL_PATH, "..", "..", "test") sys.path.append(TEST_PATH) from test_utils import download_file_and_uncompress diff --git a/contrib/MechanicalIndustryMeter/download_unet_mechanical_industry_meter.py b/contrib/MechanicalIndustryMeter/download_unet_mechanical_industry_meter.py new file mode 100644 index 0000000000000000000000000000000000000000..aa55bf5e03b8dcf31e52043fd5dc87086c03c32f --- /dev/null +++ b/contrib/MechanicalIndustryMeter/download_unet_mechanical_industry_meter.py @@ -0,0 +1,30 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License" +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 sys +import os + +LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) +TEST_PATH = os.path.join(LOCAL_PATH, "..", "..", "test") +sys.path.append(TEST_PATH) + +from test_utils import download_file_and_uncompress + +if __name__ == "__main__": + download_file_and_uncompress( + url='https://paddleseg.bj.bcebos.com/models/unet_mechanical_industry_meter.tar', + savepath=LOCAL_PATH, + extrapath=LOCAL_PATH) + + print("Pretrained Model download success!") diff --git a/contrib/imgs/1560143028.5_IMG_3091.JPG b/contrib/MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.JPG similarity index 100% rename from contrib/imgs/1560143028.5_IMG_3091.JPG rename to contrib/MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.JPG diff --git a/contrib/imgs/1560143028.5_IMG_3091.png b/contrib/MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.png similarity index 100% rename from contrib/imgs/1560143028.5_IMG_3091.png rename to contrib/MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.png diff --git a/configs/unet_mechanical_meter.yaml b/contrib/MechanicalIndustryMeter/unet_mechanical_meter.yaml similarity index 77% rename from configs/unet_mechanical_meter.yaml rename to contrib/MechanicalIndustryMeter/unet_mechanical_meter.yaml index e1bc3a1183d2b435c84ad7b16002a3f604cf85b0..45ac8616f7993e15d3d262dc0e27f67624957e2a 100644 --- a/configs/unet_mechanical_meter.yaml +++ b/contrib/MechanicalIndustryMeter/unet_mechanical_meter.yaml @@ -21,14 +21,14 @@ DATALOADER: BUF_SIZE: 256 NUM_WORKERS: 4 DATASET: - DATA_DIR: "./dataset/mini_mechanical_industry_meter_data/" + DATA_DIR: "./contrib/MechanicalIndustryMeter/mini_mechanical_industry_meter_data/" IMAGE_TYPE: "rgb" # choice rgb or rgba NUM_CLASSES: 5 - TEST_FILE_LIST: "./dataset/mini_mechanical_industry_meter_data/val_mini.txt" + TEST_FILE_LIST: "./contrib/MechanicalIndustryMeter/mini_mechanical_industry_meter_data/val_mini.txt" TEST_TOTAL_IMAGES: 8 - TRAIN_FILE_LIST: "./dataset/mini_mechanical_industry_meter_data/train_mini.txt" + TRAIN_FILE_LIST: "./contrib/MechanicalIndustryMeter/mini_mechanical_industry_meter_data/train_mini.txt" TRAIN_TOTAL_IMAGES: 64 - VAL_FILE_LIST: "./dataset/mini_mechanical_industry_meter_data/val_mini.txt" + VAL_FILE_LIST: "./contrib/MechanicalIndustryMeter/mini_mechanical_industry_meter_data/val_mini.txt" VAL_TOTAL_IMAGES: 8 SEPARATOR: "|" IGNORE_INDEX: 255 diff --git a/contrib/README.md b/contrib/README.md index c39141255acc41ea4f039b65fae8ca3604c7b972..225ffb7747dba76b3dc3db2b27c764868a5e4fc5 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -1,72 +1,139 @@ # PaddleSeg 特色垂类分割模型 -提供基于PaddlePaddle最新的分割特色模型 +提供基于PaddlePaddle最新的分割特色模型: -## Augmented Context Embedding with Edge Perceiving (ACE2P) +- [人像分割](#人像分割) +- [人体解析](#人体解析) +- [车道线分割](#车道线分割) +- [工业用表分割](#工业用表分割) +- [在线体验](#在线体验) +## 人像分割 -### 1. 模型概述 - -CVPR 19 Look into Person (LIP) 单人人像分割比赛冠军模型,详见[ACE2P](./ACE2P) +**Note:** 本章节所有命令均在`contrib/HumanSeg`目录下执行。 -### 2. 模型下载 +``` +cd contrib/HumanSeg +``` -点击[链接](https://paddleseg.bj.bcebos.com/models/ACE2P.tgz),下载, 在contrib/ACE2P下解压, `tar -xzf ACE2P.tgz` +### 1. 模型结构 -### 3. 数据下载 +DeepLabv3+ backbone为Xception65 -前往LIP数据集官网: http://47.100.21.47:9999/overview.php 或点击 [Baidu_Drive](https://pan.baidu.com/s/1nvqmZBN#list/path=%2Fsharelink2787269280-523292635003760%2FLIP%2FLIP&parentPath=%2Fsharelink2787269280-523292635003760), +### 2. 下载模型和数据 + +执行以下命令下载并解压模型和数据集: -加载Testing_images.zip, 解压到contrib/ACE2P/data文件夹下 +``` +python download_HumanSeg.py +``` +或点击[链接](https://paddleseg.bj.bcebos.com/models/HumanSeg.tgz)进行手动下载,并解压到contrib/HumanSeg文件夹下 -### 4. 运行 -**NOTE:** 运行该模型需要2G左右显存 +### 3. 运行 -使用GPU预测 +使用GPU预测: ``` -python -u infer.py --example ACE2P --use_gpu +python -u infer.py --example HumanSeg --use_gpu ``` + 使用CPU预测: ``` -python -u infer.py --example ACE2P +python -u infer.py --example HumanSeg ``` -## 人像分割 (HumanSeg) +预测结果存放在contrib/HumanSeg/HumanSeg/result目录下。 -### 1. 模型结构 +### 4. 预测结果示例: -DeepLabv3+ backbone为Xception65 + 原图: + + ![](HumanSeg/imgs/Human.jpg) + + 预测结果: + + ![](HumanSeg/imgs/HumanSeg.jpg) -### 2. 下载模型和数据 - -点击[链接](https://paddleseg.bj.bcebos.com/models/HumanSeg.tgz),下载解压到contrib文件夹下 -### 3. 运行 +## 人体解析 + +![](ACE2P/imgs/result.jpg) + +人体解析(Human Parsing)是细粒度的语义分割任务,旨在识别像素级别的人类图像的组成部分(例如,身体部位和服装)。本章节使用冠军模型Augmented Context Embedding with Edge Perceiving (ACE2P)进行预测分割。 + + +**Note:** 本章节所有命令均在`contrib/ACE2P`目录下执行。 -使用GPU预测: ``` -python -u infer.py --example HumanSeg --use_gpu +cd contrib/ACE2P ``` +### 1. 模型概述 + +Augmented Context Embedding with Edge Perceiving (ACE2P)通过融合底层特征、全局上下文信息和边缘细节,端到端训练学习人体解析任务。以ACE2P单人人体解析网络为基础的解决方案在CVPR2019第三届Look into Person (LIP)挑战赛中赢得了全部三个人体解析任务的第一名。详情请参见[ACE2P](./ACE2P) + +### 2. 模型下载 + +执行以下命令下载并解压ACE2P预测模型: -使用CPU预测: ``` -python -u infer.py --example HumanSeg +python download_ACE2P.py ``` +或点击[链接](https://paddleseg.bj.bcebos.com/models/ACE2P.tgz)进行手动下载, 并在contrib/ACE2P下解压。 -### 4. 预测结果示例: +### 3. 数据下载 + +测试图片共10000张, +点击 [Baidu_Drive](https://pan.baidu.com/s/1nvqmZBN#list/path=%2Fsharelink2787269280-523292635003760%2FLIP%2FLIP&parentPath=%2Fsharelink2787269280-523292635003760) +下载Testing_images.zip,或前往LIP数据集官网进行下载。 +下载后解压到contrib/ACE2P/data文件夹下 - 原图:![](imgs/Human.jpg) + +### 4. 运行 + + +使用GPU预测 +``` +python -u infer.py --example ACE2P --use_gpu +``` + +使用CPU预测: +``` +python -u infer.py --example ACE2P +``` + +**NOTE:** 运行该模型需要2G左右显存。由于数据图片较多,预测过程将比较耗时。 + +#### 5. 预测结果示例: + + 原图: + + ![](ACE2P/imgs/117676_2149260.jpg) + + 预测结果: + + ![](ACE2P/imgs/117676_2149260.png) - 预测结果:![](imgs/HumanSeg.jpg) +### 备注 -## 车道线分割 (RoadLine) +1. 数据及模型路径等详细配置见ACE2P/HumanSeg/RoadLine下的config.py文件 +2. ACE2P模型需预留2G显存,若显存超可调小FLAGS_fraction_of_gpu_memory_to_use + + + + +## 车道线分割 + +**Note:** 本章节所有命令均在`contrib/RoadLine`目录下执行。 + +``` +cd contrib/RoadLine +``` ### 1. 模型结构 @@ -75,7 +142,15 @@ Deeplabv3+ backbone为MobileNetv2 ### 2. 下载模型和数据 -点击[链接](https://paddleseg.bj.bcebos.com/inference_model/RoadLine.tgz),下载解压在contrib文件夹下 + +执行以下命令下载并解压模型和数据集: + +``` +python download_RoadLine.py +``` + +或点击[链接](https://paddleseg.bj.bcebos.com/inference_model/RoadLine.tgz)进行手动下载,并解压到contrib/RoadLine文件夹下 + ### 3. 运行 @@ -92,43 +167,75 @@ python -u infer.py --example RoadLine --use_gpu python -u infer.py --example RoadLine ``` +预测结果存放在contrib/RoadLine/RoadLine/result目录下。 #### 4. 预测结果示例: - 原图:![](imgs/RoadLine.jpg) + 原图: + + ![](RoadLine/imgs/RoadLine.jpg) - 预测结果:![](imgs/RoadLine.png) + 预测结果: + + ![](RoadLine/imgs/RoadLine.png) + + ## 工业用表分割 + +**Note:** 本章节所有命令均在`PaddleSeg`目录下执行。 + ### 1. 模型结构 unet ### 2. 数据准备 -cd到PaddleSeg/dataset文件夹下,执行download_mini_mechanical_industry_meter.py +执行以下命令下载并解压数据集,数据集将存放在contrib/MechanicalIndustryMeter文件夹下: + +``` +python ./contrib/MechanicalIndustryMeter/download_mini_mechanical_industry_meter.py +``` -### 3. 训练与评估 +### 3. 下载预训练模型 ``` -CUDA_VISIBLE_DEVICES=0 python ./pdseg/train.py --log_steps 10 --cfg configs/unet_mechanical_meter.yaml --use_gpu --do_eval --use_mpio +python ./pretrained_model/download_model.py unet_bn_coco ``` -### 4. 可视化 -我们提供了一个训练好的模型,点击[链接](https://paddleseg.bj.bcebos.com/models/unet_mechanical_industry_meter.tar),下载后放在PaddleSeg/pretrained_model下 +### 4. 训练与评估 + ``` -CUDA_VISIBLE_DEVICES=0 python ./pdseg/vis.py --cfg configs/unet_mechanical_meter.yaml --use_gpu --vis_dir vis_meter \ -TEST.TEST_MODEL "./pretrained_model/unet_gongyeyongbiao/" +export CUDA_VISIBLE_DEVICES=0 +python ./pdseg/train.py --log_steps 10 --cfg contrib/MechanicalIndustryMeter/unet_mechanical_meter.yaml --use_gpu --do_eval --use_mpio ``` -可视化结果会保存在vis_meter文件夹下 -### 5. 可视化结果示例: +### 5. 可视化 +我们已提供了一个训练好的模型,执行以下命令进行下载,下载后将存放在./contrib/MechanicalIndustryMeter/文件夹下。 - 原图:![](imgs/1560143028.5_IMG_3091.JPG) +``` +python ./contrib/MechanicalIndustryMeter/download_unet_mechanical_industry_meter.py +``` + +使用该模型进行预测可视化: + +``` +python ./pdseg/vis.py --cfg contrib/MechanicalIndustryMeter/unet_mechanical_meter.yaml --use_gpu --vis_dir vis_meter \ +TEST.TEST_MODEL "./contrib/MechanicalIndustryMeter/unet_mechanical_industry_meter/" +``` +可视化结果会保存在./vis_meter文件夹下。 + +### 6. 可视化结果示例: + + 原图: + + ![](MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.JPG) - 预测结果:![](imgs/1560143028.5_IMG_3091.png) + 预测结果: + + ![](MechanicalIndustryMeter/imgs/1560143028.5_IMG_3091.png) ## 在线体验 @@ -140,7 +247,4 @@ PaddleSeg在AI Studio平台上提供了在线体验的教程,欢迎体验: |人像分割|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/188833)| |特色垂类模型|[点击体验](https://aistudio.baidu.com/aistudio/projectdetail/115541)| -## 备注 -1. 数据及模型路径等详细配置见ACE2P/HumanSeg/RoadLine下的config.py文件 -2. ACE2P模型需预留2G显存,若显存超可调小FLAGS_fraction_of_gpu_memory_to_use diff --git a/contrib/RoadLine/download_RoadLine.py b/contrib/RoadLine/download_RoadLine.py new file mode 100644 index 0000000000000000000000000000000000000000..86b631784edadcff6d575c59e67ee23a1775216d --- /dev/null +++ b/contrib/RoadLine/download_RoadLine.py @@ -0,0 +1,31 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License" +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 sys +import os + +LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) +TEST_PATH = os.path.join(LOCAL_PATH, "..", "..", "test") +sys.path.append(TEST_PATH) + +from test_utils import download_file_and_uncompress + +if __name__ == "__main__": + download_file_and_uncompress( + url='https://paddleseg.bj.bcebos.com/inference_model/RoadLine.tgz', + savepath=LOCAL_PATH, + extrapath=LOCAL_PATH, + extraname='RoadLine') + + print("Pretrained Model download success!") diff --git a/contrib/imgs/RoadLine.jpg b/contrib/RoadLine/imgs/RoadLine.jpg similarity index 100% rename from contrib/imgs/RoadLine.jpg rename to contrib/RoadLine/imgs/RoadLine.jpg diff --git a/contrib/imgs/RoadLine.png b/contrib/RoadLine/imgs/RoadLine.png similarity index 100% rename from contrib/imgs/RoadLine.png rename to contrib/RoadLine/imgs/RoadLine.png diff --git a/contrib/RoadLine/infer.py b/contrib/RoadLine/infer.py new file mode 100644 index 0000000000000000000000000000000000000000..971476933c431977ce80c73e1d939fe079e1af19 --- /dev/null +++ b/contrib/RoadLine/infer.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +import os +import cv2 +import numpy as np +from utils.util import get_arguments +from utils.palette import get_palette +from PIL import Image as PILImage +import importlib + +args = get_arguments() +config = importlib.import_module('config') +cfg = getattr(config, 'cfg') + +# paddle垃圾回收策略FLAG,ACE2P模型较大,当显存不够时建议开启 +os.environ['FLAGS_eager_delete_tensor_gb']='0.0' + +import paddle.fluid as fluid + +# 预测数据集类 +class TestDataSet(): + def __init__(self): + self.data_dir = cfg.data_dir + self.data_list_file = cfg.data_list_file + self.data_list = self.get_data_list() + self.data_num = len(self.data_list) + + def get_data_list(self): + # 获取预测图像路径列表 + data_list = [] + data_file_handler = open(self.data_list_file, 'r') + for line in data_file_handler: + img_name = line.strip() + name_prefix = img_name.split('.')[0] + if len(img_name.split('.')) == 1: + img_name = img_name + '.jpg' + img_path = os.path.join(self.data_dir, img_name) + data_list.append(img_path) + return data_list + + def preprocess(self, img): + # 图像预处理 + if cfg.example == 'ACE2P': + reader = importlib.import_module(args.example+'.reader') + ACE2P_preprocess = getattr(reader, 'preprocess') + img = ACE2P_preprocess(img) + else: + img = cv2.resize(img, cfg.input_size).astype(np.float32) + img -= np.array(cfg.MEAN) + img /= np.array(cfg.STD) + img = img.transpose((2, 0, 1)) + img = np.expand_dims(img, axis=0) + return img + + def get_data(self, index): + # 获取图像信息 + img_path = self.data_list[index] + img = cv2.imread(img_path, cv2.IMREAD_COLOR) + if img is None: + return img, img,img_path, None + + img_name = img_path.split(os.sep)[-1] + name_prefix = img_name.replace('.'+img_name.split('.')[-1],'') + img_shape = img.shape[:2] + img_process = self.preprocess(img) + + return img, img_process, name_prefix, img_shape + + +def infer(): + if not os.path.exists(cfg.vis_dir): + os.makedirs(cfg.vis_dir) + palette = get_palette(cfg.class_num) + # 人像分割结果显示阈值 + thresh = 120 + + place = fluid.CUDAPlace(0) if cfg.use_gpu else fluid.CPUPlace() + exe = fluid.Executor(place) + + # 加载预测模型 + test_prog, feed_name, fetch_list = fluid.io.load_inference_model( + dirname=cfg.model_path, executor=exe, params_filename='__params__') + + #加载预测数据集 + test_dataset = TestDataSet() + data_num = test_dataset.data_num + + for idx in range(data_num): + # 数据获取 + ori_img, image, im_name, im_shape = test_dataset.get_data(idx) + if image is None: + print(im_name, 'is None') + continue + + # 预测 + if cfg.example == 'ACE2P': + # ACE2P模型使用多尺度预测 + reader = importlib.import_module(args.example+'.reader') + multi_scale_test = getattr(reader, 'multi_scale_test') + parsing, logits = multi_scale_test(exe, test_prog, feed_name, fetch_list, image, im_shape) + else: + # HumanSeg,RoadLine模型单尺度预测 + result = exe.run(program=test_prog, feed={feed_name[0]: image}, fetch_list=fetch_list) + parsing = np.argmax(result[0][0], axis=0) + parsing = cv2.resize(parsing.astype(np.uint8), im_shape[::-1]) + + # 预测结果保存 + result_path = os.path.join(cfg.vis_dir, im_name + '.png') + if cfg.example == 'HumanSeg': + logits = result[0][0][1]*255 + logits = cv2.resize(logits, im_shape[::-1]) + ret, logits = cv2.threshold(logits, thresh, 0, cv2.THRESH_TOZERO) + logits = 255 *(logits - thresh)/(255 - thresh) + # 将分割结果添加到alpha通道 + rgba = np.concatenate((ori_img, np.expand_dims(logits, axis=2)), axis=2) + cv2.imwrite(result_path, rgba) + else: + output_im = PILImage.fromarray(np.asarray(parsing, dtype=np.uint8)) + output_im.putpalette(palette) + output_im.save(result_path) + + if (idx + 1) % 100 == 0: + print('%d processd' % (idx + 1)) + + print('%d processd done' % (idx + 1)) + + return 0 + + +if __name__ == "__main__": + infer() diff --git a/contrib/RoadLine/utils/__init__.py b/contrib/RoadLine/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/contrib/RoadLine/utils/palette.py b/contrib/RoadLine/utils/palette.py new file mode 100644 index 0000000000000000000000000000000000000000..2186203cbc2789f6eff70dfd92f724b4fe16cdb7 --- /dev/null +++ b/contrib/RoadLine/utils/palette.py @@ -0,0 +1,38 @@ +##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +## Created by: RainbowSecret +## Microsoft Research +## yuyua@microsoft.com +## Copyright (c) 2018 +## +## This source code is licensed under the MIT-style license found in the +## LICENSE file in the root directory of this source tree +##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import numpy as np +import cv2 + + +def get_palette(num_cls): + """ Returns the color map for visualizing the segmentation mask. + Args: + num_cls: Number of classes + Returns: + The color map + """ + n = num_cls + palette = [0] * (n * 3) + for j in range(0, n): + lab = j + palette[j * 3 + 0] = 0 + palette[j * 3 + 1] = 0 + palette[j * 3 + 2] = 0 + i = 0 + while lab: + palette[j * 3 + 0] |= (((lab >> 0) & 1) << (7 - i)) + palette[j * 3 + 1] |= (((lab >> 1) & 1) << (7 - i)) + palette[j * 3 + 2] |= (((lab >> 2) & 1) << (7 - i)) + i += 1 + lab >>= 3 + return palette diff --git a/contrib/RoadLine/utils/util.py b/contrib/RoadLine/utils/util.py new file mode 100644 index 0000000000000000000000000000000000000000..7394870e7c94c1fb16169e314696b931eecdc3b2 --- /dev/null +++ b/contrib/RoadLine/utils/util.py @@ -0,0 +1,47 @@ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +import argparse +import os + +def get_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("--use_gpu", + action="store_true", + help="Use gpu or cpu to test.") + parser.add_argument('--example', + type=str, + help='RoadLine, HumanSeg or ACE2P') + + return parser.parse_args() + + +class AttrDict(dict): + def __init__(self, *args, **kwargs): + super(AttrDict, self).__init__(*args, **kwargs) + + def __getattr__(self, name): + if name in self.__dict__: + return self.__dict__[name] + elif name in self: + return self[name] + else: + raise AttributeError(name) + + def __setattr__(self, name, value): + if name in self.__dict__: + self.__dict__[name] = value + else: + self[name] = value + +def merge_cfg_from_args(args, cfg): + """Merge config keys, values in args into the global config.""" + for k, v in vars(args).items(): + d = cfg + try: + value = eval(v) + except: + value = v + if value is not None: + cfg[k] = value +