From 267f6508f04e4f737620d1e041a0c77f60bb7052 Mon Sep 17 00:00:00 2001 From: dongshuilong Date: Tue, 25 Jan 2022 19:26:45 +0800 Subject: [PATCH] fix ppshitu_lite bugs and fix README.md --- deploy/lite_shitu/README.md | 153 +++++++++++----------- deploy/lite_shitu/generate_json_config.py | 115 ++++++++++------ deploy/lite_shitu/include/config_parser.h | 2 +- deploy/lite_shitu/include/recognition.h | 5 +- deploy/lite_shitu/include/utils.h | 20 +-- deploy/lite_shitu/src/main.cc | 71 +++------- deploy/lite_shitu/src/object_detector.cc | 5 +- deploy/lite_shitu/src/preprocess_op.cc | 10 +- deploy/lite_shitu/src/recognition.cc | 2 +- deploy/lite_shitu/src/utils.cc | 32 +++-- docs/images/ppshitu_lite_demo.png | Bin 0 -> 55001 bytes 11 files changed, 211 insertions(+), 204 deletions(-) create mode 100644 docs/images/ppshitu_lite_demo.png diff --git a/deploy/lite_shitu/README.md b/deploy/lite_shitu/README.md index e775b134a..5d6dde45d 100644 --- a/deploy/lite_shitu/README.md +++ b/deploy/lite_shitu/README.md @@ -1,4 +1,4 @@ -# Paddle-Lite端侧部署 +# PP-ShiTu在Paddle-Lite端侧部署 本教程将介绍基于[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 在移动端部署PaddleDetection模型的详细步骤。 @@ -125,30 +125,71 @@ Paddle-Lite 提供了多种策略来自动优化原始的模型,其中包括 #### 2.1.3 转换示例 -下面以PaddleDetection中的 `PicoDet` 模型为例,介绍使用`paddle_lite_opt`完成预训练模型到inference模型,再到Paddle-Lite优化模型的转换。 +下面介绍使用`paddle_lite_opt`完成主体检测模型和识别模型的预训练模型,转成inference模型,最终转换成Paddle-Lite的优化模型的过程。 + +##### 2.1.3.1 转换主体检测模型 ```shell +# 当前目录为 $PaddleClas/deploy/lite_shitu +# $code_path需替换成相应的运行目录,可以根据需要,将$code_path设置成需要的目录 +export $code_path=~ +cd $code_path +git clone https://github.com/PaddlePaddle/PaddleDetection.git # 进入PaddleDetection根目录 -cd PaddleDetection_root_path +cd PaddleDetection # 将预训练模型导出为inference模型 -python tools/export_model.py -c configs/picodet/picodet_s_320_coco.yml \ - -o weights=https://paddledet.bj.bcebos.com/models/picodet_s_320_coco.pdparams --output_dir=output_inference +python tools/export_model.py -c configs/picodet/application/mainbody_detection/picodet_lcnet_x2_5_640_mainbody.yml -o weights=https://paddledet.bj.bcebos.com/models/picodet_lcnet_x2_5_640_mainbody.pdparams --output_dir=inference # 将inference模型转化为Paddle-Lite优化模型 -# FP32 -paddle_lite_opt --valid_targets=arm --model_file=output_inference/picodet_s_320_coco/model.pdmodel --param_file=output_inference/picodet_s_320_coco/model.pdiparams --optimize_out=output_inference/picodet_s_320_coco/model -# FP16 -paddle_lite_opt --valid_targets=arm --model_file=output_inference/picodet_s_320_coco/model.pdmodel --param_file=output_inference/picodet_s_320_coco/model.pdiparams --optimize_out=output_inference/picodet_s_320_coco/model --enable_fp16=true +paddle_lite_opt --model_file=inference/picodet_lcnet_x2_5_640_mainbody/model.pdmodel --param_file=inference/picodet_lcnet_x2_5_640_mainbody/model.pdiparams --optimize_out=inference/picodet_lcnet_x2_5_640_mainbody/mainbody_det -# 将inference模型配置转化为json格式 -python deploy/lite/convert_yml_to_json.py output_inference/picodet_s_320_coco/infer_cfg.yml +# 将转好的模型复制到lite_shitu目录下 +cd $PaddleClas/deploy/lite_shitu +mkdir models +cp $code_path/PaddleDetection/inference/picodet_lcnet_x2_5_640_mainbody/mainbody_det.nb $PaddleClas/deploy/lite_shitu/models ``` -最终在output_inference/picodet_s_320_coco/文件夹下生成`model.nb` 和 `infer_cfg.json`的文件。 +##### 2.1.3.2 转换识别模型 + +```shell +# 转换inference model +待补充,生成的inference model存储在PaddleClas/inference下,同时生成label.txt,也存在此文件夹下 + +# 转换为Paddle-Lite模型 +paddle_lite_opt --model_file=inference/inference.pdmodel --param_file=inference/inference.pdiparams --optimize_out=inference/rec + +# 将模型、label文件拷贝到lite_shitu下 +cp inference/rec.nb deploy/lite_shitu/models/ +cp inference/label.txt deploy/lite_shitu/models/ +cd deploy/lite_shitu +``` **注意**:`--optimize_out` 参数为优化后模型的保存路径,无需加后缀`.nb`;`--model_file` 参数为模型结构信息文件的路径,`--param_file` 参数为模型权重信息文件的路径,请注意文件名。 +##### 2.1.3.3 准备测试图像 + +```shell +mkdir images +# 根据需要准备测试图像,可以在images文件夹中存放多张图像 +cp ../images/wangzai.jpg images/ +``` + + + +##### 2.1.3.4 将yaml文件转换成json文件 + +```shell +# 如果测试单张图像 +python generate_json_config.py --det_model_path models/mainbody_det.nb --rec_model_path models/rec.nb --rec_label_path models/label.txt --img_path images/wangzai.jpg +# or +# 如果测试多张图像 +python generate_json_config.py --det_model_path models/mainbody_det.nb --rec_model_path models/rec.nb --rec_label_path models/label.txt --img_dir images + +# 执行完成后,会在lit_shitu下生成shitu_config.json配置文件 + +``` + ### 2.2 与手机联调 首先需要进行一些准备工作。 @@ -183,41 +224,28 @@ List of devices attached 4. 编译lite部署代码生成移动端可执行文件 ```shell -cd {PadddleDetection_Root} -cd deploy/lite/ +cd $PaddleClas/deploy/lite_shitu inference_lite_path=/{lite prediction library path}/inference_lite_lib.android.armv8.gcc.c++_static.with_extra.with_cv/ -mkdir $inference_lite_path/demo/cxx/lite +mkdir $inference_lite_path/demo/cxx/ppshitu_lite -cp -r Makefile src/ include/ *runtime_config.json $inference_lite_path/demo/cxx/lite +cp -r Makefile src/ include/ *.json models/ images/ $inference_lite_path/demo/cxx/ppshitu_lite -cd $inference_lite_path/demo/cxx/lite +cd $inference_lite_path/demo/cxx/ppshitu_lite # 执行编译,等待完成后得到可执行文件main make ARM_ABI=arm8 #如果是arm7,则执行 make ARM_ABI = arm7 (或者在Makefile中修改该项) - ``` 5. 准备优化后的模型、预测库文件、测试图像。 ```shell mkdir deploy -cp main *runtime_config.json deploy/ +mv models deploy/ +mv images deploy/ +cp pp_shitu deploy/ cd deploy -mkdir model_det -mkdir model_keypoint - -# 将优化后的模型、预测库文件、测试图像放置在预测库中的demo/cxx/detection文件夹下 -cp {PadddleDetection_Root}/output_inference/picodet_s_320_coco/model.nb ./model_det/ -cp {PadddleDetection_Root}/output_inference/picodet_s_320_coco/infer_cfg.json ./model_det/ - -# 如果需要关键点模型,则只需操作: -cp {PadddleDetection_Root}/output_inference/hrnet_w32_256x192/model.nb ./model_keypoint/ -cp {PadddleDetection_Root}/output_inference/hrnet_w32_256x192/infer_cfg.json ./model_keypoint/ - -# 将测试图像复制到deploy文件夹中 -cp [your_test_img].jpg ./demo.jpg # 将C++预测动态库so文件复制到deploy文件夹中 cp ../../../cxx/lib/libpaddle_light_api_shared.so ./ @@ -227,45 +255,19 @@ cp ../../../cxx/lib/libpaddle_light_api_shared.so ./ ``` deploy/ -|-- model_det/ -| |--model.nb 优化后的检测模型文件 -| |--infer_cfg.json 检测器模型配置文件 -|-- model_keypoint/ -| |--model.nb 优化后的关键点模型文件 -| |--infer_cfg.json 关键点模型配置文件 -|-- main 生成的移动端执行文件 -|-- det_runtime_config.json 目标检测执行时参数配置文件 -|-- keypoint_runtime_config.json 关键点检测执行时参数配置文件 +|-- models/ +| |--mainbody_det.nb 优化后的主体检测模型文件 +| |--rec.nb 优化后的识别模型文件 +| |--label.txt 识别模型的label文件 +|-- images/ +| ... 图片文件 +|-- pp_shitu 生成的移动端执行文件 +|-- shitu_config.json 执行时参数配置文件 |-- libpaddle_light_api_shared.so Paddle-Lite库文件 ``` **注意:** -* `det_runtime_config.json` 包含了目标检测的超参数,请按需进行修改: - -```shell -{ - "model_dir_det": "./model_det/", #检测器模型路径 - "batch_size_det": 1, #检测预测时batchsize - "threshold_det": 0.5, #检测器输出阈值 - "image_file": "demo.jpg", #测试图片 - "image_dir": "", #测试图片文件夹 - "run_benchmark": true, #性能测试开关 - "cpu_threads": 4 #线程数 -} -``` - -* `keypoint_runtime_config.json` 包含了关键点检测的超参数,请按需进行修改: -```shell -{ - "model_dir_keypoint": "./model_keypoint/", #关键点模型路径(不使用需为空字符) - "batch_size_keypoint": 8, #关键点预测时batchsize - "threshold_keypoint": 0.5, #关键点输出阈值 - "image_file": "demo.jpg", #测试图片 - "image_dir": "", #测试图片文件夹 - "run_benchmark": true, #性能测试开关 - "cpu_threads": 4 #线程数 -} -``` +* `shitu_config.json` 包含了目标检测的超参数,请按需进行修改 6. 启动调试,上述步骤完成后就可以使用ADB将文件夹 `deploy/` push到手机上运行,步骤如下: @@ -278,23 +280,20 @@ cd /data/local/tmp/deploy export LD_LIBRARY_PATH=/data/local/tmp/deploy:$LD_LIBRARY_PATH # 修改权限为可执行 -chmod 777 main -# 以检测为例,执行程序 -./main det_runtime_config.json +chmod 777 pp_shitu +# 执行程序 +./pp_shitu shitu_config.json ``` 如果对代码做了修改,则需要重新编译并push到手机上。 运行效果如下: -
- -
- +![](../../docs/images/ppshitu_lite_demo.png) ## FAQ -Q1:如果想更换模型怎么办,需要重新按照流程走一遍吗? +Q1:如果想更换模型怎么办,需要重新按照流程走一遍吗? A1:如果已经走通了上述步骤,更换模型只需要替换 `.nb` 模型文件即可,同时要注意修改下配置文件中的 `.nb` 文件路径以及类别映射文件(如有必要)。 -Q2:换一个图测试怎么做? -A2:替换 deploy 下的测试图像为你想要测试的图像,使用 ADB 再次 push 到手机上即可。 +Q2:换一个图测试怎么做? +A2:替换 deploy 下的测试图像为你想要测试的图像,并重新生成json配置文件(或者直接修改图像路径),使用 ADB 再次 push 到手机上即可。 diff --git a/deploy/lite_shitu/generate_json_config.py b/deploy/lite_shitu/generate_json_config.py index fb54685db..1525cdab9 100644 --- a/deploy/lite_shitu/generate_json_config.py +++ b/deploy/lite_shitu/generate_json_config.py @@ -7,40 +7,63 @@ import yaml def parse_args(): parser = argparse.ArgumentParser() - parser.add_argument('--yaml_path', - type=str, - default='../configs/inference_drink.yaml') - parser.add_argument('--img_dir', type=str, default=None, - help='The dir path for inference images') - parser.add_argument('--det_model_path', - type=str, default='./det.nb', - help="The model path for mainbody detection") - parser.add_argument('--rec_model_path', type=str, default='./rec.nb', help="The rec model path") - parser.add_argument('--rec-label-path', type=str, default='./label.txt', help='The rec model label') - parser.add_argument('--arch', - type=str, - default='GFL', - help='The model structure for detection model') - parser.add_argument('--fpn-stride', - type=list, - default=[8, 16, 32, 64], - help="The fpn strid for detection model") - parser.add_argument('--keep_top_k', - type=int, - default=100, - help='The params for nms(postprocess for detection)') - parser.add_argument('--nms-name', - type=str, - default='MultiClassNMS', - help='The nms name for postprocess of detection model') - parser.add_argument('--nms_threshold', - type=float, - default=0.5, - help='The nms nms_threshold for detection postprocess') - parser.add_argument('--nms_top_k', - type=int, - default=1000, - help='The nms_top_k in postprocess of detection model') + parser.add_argument( + '--yaml_path', type=str, default='../configs/inference_drink.yaml') + parser.add_argument( + '--img_dir', + type=str, + default=None, + help='The dir path for inference images') + parser.add_argument( + '--img_path', + type=str, + default=None, + help='The dir path for inference images') + parser.add_argument( + '--det_model_path', + type=str, + default='./det.nb', + help="The model path for mainbody detection") + parser.add_argument( + '--rec_model_path', + type=str, + default='./rec.nb', + help="The rec model path") + parser.add_argument( + '--rec_label_path', + type=str, + default='./label.txt', + help='The rec model label') + parser.add_argument( + '--arch', + type=str, + default='PicoDet', + help='The model structure for detection model') + parser.add_argument( + '--fpn-stride', + type=list, + default=[8, 16, 32, 64], + help="The fpn strid for detection model") + parser.add_argument( + '--keep_top_k', + type=int, + default=100, + help='The params for nms(postprocess for detection)') + parser.add_argument( + '--nms-name', + type=str, + default='MultiClassNMS', + help='The nms name for postprocess of detection model') + parser.add_argument( + '--nms_threshold', + type=float, + default=0.5, + help='The nms nms_threshold for detection postprocess') + parser.add_argument( + '--nms_top_k', + type=int, + default=1000, + help='The nms_top_k in postprocess of detection model') parser.add_argument( '--score_threshold', type=float, @@ -55,18 +78,24 @@ def main(): config_yaml = yaml.safe_load(open(args.yaml_path)) config_json = {} config_json["Global"] = {} - config_json["Global"]["infer_imgs"] = config_yaml["Global"]["infer_imgs"] - config_json["Global"]["infer_imgs_dir"] = args.img_dir + config_json["Global"][ + "infer_imgs"] = args.img_path if args.img_path else config_yaml[ + "Global"]["infer_imgs"] + if args.img_dir is not None: + config_json["Global"]["infer_imgs_dir"] = args.img_dir + config_json["Global"]["infer_imgs"] = None + else: + config_json["Global"][ + "infer_imgs"] = args.img_path if args.img_path else config_yaml[ + "Global"]["infer_imgs"] config_json["Global"]["batch_size"] = config_yaml["Global"]["batch_size"] - config_json["Global"]["cpu_num_threads"] = config_yaml["Global"][ - "cpu_num_threads"] + config_json["Global"]["cpu_num_threads"] = min( + config_yaml["Global"]["cpu_num_threads"], 4) config_json["Global"]["image_shape"] = config_yaml["Global"]["image_shape"] - config_json["Global"][ - "det_model_path"] = args.det_model_path - config_json["Global"][ - "rec_model_path"] = args.rec_model_path + config_json["Global"]["det_model_path"] = args.det_model_path + config_json["Global"]["rec_model_path"] = args.rec_model_path config_json["Global"]["rec_label_path"] = args.rec_label_path - config_json["Global"]["labe_list"] = config_yaml["Global"]["labe_list"] + config_json["Global"]["label_list"] = config_yaml["Global"]["labe_list"] config_json["Global"]["rec_nms_thresold"] = config_yaml["Global"][ "rec_nms_thresold"] config_json["Global"]["max_det_results"] = config_yaml["Global"][ diff --git a/deploy/lite_shitu/include/config_parser.h b/deploy/lite_shitu/include/config_parser.h index 1228d1980..dca0e5a68 100644 --- a/deploy/lite_shitu/include/config_parser.h +++ b/deploy/lite_shitu/include/config_parser.h @@ -60,7 +60,7 @@ class ConfigPaser { // Get label_list for visualization if (config["Global"].isMember("label_list")) { label_list_.clear(); - for (auto item : config["label_list"]) { + for (auto item : config["Global"]["label_list"]) { label_list_.emplace_back(item.as()); } } else { diff --git a/deploy/lite_shitu/include/recognition.h b/deploy/lite_shitu/include/recognition.h index b7d2a48c2..0c45e946e 100644 --- a/deploy/lite_shitu/include/recognition.h +++ b/deploy/lite_shitu/include/recognition.h @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#pragma once #include "paddle_api.h" // NOLINT #include "json/json.h" #include @@ -54,8 +55,10 @@ public: } LoadLabel(config_file["Global"]["rec_label_path"].as()); SetPreProcessParam(config_file["RecPreProcess"]["transform_ops"]); - if (!config_file["Global"].isMember("return_k")) + if (!config_file["Global"].isMember("return_k")){ this->topk = config_file["Global"]["return_k"].as(); + } + printf("rec model create!\n"); } void LoadLabel(std::string path) { diff --git a/deploy/lite_shitu/include/utils.h b/deploy/lite_shitu/include/utils.h index cbda311ec..18a04cf34 100644 --- a/deploy/lite_shitu/include/utils.h +++ b/deploy/lite_shitu/include/utils.h @@ -14,13 +14,14 @@ #pragma once -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include namespace PPShiTu { @@ -32,8 +33,11 @@ struct ObjectResult { int class_id; // Confidence of detected object float confidence; + + // RecModel result + std::vector rec_result; }; -void nms(std::vector &input_boxes, float nms_threshold); +void nms(std::vector &input_boxes, float nms_threshold, bool rec_nms=false); -} // namespace PPShiTu +} // namespace PPShiTu diff --git a/deploy/lite_shitu/src/main.cc b/deploy/lite_shitu/src/main.cc index ae23e7c55..e9c05c72a 100644 --- a/deploy/lite_shitu/src/main.cc +++ b/deploy/lite_shitu/src/main.cc @@ -73,17 +73,10 @@ void DetPredictImage(const std::vector &batch_imgs, std::vector det_t = {0, 0, 0}; int steps = ceil(float(batch_imgs.size()) / batch_size_det); for (int idx = 0; idx < steps; idx++) { - std::vector batch_imgs; int left_image_cnt = batch_imgs.size() - idx * batch_size_det; if (left_image_cnt > batch_size_det) { left_image_cnt = batch_size_det; } - /* for (int bs = 0; bs < left_image_cnt; bs++) { */ - /* std::string image_file_path = all_img_paths.at(idx * batch_size_det + - * bs); */ - /* cv::Mat im = cv::imread(image_file_path, 1); */ - /* batch_imgs.insert(batch_imgs.end(), im); */ - /* } */ // Store all detected result std::vector result; std::vector bbox_num; @@ -108,32 +101,7 @@ void DetPredictImage(const std::vector &batch_imgs, } detect_num += 1; im_result.push_back(item); - /* if (item.rect.size() > 6) { */ - /* is_rbox = true; */ - /* printf("class=%d confidence=%.4f rect=[%d %d %d %d %d %d %d %d]\n", - */ - /* item.class_id, */ - /* item.confidence, */ - /* item.rect[0], */ - /* item.rect[1], */ - /* item.rect[2], */ - /* item.rect[3], */ - /* item.rect[4], */ - /* item.rect[5], */ - /* item.rect[6], */ - /* item.rect[7]); */ - /* } else { */ - /* printf("class=%d confidence=%.4f rect=[%d %d %d %d]\n", */ - /* item.class_id, */ - /* item.confidence, */ - /* item.rect[0], */ - /* item.rect[1], */ - /* item.rect[2], */ - /* item.rect[3]); */ - /* } */ } - /* std::cout << all_img_paths.at(idx * batch_size_det + i) */ - /* << " The number of detected box: " << detect_num << std::endl; */ item_start_idx = item_start_idx + bbox_num[i]; } @@ -144,14 +112,13 @@ void DetPredictImage(const std::vector &batch_imgs, } void PrintResult(const std::string &image_path, - std::vector &det_result, - std::vector> &rec_results) { + std::vector &det_result) { printf("%s:\n", image_path.c_str()); for (int i = 0; i < det_result.size(); ++i) { printf("\tresult%d: bbox[%d, %d, %d, %d], score: %f, label: %s\n", i, det_result[i].rect[0], det_result[i].rect[1], det_result[i].rect[2], - det_result[i].rect[3], rec_results[i][0].score, - rec_results[i][0].class_name.c_str()); + det_result[i].rect[3], det_result[i].rec_result[0].score, + det_result[i].rec_result[0].class_name.c_str()); } } @@ -163,37 +130,33 @@ int main(int argc, char **argv) { return -1; } std::string config_path = argv[1]; - std::string img_path = ""; + std::string img_dir = ""; if (argc >= 3) { - img_path = argv[2]; + img_dir = argv[2]; } // Parsing command-line PPShiTu::load_jsonf(config_path, RT_Config); - if (RT_Config["Global"]["det_inference_model_dir"] - .as() - .empty()) { - std::cout << "Please set [det_inference_model_dir] in " << config_path - << std::endl; + if (RT_Config["Global"]["det_model_path"].as().empty()) { + std::cout << "Please set [det_model_path] in " << config_path << std::endl; return -1; } if (RT_Config["Global"]["infer_imgs"].as().empty() && - img_path.empty()) { + img_dir.empty()) { std::cout << "Please set [infer_imgs] in " << config_path << " Or use command: <" << argv[0] << " [shitu_config]" << " [image_dir]>" << std::endl; return -1; } - if (!img_path.empty()) { + if (!img_dir.empty()) { std::cout << "Use image_dir in command line overide the path in config file" << std::endl; - RT_Config["Global"]["infer_imgs_dir"] = img_path; + RT_Config["Global"]["infer_imgs_dir"] = img_dir; RT_Config["Global"]["infer_imgs"] = ""; } // Load model and create a object detector PPShiTu::ObjectDetector det( - RT_Config, - RT_Config["Global"]["det_inference_model_dir"].as(), + RT_Config, RT_Config["Global"]["det_model_path"].as(), RT_Config["Global"]["cpu_num_threads"].as(), RT_Config["Global"]["batch_size"].as()); // create rec model @@ -202,7 +165,6 @@ int main(int argc, char **argv) { std::vector det_result; std::vector batch_imgs; - std::vector> rec_results; double rec_time; if (!RT_Config["Global"]["infer_imgs"].as().empty() || !RT_Config["Global"]["infer_imgs_dir"].as().empty()) { @@ -239,7 +201,7 @@ int main(int argc, char **argv) { // add the whole image for recognition to improve recall PPShiTu::ObjectResult result_whole_img = { - {0, 0, srcimg.cols - 1, srcimg.rows - 1}, 0, 1.0}; + {0, 0, srcimg.cols, srcimg.rows}, 0, 1.0}; det_result.push_back(result_whole_img); // get rec result @@ -250,13 +212,14 @@ int main(int argc, char **argv) { cv::Mat crop_img = srcimg(rect); std::vector result = rec.RunRecModel(crop_img, rec_time); - rec_results.push_back(result); + det_result[j].rec_result.assign(result.begin(), result.end()); } - PrintResult(img_path, det_result, rec_results); - + // rec nms + PPShiTu::nms(det_result, + RT_Config["Global"]["rec_nms_thresold"].as(), true); + PrintResult(img_path, det_result); batch_imgs.clear(); det_result.clear(); - rec_results.clear(); } } return 0; diff --git a/deploy/lite_shitu/src/object_detector.cc b/deploy/lite_shitu/src/object_detector.cc index 59ccba3af..ffea31bb9 100644 --- a/deploy/lite_shitu/src/object_detector.cc +++ b/deploy/lite_shitu/src/object_detector.cc @@ -95,7 +95,7 @@ cv::Mat VisualizeResult(const cv::Mat& img, void ObjectDetector::Preprocess(const cv::Mat& ori_im) { // Clone the image : keep the original mat for postprocess cv::Mat im = ori_im.clone(); - cv::cvtColor(im, im, cv::COLOR_BGR2RGB); + // cv::cvtColor(im, im, cv::COLOR_BGR2RGB); preprocessor_.Run(&im, &inputs_); } @@ -235,7 +235,7 @@ void ObjectDetector::Predict(const std::vector& imgs, auto postprocess_start = std::chrono::steady_clock::now(); // Get output tensor output_data_list_.clear(); - int num_class = 80; + int num_class = 1; int reg_max = 7; auto output_names = predictor_->GetOutputNames(); // TODO: Unified model output. @@ -281,6 +281,7 @@ void ObjectDetector::Predict(const std::vector& imgs, out_bbox_num_data_.data()); } // Postprocessing result + result->clear(); if (config_.arch_ == "PicoDet") { PPShiTu::PicoDetPostProcess( diff --git a/deploy/lite_shitu/src/preprocess_op.cc b/deploy/lite_shitu/src/preprocess_op.cc index 90a54a1c6..9c74d6ee7 100644 --- a/deploy/lite_shitu/src/preprocess_op.cc +++ b/deploy/lite_shitu/src/preprocess_op.cc @@ -127,11 +127,11 @@ void TopDownEvalAffine::Run(cv::Mat* im, ImageBlob* data) { // Preprocessor op running order const std::vector Preprocessor::RUN_ORDER = {"InitInfo", - "TopDownEvalAffine", - "Resize", - "NormalizeImage", - "PadStride", - "Permute"}; + "DetTopDownEvalAffine", + "DetResize", + "DetNormalizeImage", + "DetPadStride", + "DetPermute"}; void Preprocessor::Run(cv::Mat* im, ImageBlob* data) { for (const auto& name : RUN_ORDER) { diff --git a/deploy/lite_shitu/src/recognition.cc b/deploy/lite_shitu/src/recognition.cc index 8d3a99476..0e711f386 100644 --- a/deploy/lite_shitu/src/recognition.cc +++ b/deploy/lite_shitu/src/recognition.cc @@ -38,7 +38,7 @@ std::vector Recognition::RunRecModel(const cv::Mat &img, // Get output and post process std::unique_ptr output_tensor( - std::move(this->predictor->GetOutput(0))); + std::move(this->predictor->GetOutput(1))); auto *output_data = output_tensor->data(); auto end = std::chrono::system_clock::now(); auto duration = diff --git a/deploy/lite_shitu/src/utils.cc b/deploy/lite_shitu/src/utils.cc index 88b2c563c..3bc461770 100644 --- a/deploy/lite_shitu/src/utils.cc +++ b/deploy/lite_shitu/src/utils.cc @@ -16,14 +16,23 @@ namespace PPShiTu { -void nms(std::vector &input_boxes, float nms_threshold) { - std::sort(input_boxes.begin(), - input_boxes.end(), - [](ObjectResult a, ObjectResult b) { return a.confidence > b.confidence; }); +void nms(std::vector &input_boxes, float nms_threshold, + bool rec_nms) { + if (!rec_nms) { + std::sort(input_boxes.begin(), input_boxes.end(), + [](ObjectResult a, ObjectResult b) { + return a.confidence > b.confidence; + }); + } else { + std::sort(input_boxes.begin(), input_boxes.end(), + [](ObjectResult a, ObjectResult b) { + return a.rec_result[0].score > b.rec_result[0].score; + }); + } std::vector vArea(input_boxes.size()); for (int i = 0; i < int(input_boxes.size()); ++i) { - vArea[i] = (input_boxes.at(i).rect[2] - input_boxes.at(i).rect[0] + 1) - * (input_boxes.at(i).rect[3] - input_boxes.at(i).rect[1] + 1); + vArea[i] = (input_boxes.at(i).rect[2] - input_boxes.at(i).rect[0] + 1) * + (input_boxes.at(i).rect[3] - input_boxes.at(i).rect[1] + 1); } for (int i = 0; i < int(input_boxes.size()); ++i) { for (int j = i + 1; j < int(input_boxes.size());) { @@ -36,14 +45,13 @@ void nms(std::vector &input_boxes, float nms_threshold) { float inter = w * h; float ovr = inter / (vArea[i] + vArea[j] - inter); if (ovr >= nms_threshold) { - input_boxes.erase(input_boxes.begin() + j); - vArea.erase(vArea.begin() + j); - } - else { - j++; + input_boxes.erase(input_boxes.begin() + j); + vArea.erase(vArea.begin() + j); + } else { + j++; } } } } -} // namespace PPShiTu +} // namespace PPShiTu diff --git a/docs/images/ppshitu_lite_demo.png b/docs/images/ppshitu_lite_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b48293d9f7da512c71d0458881476d1c9cc780 GIT binary patch literal 55001 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%0DXN#;e!o9-RG-G;SA}TY4qkJuj zw})?F5419d_6T@fRZP3oMx9}{5}cA^U#S-}vD5BVM_K+aL?v=2-#)PJ%jU$BC~fV!dIm|c@agyHtvd0%BAma7H5s{`Kf=zD36Uv86>cy zIMS!+2t1~+=*)qZHqBcGVF*(nIr82l(*^X0S1_bf=Wksl`3AC)PnGOSZ z@kb6G6kU_wFvM0Ibg$_q&Ua0;N1$2X2?KW0!_YQ^70!F*=T_APu@Mif{3Ccj5iCaJ zJcJDJ(Rz346&;Hk6$M&pbDdpvMC`vmXLx{oZ``%u;J^>{1T(WFv!W5Lr=KQ= z&{iRf`;sz~J+HFZ%=P`dX==bpW4LpE`PI=1Co@rp#C=90pM(!x^INZc()z`XD{yiS z7wa%lWPO>@NM3XXnY0FxDKa+K5oOE7`i8Kp-oEJc!_?EDA&ee{y)OMFTgoU)h5voh zw388qCdl?%|0^>)_+{YgP$%lLk%V$;H>&V_;)3Vr_ykT&Sq5II$t~p79~jgQUlLw~ ze98GrrSRfQUE6zuF!jGUEidynIkNV8KrG~~;1GdKWk!LRwD{i_hnc^Z=w;sE3sPU= zhxYc!H&e(A+8~RRKeKwkR?_p=S>m-mKG{IX94KU`{m?_!v~(+iMv1{Z%q4}d!ExJ! zF1V^j4L#bxYBe(y$z-hK1Uwh=O#Ip+KxMb$3V1NWV2imRmP3VD1JrXvC%|G3$Z zSab{>h}C3UVl&=!*oSyDSTxz>^SG@nuVoIsqS{0mQ~VrdS(>vzTF*19@%sa3|Lgb8ohThf1)N8KdPKso?laS z3|nF!PM==9#~SWyo&2F~Ae#&h&T2XbFI(O`V(0NeCBK^32MQ|l_iyxB&Tm^5&(i7* z_sw=gcKT=A{_Ya3sFP(-i`|nbd|^M2Ehs|oXS;+Abu=$O=u_EgOR~OaPZ(lv=~3pz zVUB~=7fQ>yg6U)C42#-}L+X96)pbxy52yu83I+1~J=Nnsgys9EA;Fz(*W)aT}+ zj!W$zsr7Y3U44GWmW}*=IrMHsQO-|{vMyrbZ=6-=LC65B%@UdX^*t!tyzT6-bFY=O z0~ryj@p83$qF)d(^$f9bZ`RpkBcFPwdy^gME0R#L3_mA){A??9nAzalXT`th64+Li za2#+#UBZkU6Y#JV!)z5v2h;`?^oYtoR~5<8Ig=X3_zX zaGG9Z*J5#W9c8a#!zma}@}Q6gC%&Ci#1Cqu5@;;}5$6tWj5g9r!84B9uLjoM@$^~Q zIME+y;ypit2DaLRpV8Qo#MRvQ=mSd(esysyfX-#_(fvQe7+BrZsjWT-$x&HvoViR{ zJ=|P3G(Wj-*!-AbqWDfh_{}tGL?aQU88_Us)AQ}~hSsDw&!qr({ZfmncE_JZg%M)# z3r+=<;O)FL!^GtLTKdN9b!z){G#Y;C+2VIP-5#baWoNmXgXhOCKJ460Sq)zJA(9d$ zs*{X)>i?~A3^*wME7+w*2Uzw{{)fFmCG2%sY#*MyD|#Js_Kz;1abUV*TL?5n(JYYA zC|6wB!_RC2H8rQUJ4JOt5qg&7_TM3b80jp%JM76$4O^KeWZELQn&#OZh z{+^=(L=tnQdq|QYZ`~q=mt>O&H_K6^Q54q+0baal!G#`TEyFbQgxp2gh3_&tMsFkEHzF?BT$?og8^ z)p=(0)t7s2VUQFK~^4%1Zc<#}uKy*0O!Om`QR5D-XTGA^Wy*EDBU!&?Ost<=dUao_rw=zpn?P-iBMdaE1iL8o2s9{Lyg>=t*W|B+mNF(smdOBkkfm zI14TAjM$mq8h}K>Z+LrVm){Jg=h6KvcI`fV6#m0`-k^P!z~eO|IzzN-&u?PHppFxB zjarjh0{e+to52paAe_~f!Dv72)X+AqXg82PT)sZcegDC;tlWf(umFjI=KYM~?=gZU zCGOXinrpD4KYZ#O?T&q3&#JC`J8!g|eKVUqyX7`46rqaxuG$V^(bd=L@Ly2lrusK_ zXT@*QX9@@M1%?Hh%H~+4RTf6L^)+3>D7Yml+y||fb!evF)=WDXwZRzotQ%|&wY7C% zV^po|YmO%ANVM}YRc}NZ$5xEZn@SsD5c7$WEJzglIhfzD`?J{mAv&#(Jte10@$Oh+ z*}_|#m+w}Dt9I&%eC(-3{GD+^oBRz(-|bi8(35ym=bX7bBgHNJ$o;IlSl|@Us)jwC zS)5$1fq%@_9$`1o1k*I`k$DI8b{}ptSiAN8Z1K8fAbm)IJ%<^d?)Q_5J9kPBa#L;R z`XweD-APoBjXvI>a9^KtCV6^|e5pB_#KJR7oE&D8_Jq0wm7GKBy3* z3qAED69--eNMRDcv2D}#ed13Jm7r?%`det$n zd8EBF9J@Q%CX&BBa|$GH=j#b684;CEFrGrKa(o)d)yfH3n2H5^L2gH{ekWR_SSnFR zjREB;-@TZY^;lKM)wp`0Y)85y#c}e6x|`9FmurXvO zq}aQ4N%{sl@4@I$h?(c+>p>9FF*8!e#z90X|4SJnvRiyT=^XGeuFo(ym5HLdv&sRF zWjL@2f>;|cfG+7!Tpba_&A<4*cmi@U1I{Fq`ROnF=B3cl-fm1tkx!xw=aeSQc8{qN zxuf6jm+2PFSucT-9ejx!rAx401XHFHj}t|v8ALx_FVUXdq{ZM!ogM zR=rH7t_0Ch?^E1a*D2#IDcfg0_ri({8!Rr}W5cPtPZjf=Xn@) z9Df^I)kUGIFKNmgB3Y6N8I6=T?`baZJjvbnp}l^T1QekKkgCQ8e5^+ilKbqSVK(A{Kk=Q?}M98<_qpm#B6vnuz7FWFG;;&yFN<2 zQ+hbmjs~hSbF-0cK$sn|({@(qI0DWD1;9?%-;14W#DRES$+Q4aSN_TZ|LJ14KfKs< zqq~nnxEc&aa`X>T9{@Kd1821>@Y^@Oze`-10u&c-rui2FAq!wJaS-yh8t`12!5|u1 zFlyD>xCqbG$iF%!Y`F!*%(LL&(rLg43at0rg69M}MIaWqpgbbZN;%HI%7}$Grm=8_$Rr+u{dUY> zR;7cINbcqVQ&afdy1JJ5gdyN|t|Bf(a-fem`mV>GReu>(P=4NY|2+`<@Z3#R0lq(( zJt|!JOZdA_q}ijjoAokAq%RfEdT$o+Kat-aXN#IQ_?-q!4gs`|ZbN4hw>>rG1V_y2 z4H!~=A2Ge7ylChR9!TxWSUzCZ)-823U%V4W%>NKf2bs&e&t-bUjh;ovhFC+)_)#)i zcb}pEWC8H1R{{+0NupE|&VYR&-b`#=LxbHQ8YM2)*5!4PhX%!$u{}{u$brsqg;c}* z&C}K_#c>86@F>_oJKn&|lI#3xp+~8-=nO{P?({37Uka}~aRm{B35zL(U=;WkKPd%J zLSwQ9=RSSY;O5RZ8*i3hk&8wiosxij&&-w1-n<2stG@y#rJ8#%GISBsij8%^i07hk zNyI4GAb9V$(sx)J{1?<9gPAZ3*lr2!QE^P%8;&Hp%4Z3OFbx2DZaAdJHPOFyy)C)m z{)jBe`?eCmX26~Qsr>u)+`0L6lQ@_#{O8*Juo-> znLzum8e!EKl?tdP4OO?%s2T8OrmQ0%Ic8FqfgDOQ7Iw2D1(*%nwAz z{MemFZGiAxe3(4zuCJn(43*#Z$D>X#U<_8{Nr@FH{?h~@l7;Fg#LjRCsC3FjIb|^I zq*rp~g{cs$vO5n`sJf*XTBeo<$CY=@s!+;S6yD#l2O^yi%N%V|2y zJSn(7s`Zh%y1o!$C&lXde7HN|7T=$}E&vEpj#lE}X%eIJXm$NE|5s*4{T7gGvUKit zog1X*Jf@H?S=HUa436^rxgt6?gC&9N%jF+l4+m~3l#Nt47`DNaL!hO7owDQ=Y5mQq zrr_uxfe8+lN0CTAbAQhluBcx)W8ltDIqVFojTTs9GO5-F>fKJIDH%eN{~~K?u5Qpx z6BW1885#!<-!eHdu+|@>?#TJzNIbr1e=$P`9Sc+!h5)BYtkBG3r5y& zU_LM}^7MVQD*BP?`zJ8F_9GNfgdNc%CiNBSTMG4CqP0!F0LWR^qpS-7qA+D7`Ypy( z_u_E4arY~JIiZ8rM+|z^r_62~pL9-lmp8z)*W%AGidd(HVAG7C1x9}`{z8B&1jRZJ zF>Twj@CAu$!LE$($%qD79vHUWh=g(c+7wI}A1_lgc$Rrq__;8ZsfhYm#^rA~mBH6T zSR$g1ur(zxHvV|2c8PReQ>4(V{ENao_$Z>!EAC=((v0YFlE()WK^Fo=@#Hqd>8nLQ zfO_o3IB6fGSR-a!^!5Osy~N>xzP3=3DTp7v;v2stLF%wzYeJRD~vHUg+>Ox#cfEUN6tTdLMklKO26N zOw}GeqZW3d^3cjAqSRH5n#OTN;r)xCm=Oeq2parhCel(lxjjoU0H0#4tbc^#Lu1b; z-oT5}E+6<{)}Z5_-rI@AHwvk-p8Px19x5gKdELcK)G0qKh!T#?w~mpQBGuI)<|=no zYVs;*kdE=`RQJO-BaBceGZCC|quN{f*5`YMzi~-yENRC5%%{oz z;gKGaf`M@xx4w~npe6YvGOh>(OxIW?Z{gkm(c}vg(@*RkhZQG<=_9A}5X0Q^ zW=Y1{1%;|~h@tvq6=1z?c||}M17E>{-f7;_rLZ;Re4vn-j3j&vDH%9?-Juu(wu43y zhez%ded)h8>>I#`B9S>J(Z&ALi9JnW=_LiY4u#we2}hPr7vFVoM(Q#cxw6UB03X|U zUfd-Yeeo(s)Id4Uv0Y^d}x5@9;FQdcN*6-mXAgGjtbSNO9bh9N?1e6q! zlCBL1NOyyDcXvrkBLdQ0(wpu^y6c_Gdw=i!p5t-<;qi0ave#a7&G|fIjAx8&vVz5q zn7WOcPi^u&UAUuu*3S$$`ey#rMuWP$G$w@0I?3A1E8z^I1>IU|Ph$1;>X{OCbV2+I+rj(mQWt!p z#+cxmuK#9ugS96`E<`IN-wr<41ig7vL7qmrbwn;%$<&?>%@MDGd}zQoh?mqwBZ17rS_(E9RAqabuPn;i}*YM^UCu z#&xinau}yKQ@aI+uve41K5{oV=2gezr9Y9waWtpbnW6EPMj@BqdzEP8uS+g7s3Nz< zKHse!WJ&#*Vrbmh={PZjmt2+j=VmI7spmPn4gr(8r_qD4yiyexJ$v(%+bgBs(zmBc zUJ;KlaI*M8%#>B;LEB%Smz!lpSDtm5_D9Vdi~9tM=g_9aW~l*F%y{O$HpU=#i%dD+ z^iH4K%P93<^t(*`9V_MNGtywE9zDXI7zY@qkcStEPx>3xC_8zAwB?ncNo|j(8pAz*xUx?!-G+rAfc12_a4sTuo2>}(C zV@BaZTmeHwh52w@rvPVmb)}bOU_skb>-U}p8gdSfxUyiT9UB7AymOBttY#vY(zB5y z#XYIcTj{TfbMnFk-T`SxS1{*WQLzBkVqk_I)7Ofq~~6&EEM3L ziIyM>&0rUuu^Ghl=KNBHe+`EcG`BAvMzAlYWaCf^v6-mJwaUX)qtKe~%B`iB9%e24 zURfb$3Lg;K6J{Aqu=pmwbe7E+d0I1r);XZp)O3+dYRkm)#O4Rvnzmt@MfbyOhIb1- zqGwqcXBKU>o@e@{V^Zgrdd?r>S{1Ih>K5zR^bJ9xW*oIu=yPKdeXz zs!QSX*0gd6foh7+pw$`2+mB>^k18GPj5spOHI(&qk6psgT%RqfH^ zl=}t&hLY2C_qE>2N%zp`SxGH!bbVTnS#EWTxbtfeg-WWx7IN+-m7o#*zM1((`tKEQSJ9UdtgRRDp(dEN+GLJQc93^ zgUq8;@pexkm|vp=Y2=UP-ylF5`6k_P%LfwKXpS2QEq;L`Z*FJymmkuxuMx<6gH6K>zvOl?HsL;)B<{NJ^P$D`>j19U^xy& zdqaX_W1(2co*PfLXWIOp9DYwCzP?H2p}Qs7D@}!1Y<5^;*VV`T!st&SKcSP9Bw`E{ z^@Z6@vHUj+gg*vsKLT)IRFB&A`XJ??^+{cDBdd4HAcli|MqUurn|j$}>4m8l z2q*2y&ox%syPeVb1}KsrssL)sCid%8xvmgc0hw7*nE28Ex)B zV&-lFlgZvZt9`wvHNopcrQ{k(>Y9d&lKzh++0!zdjn6yIp3ma?gb%ZUz*kn|Ic{N9ePUFfsW(yTq~>cA24VuFJ375A@=X zNToarO~Y^;j%W<}7q??l0w=x@E@$giS>**|V5M3O(U)R9&9APMWhQQvliWRLETek? zmmH>kN~tgkoWRt@kv6@F$>y5-Tx<&-G>N8!Ts}wNx+NN_oEgc*mLc9>MmOxv<-0O3 z1viOo8Ekx(e)|}?$0yd-N8cc`g+>$&XMYD|jhWd>30~d&UE|Cv-5pOD>1uqi(5r zLH=*D4eMgEh{5S5rF?#cqjB8(Kq7J1N9ghq>zrtU*eY&o#rmf^3aF^}l_c8d*k-kk zuSLzbgD&waNTWmMd%0$p(jQ7x4jPoC4jhcTZyq)hNIOvbi0D<>WNfG)kiHw@Zs~VR z6QfKJm{Sd>Rkw{As==i87>rWp@n%sD55_A#yW@?195U5J%3u+ehn9j-1nQxjR2ZCz z{@T(mM0Z7XR>H1WoG#m#&3S^T?s)+l=QC8#U8-P8{83?Q$}{U4C!bv#Nli>fqbx%W z1IzPgfeQXln;KrDQgiTXccO{jjnj+B{gkBDXf6N%fX3E+aAhE zKYbi@Jr{TEDb1GzLw#UEE2M%7r@d?3`by<_L+R&WLafPB@%$OaGo%09?f_+AE#~EC z?KB>r`Np@AH9Cd%?3l}B$brSk5#)xYbw*b)7BfmsuIkOIF3rN9n_UWPR+d(|-+ELT zDr{a+s2$%SBmZ5?KQhXzo;2FR+Wi`{v9dWo!}P!fkFVf~V^3A7R6Q`>c$Xt@$OZB- z$baeSs}-8|puCYaxFBcTJWxC`3=^9XDyWIAdu6EimqL&Eh`piBv#dNT|E`#jfc2ra zwcF5CVLaz#oc0U91DSdu-~gpMu_Ntw?WpZ3bx0>BvR1L+PsgJCyl`e!mpouU*rFkj zAbER#!lBBm`E#^#C&X1pG$s0b2e-M05sT*BN|dg!HrTgk*SS4lr7OEp>c0Ag5novH z(>f>H(`Lq}%bCckoX*Ko)UN979EW$f?b(}dY3R9^2FT&I{*@SKU#>|}zcq1etYd}I zpMauFr>tV*SpS4&5}iPfS@~(E$ES-gB|EWR++8AK_*3@oZ(E4>=8?rUZ&c8&dAlbt zoC$W?JN}}C=7mBynua;w&+8akOXze#Y~D4*=Alt|(Q!Y7*gOYuF15y2ekZh~;NW0% zM%e#nH7waH0Ur_1g884ezQjmKuVDEloG_@1(eQaKKBf)D4GZ=hi+Cp>mjc zEu$;3pSFbGl63F00{d zw8`L@3{}$}sgE6x&Lf+$aSn_u%b%D~1;OISO_{gv?x4?tka^wgdoni*k-^64NcaA7 zrkt>-wa(xNYANP(M&zfTY4_zuMiCefB<$AKhT>M0@MBAwpd^%@+P#^mqXYkB)2Bs# zWC~FND=KlTeA$@&LU@kTnbP@##vU^AFq?k3+Iks3kS*0DHvK}B{37S9DFyhzk0Ke! zJSOj#@C_28<%73nq%f+hv7v+-Y*%@Vw&l=J=g@-jSx@{jl*%udPL^q3q0Fp|{RK;+^vqp;G#|)g zcY_L)VC<90zMW=h{R-DLIu8VojY&CywV4aBHVccRSKI1$d?UynkauF$Dj2YVg#_{$FtO!6}P zu2%f1V(am0N!fRQj;GOVd&NGo$!x9)H}$frma{L2pvy6QD+I+Lm zCNt(#4&|HaE={lKk|JrHArKXs?Oe&;p_$y3L2oIrffQe3J21%btnK(r=X`_xTk12G z@hZOz`mf}UmF<}TWqcc*?L3iw{6I{5wI@W_06&0Buon5aq#8K68ZPvf) zi#C?j9w=m02P26-eGxAEJEcW~T|AxKDQ^1p?-+Q~p)ee56Hdnqr-;?O{q!_VWL-89 zab46}A84xSxk^+_mWa-4egBw|g?I|X*m=bs3^~&%sUg;LqU6cc#t3Uu;G0%Vc6J&C zQd%yi{pP>S=c~z9RpiGT>Y*;tpmySRpk+3OfDkpA$ir~u);+af|NWf14ZJ3 z1`ckgsGpU4Se1y?_5|3Ke5LJ^#cx5U+!y60yF(g=fqS!oO9LFf3(z!Fa63KgnC6Em z&;K!Wf$Dc&)5-Qm1&Fu8ij;2di}X7tQr{2wi#7nbtx35e989B)G;0iQ$>gDo)+@$M zkk(P6Q6TXmHJje*9#EQTWpALR-9avX)hC;9=Y0|6zt&|Wh|ee3HFR3>zn_93hysnA zSktqg^4bQA(V>{lwXg`;hci(dSp-xDa`fjbe-NT1yEFdqc3<*1R(sTFqpaywtKM>; zkt^H$*+1FD;09aLTa&jzo}K#XC*=7omRAiA#$GD%5B|YQLhNGdL)Mk&S}kY)WGw&7 zU;5uSYpuBRAmm?&Nx*ut-U)o1NXDyKO-vIg2~mt7%JwbR^ur6=JbfPS8y6sHM@66P%lY3o@ZU=a6upCyN34i&<=6re*jsuZ-=iWVILW}| zh}LqHVlW(eYzz1&<<=YpyL@@1r7=f+(e4EWeRse|Fu&bRV>xBeNf$bJve>vt{x|j& zTuZ9yeWD5y&1QCpyOT{x;*@Qs6B9TCBPQg4>@mAKdccE>nR309BXqEle|})~ z=RZQ^-sP;i9mdwyaAtPLm|vYRl_`T142LxVxxZY@tEVTET>*$`X!0gH2UY_@iiOB5 zIvz!>x9m=3GC$!kT8D$vTe&rJNCC0A@ub@{ieG>Ia_W!!a*pNRMLY)F-xyitPJt=f z`VJWCxCdPI0rQjqaEStttJyrrgt-SYS-%WolX6S0(}G*In?ZR+FUhwY>CpS_O35(}lg(al zJ)kcK#M7Grn!_9LlHMTMfCYf|R> z5JVoXJ3j+ENFHG}2G)9NRhi&BXz?}Jer2DrdFLlAup$qBHori1cb_5q!`c?3*p!v}rYbIj8(A4Aq&79j3ry`q3xJ{}rE zEoLg-k{zwhUT;~Fe?MwG1^jg*AZM-kSzsU)tqL@@o!~+Xpy`kFm7_(c@w5ga8(UR!{1{X_UNJy?e zVc3vS=t}-L7Ir&?$ey{mchRx(QLvxR0{h(GUIXbE_@02ux6Nzvc&8j4XMHGZ0dg4_ zvV?OvAB({$@%CyG%v{0z)z}4KmC~|}#Mc2on0=zh&5e^ICe8u0`_=&Gic6EgX#VGUiE`l8J*DaavhtvVG$N3A`K@DscEIi>TBB=sU z+0$OYMzhrQWp{q-5#PKjSRm=PR8wo2i&)KBbJ!|rmj(uLT+2fnmVnkC*`&25X_j$~ z7RZ)v%#cnFU_Gc_IBqsKS5-y*`)eZ7y@{&`PmPvPF>w zAn69(w06%sxx3&ak?ZB&(Iu$bMlJA$ z-B`wM#xKc}8j|XwD%Oc$Wbm-Eha$&Fh3^Ka#+$&GKe@LSrKlbkFER^eTO3UN8M4<> zb8CF(`Lda{cXJn-fAxa9?x2FdFnFd+{VXl0)z~Sq-6x9FY!vBs1gpn=OZG z9_}!Pl+-@gw{CpsaXap+Qcj?4cWTc~6@L#eLRv*HBzLGlxP;xlFQ&Wr&&|vAKK*;u z)+ru--~*l4!RqM%($Ww86Tqa6SlykBQ*!6SpX6Ps3>;tpDK1-Jv!HCl9KcQJfS>Y6 z&fwMeEXWvwZ4ema0BU0i@RVJHi5+$t%4 zX94ry-l)Bw$7}8fK4p2j3WVBiN!ptI?YqY1@|P{pHt495qkts@`-dPVxZ#V4TkZ&Q zfYS4{$cjuY5bJ|U&k90-^v8kgl@%O(*QUc_(O}N+E9e=#A;m;4fa;j=6(l{uf`iOC*7R^ z;p#~6)E=j{rKsh?txJH;qm!D}nm0sRgQFA+YB|Tj-t*oZ+Q~)&quDz@s3pCDR0GX` z*rRxB)tVa-A4kypwwq*@)oShSQ8Z+gX>?q|-#&c%uEM;W!i+Kh$^aOmFpa5uRGkVMNi*fi1s>mmp0F?xEaiVT8T`|DVVDmlvr6aiL$s=Y~Zqvt?KLdDWUa z2ci7*L5NClkg3dmvuMYBfoIvj1U!<&XIw5!vRd!rNe7oor|4cJa)v-ok2n$X)*Cb` zYgUt1 zypWqv^~}Xi4titkI$xII&!VW}K@2==96a6-m(7v6HpLmW zmGCj)V@6WbRp`4HAs39+N8rfxM%HcBx3=%Aw#yj9Od{)wqzjE*3QP&fsM|aA8vgc5 z{h_NFcmtg0~v?lm1mO8l0_RIfUBK_arhzfB)y%drc zW8yYWa7Qm{7nsNUXf=D^t{mO_Q}+c_VE04Zo)+yXab+ihF&<>~@V(LQo_w_bD;@iP z|GfLko$7@NG7i_KKlUJ~zM;e+Dx*BuFZh3d{qF^kdmHp-B6ipRqe=VU-%J(4IlU1; zJJJtEW-JB^io+NPz~+I*;Vx8b;M;<+T1O=?QTXly;(%)k2w~PMQvO(;kUFhA;Q6*o zQuwri1P36xHm>u)WA9)^3=~*8&fd<-XCN@i{AWKFDx>T9Pzo(bZIPoAcOF}I00NZ< z8DI^6-z-N(w&`13n^dryc9^cgsQy2%Kp3%^oK{$U_WYD(KPH3-DS_FTctIHb8V|6R zH3Lp^-hQ<4UyNMZNsJh!nuFEo*6#lCF&k{L+(rF2iFD>ZSM#>e)ADOXiJEsMmBb!@ z=tx#cB+vgvEY(x;MHLd8KvirLm{cc^c*QA&=ags0xWE_h=l$8*-Wf37@#*BGv^z_G zm-7Ao)90HZBuh=!&9?Y{ARXjS1e3S(z$x+`n4kK@3&P7_^gye&X$H2G&yd)N9}KT+ zd17*}Rrj}Q2QU#7fzX!SzmC9Z~-1){>wEnp?h-Dd|B$2pMC(>fXs}~C8th+*f=M1L^%9Q zyO3IS2fs*Q3RJ&?)`^tPpk4vmx=m{vrZ4m<|5lS_Gpv+D^19espyul&)=vy01BZPl z6srd9stiG_>h>-`B#~7c8eGVx$;0W@>l$tnzadnA0aR2l- zJO@&n(tT=w6ANGfNeAv-@*pP@A-@c8Dm*vlF;dmpHOyy*oD`N7QSXO?(}eCD$mu#f z2UF1RogmBeI&P;jvC-NO0l1aTe4^Tzd# z>c`I^i{4zW3UM*9nf$W8I#Kv^`E9{=@?YvR)C7#-Pd;V;smC%^9~D$ie4Ga}QUjK8 z@|f&HxvP-Ah(hGc?n*~0w`bHF8H@KJ%^O@@8`ciV zkMUDrI6r5Vor4T$Viv?P-HLT?pdqdxDAX$A<+|KI`mjCVi|Nn8|`zm!f z-)#B-;D!4BR92ux_b#lQcybBUPjVvii4U?upl(Yc3#Y#Y2(<2i?n3I}FVKzww>92I z{J3pHAW17U10~jH&^B@VHq%Q@oZ_rXeH3Lh;u*0z1F9JGGvcvv3q5=F-?;S;Ot7yy zbHg@jF`cyS>OqGYl>%0n(&jc;w)emi4r)tFg(J^+-yL2ZNE4QCY>nV}M9cE{awmn? zZO|QAGEm@;t=)}!Kn3Mq(#jS%NjBb#RSGlIvcx^s-iS}M8hqnNA1EHMNJ;i+nVfB& z_f6!ZESy%cB$RnwKTd5I-qSE9+en+!-Fd%)=HUYnEGsF1wn*b=1;Sk$mp~xeMu$G+ z8PXv<>X$v^tyic|HM#sHW|n+-9U76 z`#Dw}c5M7LAlNW~6^p7*r-djRKlR3F|4*UDMo9Q2Y5vbX{y!B62~e*a>2zHFy&n1R zpWLq@Z0h>ekyTwJfPywOruL^#O$)N@ZS{fW|XZ?&^>6eV`{JhB9ASJ82?5$EZ8xzK}N0 zlsaRO01+!G6Oh8*3p}N)PT+VEc&%gLz`um^FQ-2S5(@5oNyRMKu#$bXqoAnMph0{u zM)3SxM}QP#j-cf3gBi{wU=jZQKmg1#e(&Px_fg|nZcpx}c(Vw$AbG*YHQ?(m4OPTg zE;Qmyijd`preV_}J*IUDOJrx#n zGQPbHc$H4@(+|`I5_&VPL14~V|)}!jhU=i**ywt1;|fXx#m5H#tCD@J(BmEfsq7bxqj`baFa?AgghQHr z`PK)?j8~;P7*dEbf>}|L=xEAG`yFzz_MiW_?o=V&RIXJ?(A3+;g0HL@)ZE2JtX^lF zQ2O0GP%LADq@&0pjR%hzF#znfQa_cmFqml#2~U9+G^xvv}g2&$e5M%L(Q=RU}=f2a6jx$z$E z)(lCw+sJKIr2=ZwrK=`B=6?lQtheLXumFky=LPm4%>b4f3e%`${t^NrndOIias8S| zKGp8Ev4UO%>Ve^=XW#z7Q=QQ66MYY2?*rw57T{0Np&(0M(AdMmRe}HXZ~QPg9;B{L zu+D$R^9B*944|?W5I+HMp_l8;#jF-Uc(8y=fK4c(A$WCr;cGJ%dVWEvcr_5CHi2(| z2(-+VZq)SXCF=#izF{8B6x@O8=IWJrqxZzBp!8rQ7Wf6;<$n3Lk{Mv!yF)40@1vL_ z_2jH37jmcn5tidK$)h)xEL35rG6n9)l8dUj0<_5@3sqFvvn}qK-B0F+E3uuUU1~UAF@~o z&Lo8tru+aPC0E~>oQ;%|&NU3f=BGxc_+w|8`|kC;FfOM-_KhXjLusKpwzL5W-D&`s zj_CT?5lZWhvg0f(?D#e1!t)>%Bw8VT5y?%}kE=rJnSH3pJGutwL;-CXL5h$P~bXWP}L z#?9a+IQ^bw;oR2PL`TfU30vCSaV2QX@|pjYlw+N@Zb0Hjg+ zEGXYqA33fLzqM>v8IFf&LM>B-t3c80z3AF-ex~w9Y(rTJS=whV#@*E7Kj4p%ksR=s zm8CpbfOkDtSad}m2@8d{Fa~B>Vvh}&@Hx@~6$lmxt^O?dqldj4MfUU1B`5oW4C+%W z1(J8HRK87xViy@RCqQPEG}6|R@K@#M*qXOZH`kqRqPzfGvr5P^u1$IN2duOf@?0^y zY0J55CZAoH7z?(RN@2hRKsgdyFd&h6@*h;L)30YZmx0}g-*qoQ<1@rkj=jBJq7#zE z8;LCsqy%+fESY{Y3Z7(Y3@9t}K$Ynjdr!r{lXCE7T8kAADXR{=SOLlDz71&5b^$iD z5&v@sJWem*p3R_=O}Ap>WGBsE*R1L7M_OsVWF2a=f^qBiTI(HupwxN(h!g~Gt1;h_ z`-HSo4_(yDn?JZ0_Z@zu3je2@uVurH6_^6XL3Kq61<+d)ea6dhIt61`oF5@SFls}# z=GU4*@Cdh;cd;QWoW8A+XbX@8a+`l!BBEd_8a^>5ilS5(mlgSuCb z7ub-<^Kl}{)l`21*QM24P?)d`qclq|2lczrAwYezf$i&3*~9$|+`4PzNVNDGu_P09AJif_vjw zPJoFoNh!6sR^hNmk$jd<#C=L3@a>kqWM&Wphrca%2dwA!Sc_df&=W@mBf3(qw)8jl z2*@TD=n_m3e0puS!VB~;dlWKgC;($49;~nX5~CNCsDQW9$`ZmT4Z**JQ1P3M&D!@uB|Yktpj%SdI3aAnPgbAx-VYzEYTbIwMn zAt;r%dZ?f6EW?Nt zMpV63-b&n%ItK1tmdT#X%Y9W0DQ@R3B=7v9nvY_zf%hYhqkMS%KTa0{{Op3Hbv3D^ z#Ng#zCTx^4i?2H66ZP5zg1X1N_96=dU@oP4`v-lt{d;Eoe@FCHQAGiSS0rivIuf5D zr}PHyfs2Ry*?25`Hz2JrqcMP)!a^?~Qa#5fTm)uq@5fi>Af9ZH?k8?IIhPZR{VPKf zBm^}18TUra6@FWbBZ^O7^-;ye43XVI%gVpYu_|6Cb}qYw)~#0i(C6sL>gZjefp=>^>O`NP>&7c!e!ZhEb@}gaabW`o7o8t;Rp= zS9g9e5xRo2_irURnfooThFD~OQvJ3+-v|}f9gjfCjdlOWAIuu`KZ%q8XS+ql`&G%} zQ#@4z$xl%3u`t%GrJs|6AlGInAc`|CGTAz(^!B@05P#&cWuD&`3yEw0Ab9V|1*I`K zeGTXUTO>zEa_cIZDFfxikZ4E5MLBCQ8wSj-lOV)^$$|H04% zoX(1Ap!4B@VTdCbIguELrnxr49O^)C?6LJ?%5#RgMmSYy0&|g-mIcAh#Q1F~{5+ZJ znTFGzm%z*#QG{X!isPFpg=e!0-$4OZ_c>#q4e?Q`ZdM2w)^7;i(&k@SY=yWv^f&M7 z;+n*t7UK5-qZtV7`X~q-62n~3^@NT%XDKh|(6qqjj{#x*(5zT9$bdV#Ahod$6dbezKgbjYTLRXLYejt$AD$z@4Pmi z)%Z#v@~qY808mxm$}#GeJ)QjJ_QCndj~lg)5M!NT5|*|} zP`f9*rsFsR4f!B{Kkp*ObpN^RO|sPE@%Ts=W(dSZqnWAne=v}*CiagdsV+&j!kP0D3S z+SQlN_{UW)!KbbpEY%SBog9@GlvYS6!qM54Yu79Tjnq-BE7d>=J}(pMfRQ5&RJC6x z1GRUMFgMdL0Qu2RrPQ0a1hNPn*VkEYkv)rXmwkeq!Fe#)HseKAuige=->bQwk5+}1 zvZ}%R*2OtMBX`)~^4}(>gfl2j*oPL>K?>)$Ov|LTVKQu-Ci|~G&=*1c2DWkaNi*d& zYZ&p`590 zW3c41Mu6LJHGltOzM4ru$`kd3sRYn5lsjjW`(9mvie>$a<-Q6Sj*v*X0hM>=2?Qh1 z(EkEGuye?289$W4BpyP=-_2M?0~(g3YbFFgIlRqWroi4IbBtCS8b({OA)irV6^(n zgd53=Cm|*&rgv%rbaJw*3@Hj2Qi4}bBxe_(L-l`}abo5Bc8w{?6_liEl z5Ae5M`FUMbO1+3U>%pvPw)4_O(5z&XLld>(kaQy~i@y`=$|Fkcfc-xTwO^kZC9#rgfrTv&9TL9@CNEQmdk-JcJs_4_1pA zR-8@1g_yiW^-0IpCtk41J)OQh8_dnXk;{WLAsZiPM@vg6ppz~NK9x0>Jz*x58T7*hVRIE-&)ECF*8+pX z@$I*C{r4+Ju0s{7b}S-nJTGhR)^$pt3RxvRHBxPD;pnC4Y4xXqg1HP;k7>AzYphBQ zkH`47NjEtR6``)~3Kf%-yMX$l#^%97&5oj&#{1z6bt>%zuyq;m?vYthQ zLovWJnD~}Lg>jcs8IwLOwC)A;NxKzx-lk1KaFziNs5OZ_;;8H<>mBym13{fn*I;v` zD?r>fG9M53r6yuh3FHR?hiz;_>kDQc@KhfuTB+0Nl-T=ugbu9ixp?qcydRa0V}QGG z3vshN6;p=U{3z6serCqNvFtUd%RmCn!QX;e; z?yjlU7wYP5y;JMxG`oLNItB$GYFC10fo@?=;)naiukWT!T&1r_XcgI&@+8Dc`zQH0 z>eyM+XKCs$2KIxrP!&<1M*sv$ajY9OM-_e;^-=r71VU{wl#9!qB^Cv$sHlk;7`)!% zq&x03{G;Ye!sWy7BpCXg1|-c}Yth;Trg$vHV4?#`Xde4hV1FTLcOWKC+m=19#8;F| z@Wvnx?=a3=sRBpb8kc#t)7MWp*KfD}0}z~k!8OJ5FQ8Bo@*WJ(HZU(~H(q@MS3R=d zJk@fMfU$A%PPp;x4aCOFHxZgEmnlf1taq?=xMdLhB4pqLdvKqM9oAzN_(v|8qO-KQ z_UJkWa%sH||441ch92I={Y>ldmD4(_%IgK=C4Y2q$R(TTwJ9~%3tbsPXz_)4f*l$ zWIfw73o!j_`v!1hDyP5nhPXs<+9fXEzLQmLt$AIt6RCBBhEB1*5I0N;9LvSZ`cFVw5wHK2wMn}KAN$)W* z7>uQxz_t|ea2h_MC$DykBUAaS1C6Ic?8Bmn^3RN`&Mh+tpzxqyB^Wui0}xYotUHc7 z)7#QCf6++d$5F&P!-oL}09SbOTI{hDswIoLOBy^ZR#fMM>otwyl>Si?Rtk^ zsWd;GdryA*!rI-pHb*q(&RH^-=JJva{xFc8UZl{PSXbk%~@^A*LqD;?ffvi~?*{HGx zv*1T3n%(2C-r+|z^!i)M;x1cNU1(L?4{37@!|7k4;GY_QNiRA2x~uQb^`hYRgR<`D zd?sq)*09tJ9q)w$;E6n;BP$kHac4o6y$4{kw`$)mDY^ELtk&OQ?xARocdKwQN8W1w}JTB#6Edg!zg!9r|$4qB{}A8BPIS z+GC6OOUCyef;c=n(T{fn+i+ta;6+dg?DVGeQjIfyP+(F>NR<$M`Ud z^xHc<>PyJ}c2&{|<8~CwH9hWu%ZL<^$b`;ZotnJx7cFJYyqF~Ekd+B{3bBO;Ljf;} zj%csTif#b$>jkrxK~Ae?4*QY1ZYy!wbRvuA8c&st!DGFf%cw?t8Y7m;Q6}!3cWWh^C{MMSeJvV{ zkvZ%Zh{Sr6n2KwttJBKg3DF;w&ez%Kwwx)nXAD;qV2<*_zaE@g-;YscecEo!bB`DK zp~G&@Zt8FU7A=fIJt09nS4svVz18A$@)3a+oc#0Lfhw?ndqw!ceWjEH{6q1Iuu zPgA`FHbNs=_Zb&MogF>5&<#)j}{ z_V{*t6iAG4qew8+yY|#;-*rc@nBdLs%%Idx1`K^`Nd3!hAbUP4*(SznZk`R+7op<;QydNi!Rr1PbZ z#Eg}i-0P5zqm*3wm9APAEXqw(@S`8!T^PWBpY8WKeEJ;ibYSgUB{f)enHdqSI~0b< zdo}8rbz z1tPP3gbNDLWcgtcKK3#z#B8~8rWL%?u_D~wJlA=N94|bpx)^7*Db&{zUq|X$ha(lz zQyZQ~%kS+uk&bYqV_Gcl(Rx)~{5crCS%+5Ouk zVlJAU&u))G;N`rtf$mlHpfA;sXEwOcvwEkYSVmOHuMH8Qipo!u_utd?XZ{qu5QbgW zILExn2(qD8XxrFd5R8S-%IQ8pvr~Wvvs;e7&^au36;+H;G=>dWKh+lqP zo63Yd7|C$*HFc$0;e|`Q5Tn?cLJ zxXAeywemcXa;!?OE+v9lXK&s=AV5bxZiE7eX`=r<+t;+E+TzZkE#4m?Nq-hDqz zTvEOfYz^!VB4Wkzo4oZq^A6V{2j`kI@9dw>tTeM_admnFarGiSO%{NR3JM ziBQH$slLtqkKqa`J0fby9STWRJL5K7qAnY!^Dd<93Q-{p;q+dmoOC#rvlQ0SQ(!=3 zu&`1$WQ2l~KfvOtk=&4@_F3Ab!uzQE$ z975AiP^{06^uf%LnQQ7U_002U8v`&u5so5cuT>(ar0k0mr}vs`?4wmjv_?I6Y$w0Q zO=}C1W!s2{=VEgnNk))ShOU2&GiCiPby*})g#^RIkwlEac8l({aj`spb<9zhF{g1! zZUqGT vUH^(CgV~>v(A|tb0CBJfHMqT+yFu29G*x#ur{Vhx{CXoI{i^7trpNyWuL_^- literal 0 HcmV?d00001