摘要:
赛题:大数据与计算智能大赛CCF-BDCI-2020-遥感影像地块分割
主办方:中国计算机学会 & 百度
主页:https://www.datafountain.cn/competitions/475
AI问题:语义分割预测
数据集:多个地区已脱敏的遥感影像数据 (包含140,000张JPG图片和PNG格式的标注图片)
数据集价值:可以基于这些数据构建自己的地块分割模型
解决方案:PaddlePaddle开发框架、图像语义分割模型。
一、赛题描述
遥感影像地块分割, 旨在对遥感影像进行像素级内容解析,对遥感影像中感兴趣的类别进行提取和分类,在城乡规划、防汛救灾等领域具有很高的实用价值,在工业界受到了广泛关注。现有的遥感影像地块分割数据处理方法局限于特定的场景和特定的数据来源,且精度无法满足需求。因此在实际应用中,仍然大量依赖于人工处理,需要消耗大量的人力、物力、财力。本次大赛旨在利用人工智能技术,对多来源、多场景的异构遥感影像数据进行充分挖掘,打造高效、实用的算法,提高遥感影像的分析提取能力。
本次评测旨在衡量遥感影像地块分割模型在多个类别上的效果,具体包括建筑、耕地、林地、水体、道路、草地和其他等7个类别。
二、数据集内容
1、训练集图像和标注
训练集包含 140,000 张分辨率为2m/pixel,尺寸为256×256的JPG图片,文件名称形如T000123.jpg。这里的2m/像素意思是:图像中每个像素(pixel)对应的实际地面尺寸是2米 × 2米的正方形区域。
训练集中的图像和标注文件的目录结构如下:
data/train/
├── img_train/ # 原始图像
│ ├── T000123.jpg
│ └── T000124.jpg
└── lab_train/ # 标注掩码
├── T000123.png
└── T000124.png
标注文件和原始图像的文件数同等数量,标注数据的格式为:尺寸为256×256的PNG格式的单通道“伪彩色标注”图片,图片的文件名称与原始的图片名称对应, 标注文件名称形如T000123.png,像素值与类别对应关系如下表所示:
像素值 | 类别 |
---|---|
0 | 建筑 |
1 | 耕地 |
2 | 林地 |
3 | 水体 |
4 | 道路 |
5 | 草地 |
6 | 其他 |
255 | 未标注区域 |
其中,255代表了未标注区域,表示对应区域的所属类别并不确定,在评测中也不会考虑这部分区域。
训练时需要提供一个文本文件(如train_list.txt
)指定图像和标注的对应关系:
train/img_train/T073713.jpg train/lab_train/T073713.png
train/img_train/T137273.jpg train/lab_train/T137273.png
train/img_train/T007892.jpg train/lab_train/T007892.png
train/img_train/T097198.jpg train/lab_train/T097198.png
...
2、测试集
测试集文件目录为 data/img_testA。包含10,000张分辨率为2m/pixel,尺寸为256×256的JPG图片,文件名称形如A000123.jpg 。
数据集使用许可协议
BY-NC-SA 4.0
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans
三、解决方案样例
1、解决方案
源码:inference.py。
这个Python脚本是一个基于PaddlePaddle框架的图像分割推理工具,主要用于对输入图像进行语义分割预测并可视化结果。这个工具适用于需要批量处理图像语义分割任务的场景,特别是:
- 工业质检
- 遥感图像分析
- 医学图像分割
- 自动驾驶场景理解
工作流程如下:
a、模型输入与预处理
- 输入适配:通过
ImageReader
类处理不同尺寸的输入图像,将其统一调整为配置文件中指定的eval_crop_size
(如512×512)。 - 归一化处理:根据配置的均值(
mean
)和标准差(std
)对图像进行标准化(若未启用预编译优化use_pr=False
) - 通道转换:将图像从HWC格式转为CHW格式(模型输入要求)。
格式定义
格式 | 含义 | 典型应用场景 |
---|---|---|
HWC | Height × Width × Channels | OpenCV默认格式(如 (512, 512, 3) ) |
CHW | Channels × Height × Width | PyTorch/PaddlePaddle等框架的输入格式(如 (3, 512, 512) ) |
为什么需要转换?
- 框架要求:大多数深度学习框架(如PyTorch、PaddlePaddle)要求输入数据的通道维度在前(CHW)。
- 计算优化:CHW格式更符合GPU内存访问模式,能加速卷积运算。
b、模型推理
- 加载模型:通过
Predictor
类加载预训练模型(配置项为__model__
和__params__
),支持GPU/CPU和TensorRT加速。 - 推理执行:输入数据通过
predictor.run()
执行前向计算,输出每个像素的类别概率分布(形状为[batch, class_num, H, W]
)。
c、后处理与可视化
类别分配:对输出概率图取argmax
,得到每个像素的预测类别(0到class_num-1
):
mask = np.argmax(mask, axis=0) # 从概率图转为类别标签
颜色映射:通过generate_colormap
为每个类别生成唯一颜色,生成可视化结果:
color_map = [
[0, 0, 0], # 类别0(背景)
[255, 0, 0], # 类别1
[0, 255, 0] # 类别2
]
结果保存:将预测的掩码(_mask.png
)和彩色可视化结果(_result.png
)保存到文件。
2、语义分割模型
采用UNet和DeepLabV3+等语义分割模型。
3、安装开发包
参考文章《安装Paddle系列深度学习框架》和《安装和验证OpenCV-Python版本》。
库名称 | 版本号 |
---|---|
python | 3.10 |
paddlepaddle-gpu | PaddlePaddle3.0-bata |
opencv-python | 4.5.5 |
pandas | 1.3.5 |
numpy | 1.26.4 |
absl-py | 2.1.0 |
说明:这里的paddlepaddle-gpu 3.0.0b1 的安装要求 numpy<2.0,>=1.13。
关键安装方法:
conda install paddlepaddle-gpu==3.0.0b1 paddlepaddle-cuda=11.8 -c paddle -c nvidia
pip install opencv-python==4.5.5.64
4、运行方法
本样例运行命令示例:
python inference.py –conf=./docs/deploy.yaml –input_dir=./images
- conf 参数表示模型文件/配置文件所在目录;
- input_dir 参数表示输入图片文件所在目录。
四、推理工作流程
源码:inference.py
1. 初始化和参数解析
使用absl.flags
定义和解析命令行参数:
--conf
: 配置文件路径--input_dir
: 输入图像目录。需要推理的原有图片。--trt_mode
: 是否使用TensorRT优化模型--ext
: 支持的图像文件扩展名
FLAGS = flags.FLAGS
flags.DEFINE_string("conf", default="", help="Configuration File Path")
flags.DEFINE_string("input_dir", default="", help="Directory of Input Images")
flags.DEFINE_string("trt_mode", default="", help="Use optimized model")
flags.DEFINE_string("ext", default=".jpeg|.jpg", help="Input Image File Extensions")
例如运行
python inference.py --conf=./docs/deploy.yaml --input_dir=./images
2. 可视化分割结果等辅助函数
generate_colormap()
: 为不同类别生成颜色映射,用于可视化分割结果get_images_from_dir()
: 扫描目录获取指定扩展名的所有图像文件
# Generate ColorMap for visualization
def generate_colormap(num_classes):
color_map = num_classes * [0, 0, 0]
for i in range(0, num_classes):
j = 0
lab = i
while lab:
color_map[i * 3] |= (((lab >> 0) & 1) << (7 - j))
color_map[i * 3 + 1] |= (((lab >> 1) & 1) << (7 - j))
color_map[i * 3 + 2] |= (((lab >> 2) & 1) << (7 - j))
j += 1
lab >>= 3
color_map = [color_map[i:i + 3] for i in range(0, len(color_map), 3)]
return color_map
# Paddle-TRT Precision Map
trt_precision_map = {
"int8": fluid.core.AnalysisConfig.Precision.Int8,
"fp32": fluid.core.AnalysisConfig.Precision.Float32,
"fp16": fluid.core.AnalysisConfig.Precision.Half
}
# scan a directory and get all images with support extensions
def get_images_from_dir(img_dir, support_ext=".jpg|.jpeg"):
if (not os.path.exists(img_dir) or not os.path.isdir(img_dir)):
raise Exception("Image Directory [%s] invalid" % img_dir)
imgs = []
for item in os.listdir(img_dir):
ext = os.path.splitext(item)[1][1:].strip().lower()
if (len(ext) > 0 and ext in support_ext):
item_path = os.path.join(img_dir, item)
imgs.append(item_path)
return imgs
3. 配置解析
配置参数:
a. 硬件与计算配置
参数 | 值 | 说明 |
---|---|---|
USE_GPU | 1 | 是否使用GPU进行推理: – 1 :启用GPU加速 – 0 :使用CPU |
PREDICTOR_MODE | "ANALYSIS" | 推理模式: – "NATIVE" :基础推理模式 – "ANALYSIS" :启用性能优化(如TensorRT) |
b. 模型文件配置
参数 | 值 | 说明 |
---|---|---|
MODEL_PATH | "docs" | 模型文件存储的目录路径 |
MODEL_FILENAME | "__model__" | 模型结构文件名称(如__model__ 表示PaddlePaddle的模型文件) |
PARAMS_FILENAME | "__params__" | 模型参数文件名称 |
c. 输入数据预处理
参数 | 值 | 说明 |
---|---|---|
EVAL_CROP_SIZE | (256, 256) | 输入图像会被缩放到此尺寸(宽×高) |
MEAN | [0.5, 0.5, 0.5] | 图像归一化的均值(RGB三通道) |
STD | [0.5, 0.5, 0.5] | 图像归一化的标准差(RGB三通道) |
IMAGE_TYPE | "rgb" | 输入图像类型: – "rgb" :三通道彩色图 – "rgba" :四通道(含透明度) |
CHANNELS | 3 | 输入图像的通道数(与IMAGE_TYPE 对应) |
USE_PR | 0 | 是否使用内置预处理/后处理: – 1 :模型已集成预处理(如某些优化模型) – 0 :需手动预处理输入数据 |
d. 模型任务相关
参数 | 值 | 说明 |
---|---|---|
NUM_CLASSES | 7 | 模型支持的类别数量(如分割任务中的7类目标) |
PRE_PROCESSOR | "SegPreProcessor" | 预处理器的类型(此处为图像语义分割任务) |
e. 性能优化
参数 | 值 | 说明 |
---|---|---|
BATCH_SIZE | 1 | 推理时的批次大小: – 增大可提升GPU利用率,但需更多显存 |
配置值:
配置文件:./docs/deploy.yaml
DEPLOY:
USE_GPU : 1
USE_PR : 0
# MODEL_PATH : "freeze_model"
MODEL_PATH : "docs"
MODEL_FILENAME : "__model__"
PARAMS_FILENAME : "__params__"
EVAL_CROP_SIZE : (256, 256)
MEAN : [0.5, 0.5, 0.5]
STD : [0.5, 0.5, 0.5]
IMAGE_TYPE : "rgb"
NUM_CLASSES : 7
CHANNELS : 3
PRE_PROCESSOR : "SegPreProcessor"
PREDICTOR_MODE : "ANALYSIS"
BATCH_SIZE : 1
代码:
配置解析类 DeployConfig
。从YAML配置文件中读取部署参数。
# Deploy Configuration File Parser
class DeployConfig:
def __init__(self, conf_file):
if not os.path.exists(conf_file):
raise Exception('Config file path [%s] invalid!' % conf_file)
with open(conf_file) as fp:
configs = yaml.load(fp, Loader=yaml.FullLoader)
deploy_conf = configs["DEPLOY"]
# 1. get eval_crop_size
self.eval_crop_size = ast.literal_eval(
deploy_conf["EVAL_CROP_SIZE"])
# 2. get mean
self.mean = deploy_conf["MEAN"]
# 3. get std
self.std = deploy_conf["STD"]
# 4. get class_num
self.class_num = deploy_conf["NUM_CLASSES"]
# 5. get paddle model and params file path
self.model_file = os.path.join(deploy_conf["MODEL_PATH"],
deploy_conf["MODEL_FILENAME"])
self.param_file = os.path.join(deploy_conf["MODEL_PATH"],
deploy_conf["PARAMS_FILENAME"])
# 6. use_gpu
self.use_gpu = deploy_conf["USE_GPU"]
# 7. predictor_mode
self.predictor_mode = deploy_conf["PREDICTOR_MODE"]
# 8. batch_size
self.batch_size = deploy_conf["BATCH_SIZE"]
# 9. channels
self.channels = deploy_conf["CHANNELS"]
# 10. use_pr
self.use_pr = deploy_conf["USE_PR"]
4. 图像读取和处理
图像读取和处理类: ImageReader
。使用线程池并行处理图像。其主要功能:
- 读取图像
- 调整大小到指定尺寸
- 进行预处理(归一化、通道转换等)
- 返回处理后的图像数据和原始图像信息
class ImageReader:
def __init__(self, configs):
self.config = configs
self.threads_pool = ThreadPoolExecutor(configs.batch_size)
# image processing thread worker
def process_reader(self, imgs, idx, use_pr=False):
image_path = imgs[idx]
cv2_imread_flag = cv2.IMREAD_COLOR
if self.config.channels == 4:
cv2_imread_flag = cv2.IMREAD_UNCHANGED
im = cv2.imread(image_path, cv2_imread_flag)
return im
def process_worker(self, imgs, idx, use_pr=False):
image_path = imgs[idx]
cv2_imread_flag = cv2.IMREAD_COLOR
if self.config.channels == 4:
cv2_imread_flag = cv2.IMREAD_UNCHANGED
im = cv2.imread(image_path, cv2_imread_flag)
channels = im.shape[2]
if channels != 3 and channels != 4:
print("Only support rgb(gray) or rgba image.")
return -1
ori_h = im.shape[0]
ori_w = im.shape[1]
# resize to eval_crop_size
eval_crop_size = self.config.eval_crop_size
if (ori_h != eval_crop_size[1] or ori_w != eval_crop_size[0]):
im = cv2.resize(
im, eval_crop_size, fx=0, fy=0, interpolation=cv2.INTER_LINEAR)
# if use models with no pre-processing/post-processing op optimizations
if not use_pr:
im_mean = np.array(self.config.mean).reshape((self.config.channels,
1, 1))
im_std = np.array(self.config.std).reshape((self.config.channels, 1,
1))
# HWC -> CHW, don't use transpose((2, 0, 1))
im = im.swapaxes(1, 2)
im = im.swapaxes(0, 1)
im = im[:, :, :].astype('float32') / 255.0
im -= im_mean
im /= im_std
im = im[np.newaxis, :, :, :]
info = [image_path, im, (ori_w, ori_h)]
return info
# process multiple images with multithreading
def process(self, imgs, use_pr=False):
imgs_data = []
with ThreadPoolExecutor(max_workers=self.config.batch_size) as exe_pool:
tasks = [
exe_pool.submit(self.process_worker, imgs, idx, use_pr)
for idx in range(len(imgs))
]
for task in as_completed(tasks):
imgs_data.append(task.result())
return imgs_data
5. 推理预测
预测器类 Predictor
为核心推理类,主要功能:
初始化
- 创建PaddlePaddle预测器
- 根据配置选择不同的预测模式(NATIVE或ANALYSIS)
- 如果启用TensorRT,配置相应的精度模式(int8/fp16/fp32)
class Predictor:
def __init__(self, conf_file):
self.config = DeployConfig(conf_file)
self.image_reader = ImageReader(self.config)
# 初始化 Config
if self.config.predictor_mode == "NATIVE":
predictor_config = paddle.inference.Config()
predictor_config.set_prog_file(self.config.model_file)
predictor_config.set_params_file(self.config.param_file)
predictor_config.enable_use_gpu(100, 0) if self.config.use_gpu else predictor_config.disable_gpu()
elif self.config.predictor_mode == "ANALYSIS":
predictor_config = Config(self.config.model_file, self.config.param_file)
if self.config.use_gpu:
predictor_config.enable_use_gpu(100, 0)
if FLAGS.trt_mode:
predictor_config.enable_tensorrt_engine(
precision_mode=trt_precision_map[FLAGS.trt_mode]
)
self.predictor = create_predictor(predictor_config)
self.input_handle = self.predictor.get_input_handle(
self.predictor.get_input_names()[0]
)
self.output_handle = None
推理流程
create_tensor()
: 将输入数据转换为PaddleTensor格式predict()
: 执行批量推理- 分批读取和处理图像
- 执行模型推理
- 处理输出结果
output_result()
: 处理推理结果- 生成分割掩码
- 应用颜色映射可视化
- 保存结果图像(原始图像名mask.png和原始图像名result.png)
def create_tensor(self, inputs, batch_size, use_pr=False):
# im_tensor = fluid.core.PaddleTensor()
# 直接通过 numpy 数组创建 Tensor v2.x
im_tensor = Tensor(
data=inputs.ravel().astype("float32"), # 输入数据(需展平)
dtype=paddle.float32, # 数据类型
name="input" # 可选:张量名称
)
im_tensor.name = "image"
if not use_pr:
im_tensor.shape = [
batch_size, self.config.channels, self.config.eval_crop_size[1],
self.config.eval_crop_size[0]
]
else:
im_tensor.shape = [
batch_size, self.config.eval_crop_size[1],
self.config.eval_crop_size[0], self.config.channels
]
# im_tensor.dtype = fluid.core.PaddleDType.FLOAT32 # v1.0
# im_tensor.data = fluid.core.PaddleBuf(inputs.ravel().astype("float32")) # v1.0
return [im_tensor]
6. 主执行流程
函数:run()
- 扫描输入目录获取所有图像文件
- 创建Predictor实例
- 执行批量预测
def run(deploy_conf, imgs_dir, support_extensions=".jpg|.jpeg"):
# 1. scan and get all images with valid extensions in directory imgs_dir
imgs = get_images_from_dir(imgs_dir, support_extensions)
if len(imgs) == 0:
print("No Image (with extensions : %s) found in [%s]" %
(support_extensions, imgs_dir))
return -1
# 2. create a predictor
seg_predictor = Predictor(deploy_conf)
# 3. do a inference on images
seg_predictor.predict(imgs)
return 0
7. 主函数
主函数 __main__
- 解析命令行参数
- 验证参数有效性
- 调用
run()
函数执行推理
if __name__ == "__main__":
# 0. parse the arguments
FLAGS(sys.argv)
if (FLAGS.conf == "" or FLAGS.input_dir == ""):
print("Usage: python infer.py --conf=/config/path/to/your/model " +
"--input_dir=/directory/of/your/input/images [--use_pr=True]")
exit(-1)
# set empty to turn off as default
trt_mode = FLAGS.trt_mode
if (trt_mode != "" and trt_mode not in trt_precision_map):
print(
"Invalid trt_mode [%s], only support[int8, fp16, fp32]" % trt_mode)
exit(-1)
# run inference
run(FLAGS.conf, FLAGS.input_dir, FLAGS.ext)
运行展示
python inference.py --conf=./docs/deploy.yaml --input_dir=./images
输出:
e[1me[35m--- Running analysis [ir_graph_build_pass]e[0m
I0811 19:21:17.294570 9844 executor.cc:184] Old Executor is Running.
e[1me[35m--- Running analysis [ir_analysis_pass]e[0m
e[32m--- Running IR pass [map_op_to_another_pass]e[0m
I0811 19:21:17.357097 9844 fuse_pass_base.cc:59] --- detected 19 subgraphs
e[32m--- Running IR pass [is_test_pass]e[0m
e[32m--- Running IR pass [simplify_with_basic_ops_pass]e[0m
e[32m--- Running IR pass [delete_quant_dequant_linear_op_pass]e[0m
e[32m--- Running IR pass [delete_weight_dequant_linear_op_pass]e[0m
e[32m--- Running IR pass [constant_folding_pass]e[0m
e[32m--- Running IR pass [silu_fuse_pass]e[0m
e[32m--- Running IR pass [conv_bn_fuse_pass]e[0m
I0811 19:21:17.404409 9844 fuse_pass_base.cc:59] --- detected 18 subgraphs
e[32m--- Running IR pass [conv_eltwiseadd_bn_fuse_pass]e[0m
e[32m--- Running IR pass [embedding_eltwise_layernorm_fuse_pass]e[0m
e[32m--- Running IR pass [multihead_matmul_fuse_pass_v2]e[0m
e[32m--- Running IR pass [vit_attention_fuse_pass]e[0m
e[32m--- Running IR pass [fused_multi_transformer_encoder_pass]e[0m
e[32m--- Running IR pass [fused_multi_transformer_decoder_pass]e[0m
e[32m--- Running IR pass [fused_multi_transformer_encoder_fuse_qkv_pass]e[0m
e[32m--- Running IR pass [fused_multi_transformer_decoder_fuse_qkv_pass]e[0m
e[32m--- Running IR pass [multi_devices_fused_multi_transformer_encoder_pass]e[0m
e[32m--- Running IR pass [multi_devices_fused_multi_transformer_encoder_fuse_qkv_pass]e[0m
e[32m--- Running IR pass [multi_devices_fused_multi_transformer_decoder_fuse_qkv_pass]e[0m
e[32m--- Running IR pass [fuse_multi_transformer_layer_pass]e[0m
e[32m--- Running IR pass [gpu_cpu_squeeze2_matmul_fuse_pass]e[0m
e[32m--- Running IR pass [gpu_cpu_reshape2_matmul_fuse_pass]e[0m
e[32m--- Running IR pass [gpu_cpu_flatten2_matmul_fuse_pass]e[0m
e[32m--- Running IR pass [gpu_cpu_map_matmul_v2_to_mul_pass]e[0m
e[32m--- Running IR pass [gpu_cpu_map_matmul_v2_to_matmul_pass]e[0m
e[32m--- Running IR pass [matmul_scale_fuse_pass]e[0m
e[32m--- Running IR pass [multihead_matmul_fuse_pass_v3]e[0m
e[32m--- Running IR pass [gpu_cpu_map_matmul_to_mul_pass]e[0m
e[32m--- Running IR pass [fc_fuse_pass]e[0m
e[32m--- Running IR pass [fc_elementwise_layernorm_fuse_pass]e[0m
e[32m--- Running IR pass [conv_elementwise_add_act_fuse_pass]e[0m
I0811 19:21:17.907351 9844 fuse_pass_base.cc:59] --- detected 18 subgraphs
e[32m--- Running IR pass [conv_elementwise_add2_act_fuse_pass]e[0m
e[32m--- Running IR pass [conv_elementwise_add_fuse_pass]e[0m
e[32m--- Running IR pass [transpose_flatten_concat_fuse_pass]e[0m
e[32m--- Running IR pass [transfer_layout_pass]e[0m
e[32m--- Running IR pass [transfer_layout_elim_pass]e[0m
e[32m--- Running IR pass [auto_mixed_precision_pass]e[0m
e[32m--- Running IR pass [identity_op_clean_pass]e[0m
I0811 19:21:17.938565 9844 fuse_pass_base.cc:59] --- detected 1 subgraphs
e[32m--- Running IR pass [inplace_op_var_pass]e[0m
e[1me[35m--- Running analysis [ir_params_sync_among_devices_pass]e[0m
I0811 19:21:17.938565 9844 ir_params_sync_among_devices_pass.cc:51] Sync params from CPU to GPU
e[1me[35m--- Running analysis [adjust_cudnn_workspace_size_pass]e[0m
e[1me[35m--- Running analysis [inference_op_replace_pass]e[0m
e[1me[35m--- Running analysis [save_optimized_model_pass]e[0m
e[1me[35m--- Running analysis [ir_graph_to_program_pass]e[0m
I0811 19:21:18.001578 9844 analysis_predictor.cc:2080] ======= ir optimization completed =======
I0811 19:21:18.001578 9844 naive_executor.cc:200] --- skip [feed], feed -> image
I0811 19:21:18.001578 9844 naive_executor.cc:200] --- skip [save_infer_model/scale_0.tmp_0], fetch -> fetch
W0811 19:21:18.018024 9844 gpu_resources.cc:119] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 12.2, Runtime API Version: 11.8
W0811 19:21:18.033665 9844 gpu_resources.cc:164] device: 0, cuDNN Version: 8.9.
I0811 19:21:18.033665 9844 program_interpreter.cc:243] New Executor is Running.
save result of [./images\T004706.jpg] done.
save result of [./images\T005998.jpg] done.
save result of [./images\T006088.jpg] done.
save result of [./images\T006105.jpg] done.
save result of [./images\T006857.jpg] done.
save result of [./images\T006880.jpg] done.
save result of [./images\T006887.jpg] done.
images_num=[7], preprocessing_time=[0.065], infer_time=[3.061], postprocessing_time=[0.293], total_runtime=[3.420]
本样例根据输入的遥感影像图片文件生成可视化的地块分割图片文件列表,示例如下:
Input_Picture | Output_Picture |
---|---|
T004706.jpg | T004706_jpg_result.png |
T005998.jpg | T005998_jpg_result.png |
T006088.jpg | T006088_jpg_result.png |
T006105.jpg | T006105_jpg_result.png |
T006857.jpg | T006857_jpg_result.png |
T006880.jpg | T006880_jpg_result.png |
T006887.jpg | T006887_jpg_result.png |
源码开源协议
GPL-v3
https://zhuanlan.zhihu.com/p/608456168
五、获取案例套装
文件包大小:50 MB
获取:社会基础服务计算机视觉案例套装 下载文件包