Commit 03bb378f authored by LDOUBLEV's avatar LDOUBLEV
Browse files

fix TRT8 core bug

parents a2a12fe4 2e9abcb9
#!/bin/bash
# 提供可稳定复现性能的脚本,默认在标准docker环境内py37执行: paddlepaddle/paddle:latest-gpu-cuda10.1-cudnn7 paddle=2.1.2 py=37 # 提供可稳定复现性能的脚本,默认在标准docker环境内py37执行: paddlepaddle/paddle:latest-gpu-cuda10.1-cudnn7 paddle=2.1.2 py=37
# 执行目录: ./PaddleOCR # 执行目录: ./PaddleOCR
# 1 安装该模型需要的依赖 (如需开启优化策略请注明) # 1 安装该模型需要的依赖 (如需开启优化策略请注明)
python3.7 -m pip install -r requirements.txt python -m pip install -r requirements.txt
# 2 拷贝该模型需要数据、预训练模型 # 2 拷贝该模型需要数据、预训练模型
wget -c -p ./tain_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015.tar && cd train_data && tar xf icdar2015.tar && cd ../ wget -P ./train_data/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/test/icdar2015.tar && cd train_data && tar xf icdar2015.tar && cd ../
wget -c -p ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_pretrained.pdparams wget -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_pretrained.pdparams
wget -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet18_vd_pretrained.pdparams
wget -P ./pretrain_models/ https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_ssld_pretrained.pdparams
# 3 批量运行(如不方便批量,1,2需放到单个模型中) # 3 批量运行(如不方便批量,1,2需放到单个模型中)
model_mode_list=(det_res18_db_v2.0 det_r50_vd_east) model_mode_list=(det_res18_db_v2.0 det_r50_vd_east det_r50_vd_pse)
fp_item_list=(fp32) fp_item_list=(fp32)
bs_list=(8 16) bs_list=(8 16)
for model_mode in ${model_mode_list[@]}; do for model_mode in ${model_mode_list[@]}; do
...@@ -15,11 +18,13 @@ for model_mode in ${model_mode_list[@]}; do ...@@ -15,11 +18,13 @@ for model_mode in ${model_mode_list[@]}; do
for bs_item in ${bs_list[@]}; do for bs_item in ${bs_list[@]}; do
echo "index is speed, 1gpus, begin, ${model_name}" echo "index is speed, 1gpus, begin, ${model_name}"
run_mode=sp run_mode=sp
CUDA_VISIBLE_DEVICES=0 bash benchmark/run_benchmark_det.sh ${run_mode} ${bs_item} ${fp_item} 10 ${model_mode} # (5min) log_name=ocr_${model_mode}_${run_mode}_bs${bs_item}_${fp_item}
CUDA_VISIBLE_DEVICES=0 bash benchmark/run_benchmark_det.sh ${run_mode} ${bs_item} ${fp_item} 1 ${model_mode} | tee ${log_path}/${log_name}_speed_1gpus 2>&1 # (5min)
sleep 60 sleep 60
echo "index is speed, 8gpus, run_mode is multi_process, begin, ${model_name}" echo "index is speed, 8gpus, run_mode is multi_process, begin, ${model_name}"
run_mode=mp run_mode=mp
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 bash benchmark/run_benchmark_det.sh ${run_mode} ${bs_item} ${fp_item} 10 ${model_mode} log_name=ocr_${model_mode}_${run_mode}_bs${bs_item}_${fp_item}
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 bash benchmark/run_benchmark_det.sh ${run_mode} ${bs_item} ${fp_item} 2 ${model_mode} | tee ${log_path}/${log_name}_speed_8gpus8p 2>&1
sleep 60 sleep 60
done done
done done
......
...@@ -90,7 +90,7 @@ Optimizer: ...@@ -90,7 +90,7 @@ Optimizer:
PostProcess: PostProcess:
name: DistillationDBPostProcess name: DistillationDBPostProcess
model_name: ["Student", "Student2"] model_name: ["Student"]
key: head_out key: head_out
thresh: 0.3 thresh: 0.3
box_thresh: 0.6 box_thresh: 0.6
......
...@@ -8,7 +8,7 @@ Global: ...@@ -8,7 +8,7 @@ Global:
# evaluation is run every 5000 iterations after the 4000th iteration # evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [4000, 5000] eval_batch_step: [4000, 5000]
cal_metric_during_train: False cal_metric_during_train: False
pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained/ pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained
checkpoints: checkpoints:
save_inference_dir: save_inference_dir:
use_visualdl: False use_visualdl: False
......
...@@ -8,7 +8,7 @@ Global: ...@@ -8,7 +8,7 @@ Global:
# evaluation is run every 5000 iterations after the 4000th iteration # evaluation is run every 5000 iterations after the 4000th iteration
eval_batch_step: [4000, 5000] eval_batch_step: [4000, 5000]
cal_metric_during_train: False cal_metric_during_train: False
pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained/ pretrained_model: ./pretrain_models/ResNet50_vd_ssld_pretrained
checkpoints: checkpoints:
save_inference_dir: save_inference_dir:
use_visualdl: False use_visualdl: False
......
...@@ -62,8 +62,7 @@ Loss: ...@@ -62,8 +62,7 @@ Loss:
weight: 0.05 weight: 0.05
num_classes: 6625 num_classes: 6625
feat_dim: 96 feat_dim: 96
init_center: false center_file_path:
center_file_path: "./train_center.pkl"
# you can also try to add ace loss on your own dataset # you can also try to add ace loss on your own dataset
# - ACELoss: # - ACELoss:
# weight: 0.1 # weight: 0.1
......
Global: Global:
use_gpu: true use_gpu: true
epoch_num: 50 epoch_num: 400
log_smooth_window: 20 log_smooth_window: 20
print_batch_step: 5 print_batch_step: 5
save_model_dir: ./output/table_mv3/ save_model_dir: ./output/table_mv3/
save_epoch_step: 5 save_epoch_step: 3
# evaluation is run every 400 iterations after the 0th iteration # evaluation is run every 400 iterations after the 0th iteration
eval_batch_step: [0, 400] eval_batch_step: [0, 400]
cal_metric_during_train: True cal_metric_during_train: True
...@@ -12,18 +12,17 @@ Global: ...@@ -12,18 +12,17 @@ Global:
checkpoints: checkpoints:
save_inference_dir: save_inference_dir:
use_visualdl: False use_visualdl: False
infer_img: doc/imgs_words/ch/word_1.jpg infer_img: doc/table/table.jpg
# for data or label process # for data or label process
character_dict_path: ppocr/utils/dict/table_structure_dict.txt character_dict_path: ppocr/utils/dict/table_structure_dict.txt
character_type: en character_type: en
max_text_length: 100 max_text_length: 100
max_elem_length: 500 max_elem_length: 800
max_cell_num: 500 max_cell_num: 500
infer_mode: False infer_mode: False
process_total_num: 0 process_total_num: 0
process_cut_num: 0 process_cut_num: 0
Optimizer: Optimizer:
name: Adam name: Adam
beta1: 0.9 beta1: 0.9
...@@ -41,13 +40,15 @@ Architecture: ...@@ -41,13 +40,15 @@ Architecture:
Backbone: Backbone:
name: MobileNetV3 name: MobileNetV3
scale: 1.0 scale: 1.0
model_name: small model_name: large
disable_se: True
Head: Head:
name: TableAttentionHead name: TableAttentionHead
hidden_size: 256 hidden_size: 256
l2_decay: 0.00001 l2_decay: 0.00001
loc_type: 2 loc_type: 2
max_text_length: 100
max_elem_length: 800
max_cell_num: 500
Loss: Loss:
name: TableAttentionLoss name: TableAttentionLoss
......
...@@ -44,7 +44,8 @@ public: ...@@ -44,7 +44,8 @@ public:
const int &gpu_id, const int &gpu_mem, const int &gpu_id, const int &gpu_mem,
const int &cpu_math_library_num_threads, const int &cpu_math_library_num_threads,
const bool &use_mkldnn, const string &label_path, const bool &use_mkldnn, const string &label_path,
const bool &use_tensorrt, const std::string &precision) { const bool &use_tensorrt, const std::string &precision,
const int &rec_batch_num) {
this->use_gpu_ = use_gpu; this->use_gpu_ = use_gpu;
this->gpu_id_ = gpu_id; this->gpu_id_ = gpu_id;
this->gpu_mem_ = gpu_mem; this->gpu_mem_ = gpu_mem;
...@@ -52,6 +53,7 @@ public: ...@@ -52,6 +53,7 @@ public:
this->use_mkldnn_ = use_mkldnn; this->use_mkldnn_ = use_mkldnn;
this->use_tensorrt_ = use_tensorrt; this->use_tensorrt_ = use_tensorrt;
this->precision_ = precision; this->precision_ = precision;
this->rec_batch_num_ = rec_batch_num;
this->label_list_ = Utility::ReadDict(label_path); this->label_list_ = Utility::ReadDict(label_path);
this->label_list_.insert(this->label_list_.begin(), this->label_list_.insert(this->label_list_.begin(),
...@@ -64,7 +66,7 @@ public: ...@@ -64,7 +66,7 @@ public:
// Load Paddle inference model // Load Paddle inference model
void LoadModel(const std::string &model_dir); void LoadModel(const std::string &model_dir);
void Run(cv::Mat &img, std::vector<double> *times); void Run(std::vector<cv::Mat> img_list, std::vector<double> *times);
private: private:
std::shared_ptr<Predictor> predictor_; std::shared_ptr<Predictor> predictor_;
...@@ -82,10 +84,12 @@ private: ...@@ -82,10 +84,12 @@ private:
bool is_scale_ = true; bool is_scale_ = true;
bool use_tensorrt_ = false; bool use_tensorrt_ = false;
std::string precision_ = "fp32"; std::string precision_ = "fp32";
int rec_batch_num_ = 6;
// pre-process // pre-process
CrnnResizeImg resize_op_; CrnnResizeImg resize_op_;
Normalize normalize_op_; Normalize normalize_op_;
Permute permute_op_; PermuteBatch permute_op_;
// post-process // post-process
PostProcessor post_processor_; PostProcessor post_processor_;
......
...@@ -44,6 +44,11 @@ public: ...@@ -44,6 +44,11 @@ public:
virtual void Run(const cv::Mat *im, float *data); virtual void Run(const cv::Mat *im, float *data);
}; };
class PermuteBatch {
public:
virtual void Run(const std::vector<cv::Mat> imgs, float *data);
};
class ResizeImgType0 { class ResizeImgType0 {
public: public:
virtual void Run(const cv::Mat &img, cv::Mat &resize_img, int max_size_len, virtual void Run(const cv::Mat &img, cv::Mat &resize_img, int max_size_len,
......
...@@ -50,6 +50,9 @@ public: ...@@ -50,6 +50,9 @@ public:
static cv::Mat GetRotateCropImage(const cv::Mat &srcimage, static cv::Mat GetRotateCropImage(const cv::Mat &srcimage,
std::vector<std::vector<int>> box); std::vector<std::vector<int>> box);
static std::vector<int> argsort(const std::vector<float>& array);
}; };
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
...@@ -34,10 +34,10 @@ PaddleOCR模型部署。 ...@@ -34,10 +34,10 @@ PaddleOCR模型部署。
* 首先需要从opencv官网上下载在Linux环境下源码编译的包,以opencv3.4.7为例,下载命令如下。 * 首先需要从opencv官网上下载在Linux环境下源码编译的包,以opencv3.4.7为例,下载命令如下。
``` ```bash
cd deploy/cpp_infer cd deploy/cpp_infer
wget https://github.com/opencv/opencv/archive/3.4.7.tar.gz wget https://paddleocr.bj.bcebos.com/libs/opencv/opencv-3.4.7.tar.gz
tar -xf 3.4.7.tar.gz tar -xf opencv-3.4.7.tar.gz
``` ```
最终可以在当前目录下看到`opencv-3.4.7/`的文件夹。 最终可以在当前目录下看到`opencv-3.4.7/`的文件夹。
...@@ -45,12 +45,13 @@ tar -xf 3.4.7.tar.gz ...@@ -45,12 +45,13 @@ tar -xf 3.4.7.tar.gz
* 编译opencv,设置opencv源码路径(`root_path`)以及安装路径(`install_path`)。进入opencv源码路径下,按照下面的方式进行编译。 * 编译opencv,设置opencv源码路径(`root_path`)以及安装路径(`install_path`)。进入opencv源码路径下,按照下面的方式进行编译。
```shell ```shell
root_path=your_opencv_root_path root_path="your_opencv_root_path"
install_path=${root_path}/opencv3 install_path=${root_path}/opencv3
build_dir=${root_path}/build
rm -rf build rm -rf ${build_dir}
mkdir build mkdir ${build_dir}
cd build cd ${build_dir}
cmake .. \ cmake .. \
-DCMAKE_INSTALL_PREFIX=${install_path} \ -DCMAKE_INSTALL_PREFIX=${install_path} \
...@@ -74,6 +75,11 @@ make -j ...@@ -74,6 +75,11 @@ make -j
make install make install
``` ```
也可以直接修改`tools/build_opencv.sh`的内容,然后直接运行下面的命令进行编译。
```shell
sh tools/build_opencv.sh
```
其中`root_path`为下载的opencv源码路径,`install_path`为opencv的安装路径,`make install`完成之后,会在该文件夹下生成opencv头文件和库文件,用于后面的OCR代码编译。 其中`root_path`为下载的opencv源码路径,`install_path`为opencv的安装路径,`make install`完成之后,会在该文件夹下生成opencv头文件和库文件,用于后面的OCR代码编译。
...@@ -233,12 +239,12 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir ...@@ -233,12 +239,12 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir
--image_dir=../../doc/imgs/12.jpg --image_dir=../../doc/imgs/12.jpg
``` ```
更多参数如下: 更多支持的可调节参数解释如下:
- 通用参数 - 通用参数
|参数名称|类型|默认参数|意义| |参数名称|类型|默认参数|意义|
| --- | --- | --- | --- | | :---: | :---: | :---: | :---: |
|use_gpu|bool|false|是否使用GPU| |use_gpu|bool|false|是否使用GPU|
|gpu_id|int|0|GPU id,使用GPU时有效| |gpu_id|int|0|GPU id,使用GPU时有效|
|gpu_mem|int|4000|申请的GPU内存| |gpu_mem|int|4000|申请的GPU内存|
...@@ -248,7 +254,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir ...@@ -248,7 +254,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir
- 检测模型相关 - 检测模型相关
|参数名称|类型|默认参数|意义| |参数名称|类型|默认参数|意义|
| --- | --- | --- | --- | | :---: | :---: | :---: | :---: |
|det_model_dir|string|-|检测模型inference model地址| |det_model_dir|string|-|检测模型inference model地址|
|max_side_len|int|960|输入图像长宽大于960时,等比例缩放图像,使得图像最长边为960| |max_side_len|int|960|输入图像长宽大于960时,等比例缩放图像,使得图像最长边为960|
|det_db_thresh|float|0.3|用于过滤DB预测的二值化图像,设置为0.-0.3对结果影响不明显| |det_db_thresh|float|0.3|用于过滤DB预测的二值化图像,设置为0.-0.3对结果影响不明显|
...@@ -260,7 +266,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir ...@@ -260,7 +266,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir
- 方向分类器相关 - 方向分类器相关
|参数名称|类型|默认参数|意义| |参数名称|类型|默认参数|意义|
| --- | --- | --- | --- | | :---: | :---: | :---: | :---: |
|use_angle_cls|bool|false|是否使用方向分类器| |use_angle_cls|bool|false|是否使用方向分类器|
|cls_model_dir|string|-|方向分类器inference model地址| |cls_model_dir|string|-|方向分类器inference model地址|
|cls_thresh|float|0.9|方向分类器的得分阈值| |cls_thresh|float|0.9|方向分类器的得分阈值|
...@@ -268,7 +274,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir ...@@ -268,7 +274,7 @@ CUDNN_LIB_DIR=/your_cudnn_lib_dir
- 识别模型相关 - 识别模型相关
|参数名称|类型|默认参数|意义| |参数名称|类型|默认参数|意义|
| --- | --- | --- | --- | | :---: | :---: | :---: | :---: |
|rec_model_dir|string|-|识别模型inference model地址| |rec_model_dir|string|-|识别模型inference model地址|
|char_list_file|string|../../ppocr/utils/ppocr_keys_v1.txt|字典文件| |char_list_file|string|../../ppocr/utils/ppocr_keys_v1.txt|字典文件|
......
...@@ -17,10 +17,10 @@ PaddleOCR model deployment. ...@@ -17,10 +17,10 @@ PaddleOCR model deployment.
* First of all, you need to download the source code compiled package in the Linux environment from the opencv official website. Taking opencv3.4.7 as an example, the download command is as follows. * First of all, you need to download the source code compiled package in the Linux environment from the opencv official website. Taking opencv3.4.7 as an example, the download command is as follows.
``` ```bash
cd deploy/cpp_infer cd deploy/cpp_infer
wget https://github.com/opencv/opencv/archive/3.4.7.tar.gz wget https://paddleocr.bj.bcebos.com/libs/opencv/opencv-3.4.7.tar.gz
tar -xf 3.4.7.tar.gz tar -xf opencv-3.4.7.tar.gz
``` ```
Finally, you can see the folder of `opencv-3.4.7/` in the current directory. Finally, you can see the folder of `opencv-3.4.7/` in the current directory.
......
...@@ -61,7 +61,7 @@ DEFINE_string(cls_model_dir, "", "Path of cls inference model."); ...@@ -61,7 +61,7 @@ DEFINE_string(cls_model_dir, "", "Path of cls inference model.");
DEFINE_double(cls_thresh, 0.9, "Threshold of cls_thresh."); DEFINE_double(cls_thresh, 0.9, "Threshold of cls_thresh.");
// recognition related // recognition related
DEFINE_string(rec_model_dir, "", "Path of rec inference model."); DEFINE_string(rec_model_dir, "", "Path of rec inference model.");
DEFINE_int32(rec_batch_num, 1, "rec_batch_num."); DEFINE_int32(rec_batch_num, 6, "rec_batch_num.");
DEFINE_string(char_list_file, "../../ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary."); DEFINE_string(char_list_file, "../../ppocr/utils/ppocr_keys_v1.txt", "Path of dictionary.");
...@@ -146,8 +146,9 @@ int main_rec(std::vector<cv::String> cv_all_img_names) { ...@@ -146,8 +146,9 @@ int main_rec(std::vector<cv::String> cv_all_img_names) {
CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id, CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id,
FLAGS_gpu_mem, FLAGS_cpu_threads, FLAGS_gpu_mem, FLAGS_cpu_threads,
FLAGS_enable_mkldnn, char_list_file, FLAGS_enable_mkldnn, char_list_file,
FLAGS_use_tensorrt, FLAGS_precision); FLAGS_use_tensorrt, FLAGS_precision, FLAGS_rec_batch_num);
std::vector<cv::Mat> img_list;
for (int i = 0; i < cv_all_img_names.size(); ++i) { for (int i = 0; i < cv_all_img_names.size(); ++i) {
LOG(INFO) << "The predict img: " << cv_all_img_names[i]; LOG(INFO) << "The predict img: " << cv_all_img_names[i];
...@@ -156,14 +157,13 @@ int main_rec(std::vector<cv::String> cv_all_img_names) { ...@@ -156,14 +157,13 @@ int main_rec(std::vector<cv::String> cv_all_img_names) {
std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << endl; std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << endl;
exit(1); exit(1);
} }
img_list.push_back(srcimg);
}
std::vector<double> rec_times; std::vector<double> rec_times;
rec.Run(srcimg, &rec_times); rec.Run(img_list, &rec_times);
time_info[0] += rec_times[0]; time_info[0] += rec_times[0];
time_info[1] += rec_times[1]; time_info[1] += rec_times[1];
time_info[2] += rec_times[2]; time_info[2] += rec_times[2];
}
if (FLAGS_benchmark) { if (FLAGS_benchmark) {
AutoLogger autolog("ocr_rec", AutoLogger autolog("ocr_rec",
...@@ -171,7 +171,7 @@ int main_rec(std::vector<cv::String> cv_all_img_names) { ...@@ -171,7 +171,7 @@ int main_rec(std::vector<cv::String> cv_all_img_names) {
FLAGS_use_tensorrt, FLAGS_use_tensorrt,
FLAGS_enable_mkldnn, FLAGS_enable_mkldnn,
FLAGS_cpu_threads, FLAGS_cpu_threads,
1, FLAGS_rec_batch_num,
"dynamic", "dynamic",
FLAGS_precision, FLAGS_precision,
time_info, time_info,
...@@ -209,7 +209,7 @@ int main_system(std::vector<cv::String> cv_all_img_names) { ...@@ -209,7 +209,7 @@ int main_system(std::vector<cv::String> cv_all_img_names) {
CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id, CRNNRecognizer rec(FLAGS_rec_model_dir, FLAGS_use_gpu, FLAGS_gpu_id,
FLAGS_gpu_mem, FLAGS_cpu_threads, FLAGS_gpu_mem, FLAGS_cpu_threads,
FLAGS_enable_mkldnn, char_list_file, FLAGS_enable_mkldnn, char_list_file,
FLAGS_use_tensorrt, FLAGS_precision); FLAGS_use_tensorrt, FLAGS_precision, FLAGS_rec_batch_num);
for (int i = 0; i < cv_all_img_names.size(); ++i) { for (int i = 0; i < cv_all_img_names.size(); ++i) {
LOG(INFO) << "The predict img: " << cv_all_img_names[i]; LOG(INFO) << "The predict img: " << cv_all_img_names[i];
...@@ -228,19 +228,22 @@ int main_system(std::vector<cv::String> cv_all_img_names) { ...@@ -228,19 +228,22 @@ int main_system(std::vector<cv::String> cv_all_img_names) {
time_info_det[1] += det_times[1]; time_info_det[1] += det_times[1];
time_info_det[2] += det_times[2]; time_info_det[2] += det_times[2];
cv::Mat crop_img; std::vector<cv::Mat> img_list;
for (int j = 0; j < boxes.size(); j++) { for (int j = 0; j < boxes.size(); j++) {
cv::Mat crop_img;
crop_img = Utility::GetRotateCropImage(srcimg, boxes[j]); crop_img = Utility::GetRotateCropImage(srcimg, boxes[j]);
if (cls != nullptr) { if (cls != nullptr) {
crop_img = cls->Run(crop_img); crop_img = cls->Run(crop_img);
} }
rec.Run(crop_img, &rec_times); img_list.push_back(crop_img);
}
rec.Run(img_list, &rec_times);
time_info_rec[0] += rec_times[0]; time_info_rec[0] += rec_times[0];
time_info_rec[1] += rec_times[1]; time_info_rec[1] += rec_times[1];
time_info_rec[2] += rec_times[2]; time_info_rec[2] += rec_times[2];
} }
}
if (FLAGS_benchmark) { if (FLAGS_benchmark) {
AutoLogger autolog_det("ocr_det", AutoLogger autolog_det("ocr_det",
FLAGS_use_gpu, FLAGS_use_gpu,
...@@ -257,7 +260,7 @@ int main_system(std::vector<cv::String> cv_all_img_names) { ...@@ -257,7 +260,7 @@ int main_system(std::vector<cv::String> cv_all_img_names) {
FLAGS_use_tensorrt, FLAGS_use_tensorrt,
FLAGS_enable_mkldnn, FLAGS_enable_mkldnn,
FLAGS_cpu_threads, FLAGS_cpu_threads,
1, FLAGS_rec_batch_num,
"dynamic", "dynamic",
FLAGS_precision, FLAGS_precision,
time_info_rec, time_info_rec,
......
...@@ -16,27 +16,48 @@ ...@@ -16,27 +16,48 @@
namespace PaddleOCR { namespace PaddleOCR {
void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) { void CRNNRecognizer::Run(std::vector<cv::Mat> img_list, std::vector<double> *times) {
cv::Mat srcimg; std::chrono::duration<float> preprocess_diff = std::chrono::steady_clock::now() - std::chrono::steady_clock::now();
img.copyTo(srcimg); std::chrono::duration<float> inference_diff = std::chrono::steady_clock::now() - std::chrono::steady_clock::now();
cv::Mat resize_img; std::chrono::duration<float> postprocess_diff = std::chrono::steady_clock::now() - std::chrono::steady_clock::now();
int img_num = img_list.size();
std::vector<float> width_list;
for (int i = 0; i < img_num; i++) {
width_list.push_back(float(img_list[i].cols) / img_list[i].rows);
}
std::vector<int> indices = Utility::argsort(width_list);
float wh_ratio = float(srcimg.cols) / float(srcimg.rows); for (int beg_img_no = 0; beg_img_no < img_num; beg_img_no += this->rec_batch_num_) {
auto preprocess_start = std::chrono::steady_clock::now(); auto preprocess_start = std::chrono::steady_clock::now();
this->resize_op_.Run(srcimg, resize_img, wh_ratio, this->use_tensorrt_); int end_img_no = min(img_num, beg_img_no + this->rec_batch_num_);
float max_wh_ratio = 0;
this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, for (int ino = beg_img_no; ino < end_img_no; ino ++) {
this->is_scale_); int h = img_list[indices[ino]].rows;
int w = img_list[indices[ino]].cols;
std::vector<float> input(1 * 3 * resize_img.rows * resize_img.cols, 0.0f); float wh_ratio = w * 1.0 / h;
max_wh_ratio = max(max_wh_ratio, wh_ratio);
}
std::vector<cv::Mat> norm_img_batch;
for (int ino = beg_img_no; ino < end_img_no; ino ++) {
cv::Mat srcimg;
img_list[indices[ino]].copyTo(srcimg);
cv::Mat resize_img;
this->resize_op_.Run(srcimg, resize_img, max_wh_ratio, this->use_tensorrt_);
this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->is_scale_);
norm_img_batch.push_back(resize_img);
}
this->permute_op_.Run(&resize_img, input.data()); int batch_width = int(ceilf(32 * max_wh_ratio)) - 1;
std::vector<float> input(this->rec_batch_num_ * 3 * 32 * batch_width, 0.0f);
this->permute_op_.Run(norm_img_batch, input.data());
auto preprocess_end = std::chrono::steady_clock::now(); auto preprocess_end = std::chrono::steady_clock::now();
preprocess_diff += preprocess_end - preprocess_start;
// Inference. // Inference.
auto input_names = this->predictor_->GetInputNames(); auto input_names = this->predictor_->GetInputNames();
auto input_t = this->predictor_->GetInputHandle(input_names[0]); auto input_t = this->predictor_->GetInputHandle(input_names[0]);
input_t->Reshape({1, 3, resize_img.rows, resize_img.cols}); input_t->Reshape({this->rec_batch_num_, 3, 32, batch_width});
auto inference_start = std::chrono::steady_clock::now(); auto inference_start = std::chrono::steady_clock::now();
input_t->CopyFromCpu(input.data()); input_t->CopyFromCpu(input.data());
this->predictor_->Run(); this->predictor_->Run();
...@@ -52,9 +73,11 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) { ...@@ -52,9 +73,11 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) {
output_t->CopyToCpu(predict_batch.data()); output_t->CopyToCpu(predict_batch.data());
auto inference_end = std::chrono::steady_clock::now(); auto inference_end = std::chrono::steady_clock::now();
inference_diff += inference_end - inference_start;
// ctc decode // ctc decode
auto postprocess_start = std::chrono::steady_clock::now(); auto postprocess_start = std::chrono::steady_clock::now();
for (int m = 0; m < predict_shape[0]; m++) {
std::vector<std::string> str_res; std::vector<std::string> str_res;
int argmax_idx; int argmax_idx;
int last_index = 0; int last_index = 0;
...@@ -64,11 +87,11 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) { ...@@ -64,11 +87,11 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) {
for (int n = 0; n < predict_shape[1]; n++) { for (int n = 0; n < predict_shape[1]; n++) {
argmax_idx = argmax_idx =
int(Utility::argmax(&predict_batch[n * predict_shape[2]], int(Utility::argmax(&predict_batch[(m * predict_shape[1] + n) * predict_shape[2]],
&predict_batch[(n + 1) * predict_shape[2]])); &predict_batch[(m * predict_shape[1] + n + 1) * predict_shape[2]]));
max_value = max_value =
float(*std::max_element(&predict_batch[n * predict_shape[2]], float(*std::max_element(&predict_batch[(m * predict_shape[1] + n) * predict_shape[2]],
&predict_batch[(n + 1) * predict_shape[2]])); &predict_batch[(m * predict_shape[1] + n + 1) * predict_shape[2]]));
if (argmax_idx > 0 && (!(n > 0 && argmax_idx == last_index))) { if (argmax_idx > 0 && (!(n > 0 && argmax_idx == last_index))) {
score += max_value; score += max_value;
...@@ -77,21 +100,23 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) { ...@@ -77,21 +100,23 @@ void CRNNRecognizer::Run(cv::Mat &img, std::vector<double> *times) {
} }
last_index = argmax_idx; last_index = argmax_idx;
} }
auto postprocess_end = std::chrono::steady_clock::now();
score /= count; score /= count;
if (isnan(score))
continue;
for (int i = 0; i < str_res.size(); i++) { for (int i = 0; i < str_res.size(); i++) {
std::cout << str_res[i]; std::cout << str_res[i];
} }
std::cout << "\tscore: " << score << std::endl; std::cout << "\tscore: " << score << std::endl;
}
std::chrono::duration<float> preprocess_diff = preprocess_end - preprocess_start; auto postprocess_end = std::chrono::steady_clock::now();
postprocess_diff += postprocess_end - postprocess_start;
}
times->push_back(double(preprocess_diff.count() * 1000)); times->push_back(double(preprocess_diff.count() * 1000));
std::chrono::duration<float> inference_diff = inference_end - inference_start;
times->push_back(double(inference_diff.count() * 1000)); times->push_back(double(inference_diff.count() * 1000));
std::chrono::duration<float> postprocess_diff = postprocess_end - postprocess_start;
times->push_back(double(postprocess_diff.count() * 1000)); times->push_back(double(postprocess_diff.count() * 1000));
} }
void CRNNRecognizer::LoadModel(const std::string &model_dir) { void CRNNRecognizer::LoadModel(const std::string &model_dir) {
// AnalysisConfig config; // AnalysisConfig config;
paddle_infer::Config config; paddle_infer::Config config;
......
...@@ -40,6 +40,17 @@ void Permute::Run(const cv::Mat *im, float *data) { ...@@ -40,6 +40,17 @@ void Permute::Run(const cv::Mat *im, float *data) {
} }
} }
void PermuteBatch::Run(const std::vector<cv::Mat> imgs, float *data) {
for (int j = 0; j < imgs.size(); j ++){
int rh = imgs[j].rows;
int rw = imgs[j].cols;
int rc = imgs[j].channels();
for (int i = 0; i < rc; ++i) {
cv::extractChannel(imgs[j], cv::Mat(rh, rw, CV_32FC1, data + (j * rc + i) * rh * rw), i);
}
}
}
void Normalize::Run(cv::Mat *im, const std::vector<float> &mean, void Normalize::Run(cv::Mat *im, const std::vector<float> &mean,
const std::vector<float> &scale, const bool is_scale) { const std::vector<float> &scale, const bool is_scale) {
double e = 1.0; double e = 1.0;
...@@ -95,6 +106,7 @@ void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, ...@@ -95,6 +106,7 @@ void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio,
float ratio = float(img.cols) / float(img.rows); float ratio = float(img.cols) / float(img.rows);
int resize_w, resize_h; int resize_w, resize_h;
if (ceilf(imgH * ratio) > imgW) if (ceilf(imgH * ratio) > imgW)
resize_w = imgW; resize_w = imgW;
else else
......
...@@ -147,4 +147,17 @@ cv::Mat Utility::GetRotateCropImage(const cv::Mat &srcimage, ...@@ -147,4 +147,17 @@ cv::Mat Utility::GetRotateCropImage(const cv::Mat &srcimage,
} }
} }
std::vector<int> Utility::argsort(const std::vector<float>& array)
{
const int array_len(array.size());
std::vector<int> array_index(array_len, 0);
for (int i = 0; i < array_len; ++i)
array_index[i] = i;
std::sort(array_index.begin(), array_index.end(),
[&array](int pos1, int pos2) {return (array[pos1] < array[pos2]); });
return array_index;
}
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
root_path="/paddle/PaddleOCR/deploy/cpp_infer/opencv-3.4.7"
install_path=${root_path}/opencv3
build_dir=${root_path}/build
rm -rf ${build_dir}
mkdir ${build_dir}
cd ${build_dir}
cmake .. \
-DCMAKE_INSTALL_PREFIX=${install_path} \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DWITH_IPP=OFF \
-DBUILD_IPP_IW=OFF \
-DWITH_LAPACK=OFF \
-DWITH_EIGEN=OFF \
-DCMAKE_INSTALL_LIBDIR=lib64 \
-DWITH_ZLIB=ON \
-DBUILD_ZLIB=ON \
-DWITH_JPEG=ON \
-DBUILD_JPEG=ON \
-DWITH_PNG=ON \
-DBUILD_PNG=ON \
-DWITH_TIFF=ON \
-DBUILD_TIFF=ON
make -j
make install
...@@ -12,12 +12,14 @@ ...@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "paddle_api.h" // NOLINT
#include <chrono> #include <chrono>
#include "paddle_api.h" // NOLINT
#include "paddle_place.h"
#include "cls_process.h" #include "cls_process.h"
#include "crnn_process.h" #include "crnn_process.h"
#include "db_post_process.h" #include "db_post_process.h"
#include "AutoLog/auto_log/lite_autolog.h"
using namespace paddle::lite_api; // NOLINT using namespace paddle::lite_api; // NOLINT
using namespace std; using namespace std;
...@@ -27,7 +29,7 @@ void NeonMeanScale(const float *din, float *dout, int size, ...@@ -27,7 +29,7 @@ void NeonMeanScale(const float *din, float *dout, int size,
const std::vector<float> mean, const std::vector<float> mean,
const std::vector<float> scale) { const std::vector<float> scale) {
if (mean.size() != 3 || scale.size() != 3) { if (mean.size() != 3 || scale.size() != 3) {
std::cerr << "[ERROR] mean or scale size must equal to 3\n"; std::cerr << "[ERROR] mean or scale size must equal to 3" << std::endl;
exit(1); exit(1);
} }
float32x4_t vmean0 = vdupq_n_f32(mean[0]); float32x4_t vmean0 = vdupq_n_f32(mean[0]);
...@@ -159,7 +161,8 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img, ...@@ -159,7 +161,8 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img,
std::vector<float> &rec_text_score, std::vector<float> &rec_text_score,
std::vector<std::string> charactor_dict, std::vector<std::string> charactor_dict,
std::shared_ptr<PaddlePredictor> predictor_cls, std::shared_ptr<PaddlePredictor> predictor_cls,
int use_direction_classify) { int use_direction_classify,
std::vector<double> *times) {
std::vector<float> mean = {0.5f, 0.5f, 0.5f}; std::vector<float> mean = {0.5f, 0.5f, 0.5f};
std::vector<float> scale = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f}; std::vector<float> scale = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f};
...@@ -169,7 +172,10 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img, ...@@ -169,7 +172,10 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img,
cv::Mat resize_img; cv::Mat resize_img;
int index = 0; int index = 0;
std::vector<double> time_info = {0, 0, 0};
for (int i = boxes.size() - 1; i >= 0; i--) { for (int i = boxes.size() - 1; i >= 0; i--) {
auto preprocess_start = std::chrono::steady_clock::now();
crop_img = GetRotateCropImage(srcimg, boxes[i]); crop_img = GetRotateCropImage(srcimg, boxes[i]);
if (use_direction_classify >= 1) { if (use_direction_classify >= 1) {
crop_img = RunClsModel(crop_img, predictor_cls); crop_img = RunClsModel(crop_img, predictor_cls);
...@@ -188,7 +194,9 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img, ...@@ -188,7 +194,9 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img,
auto *data0 = input_tensor0->mutable_data<float>(); auto *data0 = input_tensor0->mutable_data<float>();
NeonMeanScale(dimg, data0, resize_img.rows * resize_img.cols, mean, scale); NeonMeanScale(dimg, data0, resize_img.rows * resize_img.cols, mean, scale);
auto preprocess_end = std::chrono::steady_clock::now();
//// Run CRNN predictor //// Run CRNN predictor
auto inference_start = std::chrono::steady_clock::now();
predictor_crnn->Run(); predictor_crnn->Run();
// Get output and run postprocess // Get output and run postprocess
...@@ -196,8 +204,10 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img, ...@@ -196,8 +204,10 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img,
std::move(predictor_crnn->GetOutput(0))); std::move(predictor_crnn->GetOutput(0)));
auto *predict_batch = output_tensor0->data<float>(); auto *predict_batch = output_tensor0->data<float>();
auto predict_shape = output_tensor0->shape(); auto predict_shape = output_tensor0->shape();
auto inference_end = std::chrono::steady_clock::now();
// ctc decode // ctc decode
auto postprocess_start = std::chrono::steady_clock::now();
std::string str_res; std::string str_res;
int argmax_idx; int argmax_idx;
int last_index = 0; int last_index = 0;
...@@ -221,12 +231,25 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img, ...@@ -221,12 +231,25 @@ void RunRecModel(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat img,
score /= count; score /= count;
rec_text.push_back(str_res); rec_text.push_back(str_res);
rec_text_score.push_back(score); rec_text_score.push_back(score);
auto postprocess_end = std::chrono::steady_clock::now();
std::chrono::duration<float> preprocess_diff = preprocess_end - preprocess_start;
time_info[0] += double(preprocess_diff.count() * 1000);
std::chrono::duration<float> inference_diff = inference_end - inference_start;
time_info[1] += double(inference_diff.count() * 1000);
std::chrono::duration<float> postprocess_diff = postprocess_end - postprocess_start;
time_info[2] += double(postprocess_diff.count() * 1000);
} }
times->push_back(time_info[0]);
times->push_back(time_info[1]);
times->push_back(time_info[2]);
} }
std::vector<std::vector<std::vector<int>>> std::vector<std::vector<std::vector<int>>>
RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img, RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img,
std::map<std::string, double> Config) { std::map<std::string, double> Config, std::vector<double> *times) {
// Read img // Read img
int max_side_len = int(Config["max_side_len"]); int max_side_len = int(Config["max_side_len"]);
int det_db_use_dilate = int(Config["det_db_use_dilate"]); int det_db_use_dilate = int(Config["det_db_use_dilate"]);
...@@ -234,6 +257,7 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img, ...@@ -234,6 +257,7 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img,
cv::Mat srcimg; cv::Mat srcimg;
img.copyTo(srcimg); img.copyTo(srcimg);
auto preprocess_start = std::chrono::steady_clock::now();
std::vector<float> ratio_hw; std::vector<float> ratio_hw;
img = DetResizeImg(img, max_side_len, ratio_hw); img = DetResizeImg(img, max_side_len, ratio_hw);
cv::Mat img_fp; cv::Mat img_fp;
...@@ -248,8 +272,10 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img, ...@@ -248,8 +272,10 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img,
std::vector<float> scale = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f}; std::vector<float> scale = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f};
const float *dimg = reinterpret_cast<const float *>(img_fp.data); const float *dimg = reinterpret_cast<const float *>(img_fp.data);
NeonMeanScale(dimg, data0, img_fp.rows * img_fp.cols, mean, scale); NeonMeanScale(dimg, data0, img_fp.rows * img_fp.cols, mean, scale);
auto preprocess_end = std::chrono::steady_clock::now();
// Run predictor // Run predictor
auto inference_start = std::chrono::steady_clock::now();
predictor->Run(); predictor->Run();
// Get output and post process // Get output and post process
...@@ -257,8 +283,10 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img, ...@@ -257,8 +283,10 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img,
std::move(predictor->GetOutput(0))); std::move(predictor->GetOutput(0)));
auto *outptr = output_tensor->data<float>(); auto *outptr = output_tensor->data<float>();
auto shape_out = output_tensor->shape(); auto shape_out = output_tensor->shape();
auto inference_end = std::chrono::steady_clock::now();
// Save output // Save output
auto postprocess_start = std::chrono::steady_clock::now();
float pred[shape_out[2] * shape_out[3]]; float pred[shape_out[2] * shape_out[3]];
unsigned char cbuf[shape_out[2] * shape_out[3]]; unsigned char cbuf[shape_out[2] * shape_out[3]];
...@@ -287,14 +315,23 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img, ...@@ -287,14 +315,23 @@ RunDetModel(std::shared_ptr<PaddlePredictor> predictor, cv::Mat img,
std::vector<std::vector<std::vector<int>>> filter_boxes = std::vector<std::vector<std::vector<int>>> filter_boxes =
FilterTagDetRes(boxes, ratio_hw[0], ratio_hw[1], srcimg); FilterTagDetRes(boxes, ratio_hw[0], ratio_hw[1], srcimg);
auto postprocess_end = std::chrono::steady_clock::now();
std::chrono::duration<float> preprocess_diff = preprocess_end - preprocess_start;
times->push_back(double(preprocess_diff.count() * 1000));
std::chrono::duration<float> inference_diff = inference_end - inference_start;
times->push_back(double(inference_diff.count() * 1000));
std::chrono::duration<float> postprocess_diff = postprocess_end - postprocess_start;
times->push_back(double(postprocess_diff.count() * 1000));
return filter_boxes; return filter_boxes;
} }
std::shared_ptr<PaddlePredictor> loadModel(std::string model_file) { std::shared_ptr<PaddlePredictor> loadModel(std::string model_file, int num_threads) {
MobileConfig config; MobileConfig config;
config.set_model_from_file(model_file); config.set_model_from_file(model_file);
config.set_threads(num_threads);
std::shared_ptr<PaddlePredictor> predictor = std::shared_ptr<PaddlePredictor> predictor =
CreatePaddlePredictor<MobileConfig>(config); CreatePaddlePredictor<MobileConfig>(config);
return predictor; return predictor;
...@@ -354,60 +391,285 @@ std::map<std::string, double> LoadConfigTxt(std::string config_path) { ...@@ -354,60 +391,285 @@ std::map<std::string, double> LoadConfigTxt(std::string config_path) {
return dict; return dict;
} }
int main(int argc, char **argv) { void check_params(int argc, char **argv) {
if (argc < 5) { if (argc<=1 || (strcmp(argv[1], "det")!=0 && strcmp(argv[1], "rec")!=0 && strcmp(argv[1], "system")!=0)) {
std::cerr << "[ERROR] usage: " << argv[0] std::cerr << "Please choose one mode of [det, rec, system] !" << std::endl;
<< " det_model_file cls_model_file rec_model_file image_path "
"charactor_dict\n";
exit(1); exit(1);
} }
std::string det_model_file = argv[1]; if (strcmp(argv[1], "det") == 0) {
std::string rec_model_file = argv[2]; if (argc < 9){
std::string cls_model_file = argv[3]; std::cerr << "[ERROR] usage:" << argv[0]
std::string img_path = argv[4]; << " det det_model runtime_device num_threads batchsize img_dir det_config lite_benchmark_value" << std::endl;
std::string dict_path = argv[5]; exit(1);
}
}
//// load config from txt file if (strcmp(argv[1], "rec") == 0) {
auto Config = LoadConfigTxt("./config.txt"); if (argc < 9){
int use_direction_classify = int(Config["use_direction_classify"]); std::cerr << "[ERROR] usage:" << argv[0]
<< " rec rec_model runtime_device num_threads batchsize img_dir key_txt lite_benchmark_value" << std::endl;
exit(1);
}
}
if (strcmp(argv[1], "system") == 0) {
if (argc < 12){
std::cerr << "[ERROR] usage:" << argv[0]
<< " system det_model rec_model clas_model runtime_device num_threads batchsize img_dir det_config key_txt lite_benchmark_value" << std::endl;
exit(1);
}
}
}
void system(char **argv){
std::string det_model_file = argv[2];
std::string rec_model_file = argv[3];
std::string cls_model_file = argv[4];
std::string runtime_device = argv[5];
std::string precision = argv[6];
std::string num_threads = argv[7];
std::string batchsize = argv[8];
std::string img_dir = argv[9];
std::string det_config_path = argv[10];
std::string dict_path = argv[11];
if (strcmp(argv[6], "FP32") != 0 && strcmp(argv[6], "INT8") != 0) {
std::cerr << "Only support FP32 or INT8." << std::endl;
exit(1);
}
auto start = std::chrono::system_clock::now(); std::vector<cv::String> cv_all_img_names;
cv::glob(img_dir, cv_all_img_names);
auto det_predictor = loadModel(det_model_file); //// load config from txt file
auto rec_predictor = loadModel(rec_model_file); auto Config = LoadConfigTxt(det_config_path);
auto cls_predictor = loadModel(cls_model_file); int use_direction_classify = int(Config["use_direction_classify"]);
auto charactor_dict = ReadDict(dict_path); auto charactor_dict = ReadDict(dict_path);
charactor_dict.insert(charactor_dict.begin(), "#"); // blank char for ctc charactor_dict.insert(charactor_dict.begin(), "#"); // blank char for ctc
charactor_dict.push_back(" "); charactor_dict.push_back(" ");
cv::Mat srcimg = cv::imread(img_path, cv::IMREAD_COLOR); auto det_predictor = loadModel(det_model_file, std::stoi(num_threads));
auto boxes = RunDetModel(det_predictor, srcimg, Config); auto rec_predictor = loadModel(rec_model_file, std::stoi(num_threads));
auto cls_predictor = loadModel(cls_model_file, std::stoi(num_threads));
std::vector<double> det_time_info = {0, 0, 0};
std::vector<double> rec_time_info = {0, 0, 0};
for (int i = 0; i < cv_all_img_names.size(); ++i) {
std::cout << "The predict img: " << cv_all_img_names[i] << std::endl;
cv::Mat srcimg = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR);
if (!srcimg.data) {
std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << std::endl;
exit(1);
}
std::vector<double> det_times;
auto boxes = RunDetModel(det_predictor, srcimg, Config, &det_times);
std::vector<std::string> rec_text; std::vector<std::string> rec_text;
std::vector<float> rec_text_score; std::vector<float> rec_text_score;
std::vector<double> rec_times;
RunRecModel(boxes, srcimg, rec_predictor, rec_text, rec_text_score, RunRecModel(boxes, srcimg, rec_predictor, rec_text, rec_text_score,
charactor_dict, cls_predictor, use_direction_classify); charactor_dict, cls_predictor, use_direction_classify, &rec_times);
//// visualization
auto img_vis = Visualization(srcimg, boxes);
//// print recognized text
for (int i = 0; i < rec_text.size(); i++) {
std::cout << i << "\t" << rec_text[i] << "\t" << rec_text_score[i]
<< std::endl;
}
det_time_info[0] += det_times[0];
det_time_info[1] += det_times[1];
det_time_info[2] += det_times[2];
rec_time_info[0] += rec_times[0];
rec_time_info[1] += rec_times[1];
rec_time_info[2] += rec_times[2];
}
if (strcmp(argv[12], "True") == 0) {
AutoLogger autolog_det(det_model_file,
runtime_device,
std::stoi(num_threads),
std::stoi(batchsize),
"dynamic",
precision,
det_time_info,
cv_all_img_names.size());
AutoLogger autolog_rec(rec_model_file,
runtime_device,
std::stoi(num_threads),
std::stoi(batchsize),
"dynamic",
precision,
rec_time_info,
cv_all_img_names.size());
autolog_det.report();
std::cout << std::endl;
autolog_rec.report();
}
}
void det(int argc, char **argv) {
std::string det_model_file = argv[2];
std::string runtime_device = argv[3];
std::string precision = argv[4];
std::string num_threads = argv[5];
std::string batchsize = argv[6];
std::string img_dir = argv[7];
std::string det_config_path = argv[8];
if (strcmp(argv[4], "FP32") != 0 && strcmp(argv[4], "INT8") != 0) {
std::cerr << "Only support FP32 or INT8." << std::endl;
exit(1);
}
std::vector<cv::String> cv_all_img_names;
cv::glob(img_dir, cv_all_img_names);
//// load config from txt file
auto Config = LoadConfigTxt(det_config_path);
auto det_predictor = loadModel(det_model_file, std::stoi(num_threads));
auto end = std::chrono::system_clock::now(); std::vector<double> time_info = {0, 0, 0};
auto duration = for (int i = 0; i < cv_all_img_names.size(); ++i) {
std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "The predict img: " << cv_all_img_names[i] << std::endl;
cv::Mat srcimg = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR);
if (!srcimg.data) {
std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << std::endl;
exit(1);
}
std::vector<double> times;
auto boxes = RunDetModel(det_predictor, srcimg, Config, &times);
//// visualization //// visualization
auto img_vis = Visualization(srcimg, boxes); auto img_vis = Visualization(srcimg, boxes);
std::cout << boxes.size() << " bboxes have detected:" << std::endl;
for (int i=0; i<boxes.size(); i++){
std::cout << "The " << i << " box:" << std::endl;
for (int j=0; j<4; j++){
for (int k=0; k<2; k++){
std::cout << boxes[i][j][k] << "\t";
}
}
std::cout << std::endl;
}
time_info[0] += times[0];
time_info[1] += times[1];
time_info[2] += times[2];
}
if (strcmp(argv[9], "True") == 0) {
AutoLogger autolog(det_model_file,
runtime_device,
std::stoi(num_threads),
std::stoi(batchsize),
"dynamic",
precision,
time_info,
cv_all_img_names.size());
autolog.report();
}
}
void rec(int argc, char **argv) {
std::string rec_model_file = argv[2];
std::string runtime_device = argv[3];
std::string precision = argv[4];
std::string num_threads = argv[5];
std::string batchsize = argv[6];
std::string img_dir = argv[7];
std::string dict_path = argv[8];
if (strcmp(argv[4], "FP32") != 0 && strcmp(argv[4], "INT8") != 0) {
std::cerr << "Only support FP32 or INT8." << std::endl;
exit(1);
}
std::vector<cv::String> cv_all_img_names;
cv::glob(img_dir, cv_all_img_names);
auto charactor_dict = ReadDict(dict_path);
charactor_dict.insert(charactor_dict.begin(), "#"); // blank char for ctc
charactor_dict.push_back(" ");
auto rec_predictor = loadModel(rec_model_file, std::stoi(num_threads));
std::shared_ptr<PaddlePredictor> cls_predictor;
std::vector<double> time_info = {0, 0, 0};
for (int i = 0; i < cv_all_img_names.size(); ++i) {
std::cout << "The predict img: " << cv_all_img_names[i] << std::endl;
cv::Mat srcimg = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR);
if (!srcimg.data) {
std::cerr << "[ERROR] image read failed! image path: " << cv_all_img_names[i] << std::endl;
exit(1);
}
int width = srcimg.cols;
int height = srcimg.rows;
std::vector<int> upper_left = {0, 0};
std::vector<int> upper_right = {width, 0};
std::vector<int> lower_right = {width, height};
std::vector<int> lower_left = {0, height};
std::vector<std::vector<int>> box = {upper_left, upper_right, lower_right, lower_left};
std::vector<std::vector<std::vector<int>>> boxes = {box};
std::vector<std::string> rec_text;
std::vector<float> rec_text_score;
std::vector<double> times;
RunRecModel(boxes, srcimg, rec_predictor, rec_text, rec_text_score,
charactor_dict, cls_predictor, 0, &times);
//// print recognized text //// print recognized text
for (int i = 0; i < rec_text.size(); i++) { for (int i = 0; i < rec_text.size(); i++) {
std::cout << i << "\t" << rec_text[i] << "\t" << rec_text_score[i] std::cout << i << "\t" << rec_text[i] << "\t" << rec_text_score[i]
<< std::endl; << std::endl;
} }
time_info[0] += times[0];
time_info[1] += times[1];
time_info[2] += times[2];
}
// TODO: support autolog
if (strcmp(argv[9], "True") == 0) {
AutoLogger autolog(rec_model_file,
runtime_device,
std::stoi(num_threads),
std::stoi(batchsize),
"dynamic",
precision,
time_info,
cv_all_img_names.size());
autolog.report();
}
}
int main(int argc, char **argv) {
check_params(argc, argv);
std::cout << "mode: " << argv[1] << endl;
if (strcmp(argv[1], "system") == 0) {
system(argv);
}
std::cout << "花费了" if (strcmp(argv[1], "det") == 0) {
<< double(duration.count()) * det(argc, argv);
std::chrono::microseconds::period::num / }
std::chrono::microseconds::period::den
<< "秒" << std::endl; if (strcmp(argv[1], "rec") == 0) {
rec(argc, argv);
}
return 0; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment