提交 483486af 编写于 作者: littletomatodonkey's avatar littletomatodonkey

add config

上级 b5bfe823
...@@ -57,7 +57,8 @@ link_directories("${PADDLE_LIB}/third_party/install/xxhash/lib") ...@@ -57,7 +57,8 @@ link_directories("${PADDLE_LIB}/third_party/install/xxhash/lib")
link_directories("${PADDLE_LIB}/paddle/lib") link_directories("${PADDLE_LIB}/paddle/lib")
add_executable(${DEMO_NAME} src/main.cpp src/ocr_det.cpp src/ocr_rec.cpp src/preprocess_op.cpp src/clipper.cpp src/postprocess_op.cpp ) AUX_SOURCE_DIRECTORY(./src SRCS)
add_executable(${DEMO_NAME} ${SRCS})
if(WITH_MKL) if(WITH_MKL)
include_directories("${PADDLE_LIB}/third_party/install/mklml/include") include_directories("${PADDLE_LIB}/third_party/install/mklml/include")
...@@ -81,9 +82,6 @@ else() ...@@ -81,9 +82,6 @@ else()
${PADDLE_LIB}/paddle/lib/libpaddle_fluid${CMAKE_SHARED_LIBRARY_SUFFIX}) ${PADDLE_LIB}/paddle/lib/libpaddle_fluid${CMAKE_SHARED_LIBRARY_SUFFIX})
endif() endif()
# user ze
# set(EXTERNAL_LIB "-lrt -ldl -lpthread -lm -lopencv_world")
# gry
set(EXTERNAL_LIB "-lrt -ldl -lpthread -lm") set(EXTERNAL_LIB "-lrt -ldl -lpthread -lm")
set(DEPS ${DEPS} set(DEPS ${DEPS}
......
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <iomanip>
#include <iostream>
#include <map>
#include <ostream>
#include <string>
#include <vector>
#include "include/utility.h"
namespace PaddleOCR {
class Config {
public:
explicit Config(const std::string &config_file) {
config_map_ = LoadConfig(config_file);
this->use_gpu = bool(stoi(config_map_["use_gpu"]));
this->gpu_id = stoi(config_map_["gpu_id"]);
this->gpu_mem = stoi(config_map_["gpu_mem"]);
this->cpu_math_library_num_threads =
stoi(config_map_["cpu_math_library_num_threads"]);
this->max_side_len = stoi(config_map_["max_side_len"]);
this->det_db_thresh = stod(config_map_["det_db_thresh"]);
this->det_db_box_thresh = stod(config_map_["det_db_box_thresh"]);
this->det_db_box_thresh = stod(config_map_["det_db_box_thresh"]);
this->det_model_dir.assign(config_map_["det_model_dir"]);
this->rec_model_dir.assign(config_map_["rec_model_dir"]);
this->char_list_file.assign(config_map_["char_list_file"]);
}
bool use_gpu = false;
int gpu_id = 0;
int gpu_mem = 4000;
int cpu_math_library_num_threads = 1;
int max_side_len = 960;
double det_db_thresh = 0.3;
double det_db_box_thresh = 0.5;
double det_db_unclip_ratio = 2.0;
std::string det_model_dir;
std::string rec_model_dir;
std::string char_list_file;
void PrintConfigInfo();
private:
// Load configuration
std::map<std::string, std::string> LoadConfig(const std::string &config_file);
std::vector<std::string> split(const std::string &str,
const std::string &delim);
std::map<std::string, std::string> config_map_;
};
} // namespace PaddleOCR
...@@ -36,16 +36,29 @@ namespace PaddleOCR { ...@@ -36,16 +36,29 @@ namespace PaddleOCR {
class DBDetector { class DBDetector {
public: public:
explicit DBDetector(const std::string &model_dir, bool use_gpu = false, explicit DBDetector(const std::string &model_dir, const bool &use_gpu = false,
const int gpu_id = 0, const int max_side_len = 960) { const int &gpu_id = 0, const int &gpu_mem = 4000,
LoadModel(model_dir, use_gpu); const int &cpu_math_library_num_threads = 4,
const int &max_side_len = 960,
const double &det_db_thresh = 0.3,
const double &det_db_box_thresh = 0.5,
const double &det_db_unclip_ratio = 2.0) {
LoadModel(model_dir);
this->use_gpu_ = use_gpu;
this->gpu_id_ = gpu_id;
this->gpu_mem_ = gpu_mem;
this->cpu_math_library_num_threads_ = cpu_math_library_num_threads;
this->max_side_len_ = max_side_len; this->max_side_len_ = max_side_len;
this->det_db_thresh_ = det_db_thresh;
this->det_db_box_thresh_ = det_db_box_thresh;
this->det_db_unclip_ratio_ = det_db_unclip_ratio;
} }
// Load Paddle inference model // Load Paddle inference model
void LoadModel(const std::string &model_dir, bool use_gpu, void LoadModel(const std::string &model_dir);
const int min_subgraph_size = 3, const int batch_size = 1,
const int gpu_id = 0);
// Run predictor // Run predictor
void Run(cv::Mat &img, std::vector<std::vector<std::vector<int>>> &boxes); void Run(cv::Mat &img, std::vector<std::vector<std::vector<int>>> &boxes);
...@@ -53,8 +66,17 @@ public: ...@@ -53,8 +66,17 @@ public:
private: private:
std::shared_ptr<PaddlePredictor> predictor_; std::shared_ptr<PaddlePredictor> predictor_;
bool use_gpu_ = false;
int gpu_id_ = 0;
int gpu_mem_ = 4000;
int cpu_math_library_num_threads_ = 4;
int max_side_len_ = 960; int max_side_len_ = 960;
double det_db_thresh_ = 0.3;
double det_db_box_thresh_ = 0.5;
double det_db_unclip_ratio_ = 2.0;
std::vector<float> mean_ = {0.485f, 0.456f, 0.406f}; std::vector<float> mean_ = {0.485f, 0.456f, 0.406f};
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};
bool is_scale_ = true; bool is_scale_ = true;
......
...@@ -29,29 +29,40 @@ ...@@ -29,29 +29,40 @@
#include <include/postprocess_op.h> #include <include/postprocess_op.h>
#include <include/preprocess_op.h> #include <include/preprocess_op.h>
#include <include/utility.h>
namespace PaddleOCR { namespace PaddleOCR {
class CRNNRecognizer { class CRNNRecognizer {
public: public:
explicit CRNNRecognizer(const std::string &model_dir, explicit CRNNRecognizer(
const string label_path = "./tools/ppocr_keys_v1.txt", const std::string &model_dir, const bool &use_gpu = false,
bool use_gpu = false, const int gpu_id = 0) { const int &gpu_id = 0, const int &gpu_mem = 4000,
LoadModel(model_dir, use_gpu); const int &cpu_math_library_num_threads = 4,
const string &label_path = "./tools/ppocr_keys_v1.txt") {
this->label_list_ = ReadDict(label_path); LoadModel(model_dir);
this->use_gpu_ = use_gpu;
this->gpu_id_ = gpu_id;
this->gpu_mem_ = gpu_mem;
this->cpu_math_library_num_threads_ = cpu_math_library_num_threads;
this->label_list_ = Utility::ReadDict(label_path);
} }
// Load Paddle inference model // Load Paddle inference model
void LoadModel(const std::string &model_dir, bool use_gpu, void LoadModel(const std::string &model_dir);
const int gpu_id = 0, const int min_subgraph_size = 3,
const int batch_size = 1);
void Run(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat &img); void Run(std::vector<std::vector<std::vector<int>>> boxes, cv::Mat &img);
private: private:
std::shared_ptr<PaddlePredictor> predictor_; std::shared_ptr<PaddlePredictor> predictor_;
bool use_gpu_ = false;
int gpu_id_ = 0;
int gpu_mem_ = 4000;
int cpu_math_library_num_threads_ = 4;
std::vector<std::string> label_list_; std::vector<std::string> label_list_;
std::vector<float> mean_ = {0.5f, 0.5f, 0.5f}; std::vector<float> mean_ = {0.5f, 0.5f, 0.5f};
...@@ -66,15 +77,8 @@ private: ...@@ -66,15 +77,8 @@ private:
// post-process // post-process
PostProcessor post_processor_; PostProcessor post_processor_;
cv::Mat get_rotate_crop_image(const cv::Mat &srcimage, cv::Mat GetRotateCropImage(const cv::Mat &srcimage,
std::vector<std::vector<int>> box); std::vector<std::vector<int>> box);
std::vector<std::string> ReadDict(const std::string &path);
template <class ForwardIterator>
inline size_t argmax(ForwardIterator first, ForwardIterator last) {
return std::distance(first, std::max_element(first, last));
}
}; // class CrnnRecognizer }; // class CrnnRecognizer
......
...@@ -28,36 +28,17 @@ ...@@ -28,36 +28,17 @@
#include <numeric> #include <numeric>
#include "include/clipper.h" #include "include/clipper.h"
#include "include/utility.h"
using namespace std; using namespace std;
namespace PaddleOCR { namespace PaddleOCR {
inline std::vector<std::string> ReadDict(std::string path) {
std::ifstream in(path);
std::string filename;
std::string line;
std::vector<std::string> m_vec;
if (in) {
while (getline(in, line)) {
m_vec.push_back(line);
}
} else {
std::cout << "no such file" << std::endl;
}
return m_vec;
}
template <class ForwardIterator>
inline size_t Argmax(ForwardIterator first, ForwardIterator last) {
return std::distance(first, std::max_element(first, last));
}
class PostProcessor { class PostProcessor {
public: public:
void GetContourArea(float **box, float unclip_ratio, float &distance); void GetContourArea(float **box, float unclip_ratio, float &distance);
cv::RotatedRect unclip(float **box); cv::RotatedRect UnClip(float **box, const float &unclip_ratio);
float **Mat2Vec(cv::Mat mat); float **Mat2Vec(cv::Mat mat);
...@@ -67,23 +48,17 @@ public: ...@@ -67,23 +48,17 @@ public:
std::vector<std::vector<int>> std::vector<std::vector<int>>
order_points_clockwise(std::vector<std::vector<int>> pts); order_points_clockwise(std::vector<std::vector<int>> pts);
float **get_mini_boxes(cv::RotatedRect box, float &ssid); float **GetMiniBoxes(cv::RotatedRect box, float &ssid);
float box_score_fast(float **box_array, cv::Mat pred); float BoxScoreFast(float **box_array, cv::Mat pred);
std::vector<std::vector<std::vector<int>>> std::vector<std::vector<std::vector<int>>>
boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap); BoxesFromBitmap(const cv::Mat pred, const cv::Mat bitmap,
const float &box_thresh, const float &det_db_unclip_ratio);
std::vector<std::vector<std::vector<int>>> std::vector<std::vector<std::vector<int>>>
filter_tag_det_res(std::vector<std::vector<std::vector<int>>> boxes, FilterTagDetRes(std::vector<std::vector<std::vector<int>>> boxes,
float ratio_h, float ratio_w, cv::Mat srcimg); float ratio_h, float ratio_w, cv::Mat srcimg);
template <class ForwardIterator>
inline size_t argmax(ForwardIterator first, ForwardIterator last) {
return std::distance(first, std::max_element(first, last));
}
// CRNN
private: private:
void quickSort(float **s, int l, int r); void quickSort(float **s, int l, int r);
...@@ -99,6 +74,7 @@ private: ...@@ -99,6 +74,7 @@ private:
return min; return min;
return x; return x;
} }
inline float clampf(float x, float min, float max) { inline float clampf(float x, float min, float max) {
if (x > max) if (x > max)
return max; return max;
...@@ -108,4 +84,4 @@ private: ...@@ -108,4 +84,4 @@ private:
} }
}; };
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
...@@ -44,7 +44,6 @@ public: ...@@ -44,7 +44,6 @@ public:
virtual void Run(const cv::Mat *im, float *data); virtual void Run(const cv::Mat *im, float *data);
}; };
// RGB -> CHW
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,
...@@ -54,7 +53,7 @@ public: ...@@ -54,7 +53,7 @@ public:
class CrnnResizeImg { class CrnnResizeImg {
public: public:
virtual void Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, virtual void Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio,
const std::vector<int> rec_image_shape = {3, 32, 320}); const std::vector<int> &rec_image_shape = {3, 32, 320});
}; };
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <chrono>
#include <iomanip>
#include <iostream>
#include <ostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <cstring>
#include <fstream>
#include <numeric>
namespace PaddleOCR {
class Utility {
public:
static std::vector<std::string> ReadDict(const std::string &path);
template <class ForwardIterator>
inline static size_t argmax(ForwardIterator first, ForwardIterator last) {
return std::distance(first, std::max_element(first, last));
}
};
} // namespace PaddleOCR
\ No newline at end of file
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <include/config.h>
namespace PaddleOCR {
std::vector<std::string> Config::split(const std::string &str,
const std::string &delim) {
std::vector<std::string> res;
if ("" == str)
return res;
char *strs = new char[str.length() + 1];
std::strcpy(strs, str.c_str());
char *d = new char[delim.length() + 1];
std::strcpy(d, delim.c_str());
char *p = std::strtok(strs, d);
while (p) {
std::string s = p;
res.push_back(s);
p = std::strtok(NULL, d);
}
return res;
}
std::map<std::string, std::string>
Config::LoadConfig(const std::string &config_path) {
auto config = Utility::ReadDict(config_path);
std::map<std::string, std::string> dict;
for (int i = 0; i < config.size(); i++) {
// pass for empty line or comment
if (config[i].size() <= 1 or config[i][0] == '#') {
continue;
}
std::vector<std::string> res = split(config[i], " ");
dict[res[0]] = res[1];
}
return dict;
}
void Config::PrintConfigInfo() {
std::cout << "=======Paddle OCR inference config======" << std::endl;
for (auto iter = config_map_.begin(); iter != config_map_.end(); iter++) {
std::cout << iter->first << " : " << iter->second << std::endl;
}
std::cout << "=======End of Paddle OCR inference config======" << std::endl;
}
} // namespace PaddleOCR
\ No newline at end of file
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <fstream> #include <fstream>
#include <numeric> #include <numeric>
#include <include/config.h>
#include <include/ocr_det.h> #include <include/ocr_det.h>
#include <include/ocr_rec.h> #include <include/ocr_rec.h>
...@@ -33,21 +34,29 @@ using namespace cv; ...@@ -33,21 +34,29 @@ using namespace cv;
using namespace PaddleOCR; using namespace PaddleOCR;
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (argc < 4) { if (argc < 3) {
std::cerr << "[ERROR] usage: " << argv[0] std::cerr << "[ERROR] usage: " << argv[0]
<< " det_model_file rec_model_file image_path\n"; << " configure_filepath image_path\n";
exit(1); exit(1);
} }
std::string det_model_file = argv[1];
std::string rec_model_file = argv[2]; Config config(argv[1]);
std::string img_path = argv[3];
config.PrintConfigInfo();
std::string img_path(argv[2]);
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
cv::Mat srcimg = cv::imread(img_path, cv::IMREAD_COLOR); cv::Mat srcimg = cv::imread(img_path, cv::IMREAD_COLOR);
DBDetector det(det_model_file); DBDetector det(config.det_model_dir, config.use_gpu, config.gpu_id,
CRNNRecognizer rec(rec_model_file); config.gpu_mem, config.cpu_math_library_num_threads,
config.max_side_len, config.det_db_thresh,
config.det_db_box_thresh, config.det_db_unclip_ratio);
CRNNRecognizer rec(config.rec_model_dir, config.use_gpu, config.gpu_id,
config.gpu_mem, config.cpu_math_library_num_threads,
config.char_list_file);
std::vector<std::vector<std::vector<int>>> boxes; std::vector<std::vector<std::vector<int>>> boxes;
det.Run(srcimg, boxes); det.Run(srcimg, boxes);
......
...@@ -31,29 +31,28 @@ ...@@ -31,29 +31,28 @@
namespace PaddleOCR { namespace PaddleOCR {
void DBDetector::LoadModel(const std::string &model_dir, bool use_gpu, void DBDetector::LoadModel(const std::string &model_dir) {
const int gpu_id, const int min_subgraph_size,
const int batch_size) {
AnalysisConfig config; AnalysisConfig config;
config.SetModel(model_dir + "/model", model_dir + "/params"); config.SetModel(model_dir + "/model", model_dir + "/params");
// for cpu if (this->use_gpu_) {
config.DisableGpu(); config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
config.EnableMKLDNN(); // 开启MKLDNN加速 } else {
config.SetCpuMathLibraryNumThreads(10); config.DisableGpu();
config.EnableMKLDNN(); // 开启MKLDNN加速
config.SetCpuMathLibraryNumThreads(this->cpu_math_library_num_threads_);
}
// 使用ZeroCopyTensor,此处必须设置为false // false for zero copy tensor
config.SwitchUseFeedFetchOps(false); config.SwitchUseFeedFetchOps(false);
// 若输入为多个,此处必须设置为true // true for multiple input
config.SwitchSpecifyInputNames(true); config.SwitchSpecifyInputNames(true);
// config.SwitchIrDebug(true); //
// 可视化调试选项,若开启,则会在每个图优化过程后生成dot文件 config.SwitchIrOptim(true);
// config.SwitchIrOptim(false);// 默认为true。如果设置为false,关闭所有优化
config.EnableMemoryOptim(); // 开启内存/显存复用 config.EnableMemoryOptim();
this->predictor_ = CreatePaddlePredictor(config); this->predictor_ = CreatePaddlePredictor(config);
// predictor_ = std::move(CreatePaddlePredictor(config)); // PaddleDetection
// usage
} }
void DBDetector::Run(cv::Mat &img, void DBDetector::Run(cv::Mat &img,
...@@ -69,13 +68,13 @@ void DBDetector::Run(cv::Mat &img, ...@@ -69,13 +68,13 @@ void DBDetector::Run(cv::Mat &img,
this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->normalize_op_.Run(&resize_img, this->mean_, this->scale_,
this->is_scale_); this->is_scale_);
float *input = new float[1 * 3 * resize_img.rows * resize_img.cols]; std::vector<float> input(1 * 3 * resize_img.rows * resize_img.cols, 0.0f);
this->permute_op_.Run(&resize_img, input); this->permute_op_.Run(&resize_img, input.data());
auto input_names = this->predictor_->GetInputNames(); auto input_names = this->predictor_->GetInputNames();
auto input_t = this->predictor_->GetInputTensor(input_names[0]); auto input_t = this->predictor_->GetInputTensor(input_names[0]);
input_t->Reshape({1, 3, resize_img.rows, resize_img.cols}); input_t->Reshape({1, 3, resize_img.rows, resize_img.cols});
input_t->copy_from_cpu(input); input_t->copy_from_cpu(input.data());
this->predictor_->ZeroCopyRun(); this->predictor_->ZeroCopyRun();
...@@ -93,25 +92,26 @@ void DBDetector::Run(cv::Mat &img, ...@@ -93,25 +92,26 @@ void DBDetector::Run(cv::Mat &img,
int n3 = output_shape[3]; int n3 = output_shape[3];
int n = n2 * n3; int n = n2 * n3;
float *pred = new float[n]; std::vector<float> pred(n, 0.0);
unsigned char *cbuf = new unsigned char[n]; std::vector<unsigned char> cbuf(n, ' ');
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
pred[i] = float(out_data[i]); pred[i] = float(out_data[i]);
cbuf[i] = (unsigned char)((out_data[i]) * 255); cbuf[i] = (unsigned char)((out_data[i]) * 255);
} }
cv::Mat cbuf_map(n2, n3, CV_8UC1, (unsigned char *)cbuf); cv::Mat cbuf_map(n2, n3, CV_8UC1, (unsigned char *)cbuf.data());
cv::Mat pred_map(n2, n3, CV_32F, (float *)pred); cv::Mat pred_map(n2, n3, CV_32F, (float *)pred.data());
const double threshold = 0.3 * 255; const double threshold = this->det_db_thresh_ * 255;
const double maxvalue = 255; const double maxvalue = 255;
cv::Mat bit_map; cv::Mat bit_map;
cv::threshold(cbuf_map, bit_map, threshold, maxvalue, cv::THRESH_BINARY); cv::threshold(cbuf_map, bit_map, threshold, maxvalue, cv::THRESH_BINARY);
boxes = post_processor_.boxes_from_bitmap(pred_map, bit_map); boxes = post_processor_.BoxesFromBitmap(
pred_map, bit_map, this->det_db_box_thresh_, this->det_db_unclip_ratio_);
boxes = post_processor_.filter_tag_det_res(boxes, ratio_h, ratio_w, srcimg); boxes = post_processor_.FilterTagDetRes(boxes, ratio_h, ratio_w, srcimg);
//// visualization //// visualization
cv::Point rook_points[boxes.size()][4]; cv::Point rook_points[boxes.size()][4];
...@@ -133,10 +133,6 @@ void DBDetector::Run(cv::Mat &img, ...@@ -133,10 +133,6 @@ void DBDetector::Run(cv::Mat &img,
std::cout << "The detection visualized image saved in ./det_res.png" std::cout << "The detection visualized image saved in ./det_res.png"
<< std::endl; << std::endl;
delete[] input;
delete[] pred;
delete[] cbuf;
} }
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
...@@ -41,7 +41,7 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes, ...@@ -41,7 +41,7 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes,
std::cout << "The predicted text is :" << std::endl; std::cout << "The predicted text is :" << std::endl;
int index = 0; int index = 0;
for (int i = boxes.size() - 1; i >= 0; i--) { for (int i = boxes.size() - 1; i >= 0; i--) {
crop_img = get_rotate_crop_image(srcimg, boxes[i]); crop_img = GetRotateCropImage(srcimg, boxes[i]);
float wh_ratio = float(crop_img.cols) / float(crop_img.rows); float wh_ratio = float(crop_img.cols) / float(crop_img.rows);
...@@ -50,14 +50,14 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes, ...@@ -50,14 +50,14 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes,
this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->normalize_op_.Run(&resize_img, this->mean_, this->scale_,
this->is_scale_); this->is_scale_);
float *input = new float[1 * 3 * resize_img.rows * resize_img.cols]; std::vector<float> input(1 * 3 * resize_img.rows * resize_img.cols, 0.0f);
this->permute_op_.Run(&resize_img, input); this->permute_op_.Run(&resize_img, input.data());
auto input_names = this->predictor_->GetInputNames(); auto input_names = this->predictor_->GetInputNames();
auto input_t = this->predictor_->GetInputTensor(input_names[0]); auto input_t = this->predictor_->GetInputTensor(input_names[0]);
input_t->Reshape({1, 3, resize_img.rows, resize_img.cols}); input_t->Reshape({1, 3, resize_img.rows, resize_img.cols});
input_t->copy_from_cpu(input); input_t->copy_from_cpu(input.data());
this->predictor_->ZeroCopyRun(); this->predictor_->ZeroCopyRun();
...@@ -104,7 +104,8 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes, ...@@ -104,7 +104,8 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes,
float max_value = 0.0f; float max_value = 0.0f;
for (int n = predict_lod[0][0]; n < predict_lod[0][1] - 1; n++) { for (int n = predict_lod[0][0]; n < predict_lod[0][1] - 1; n++) {
argmax_idx = int(argmax(&predict_batch[n * predict_shape[1]], argmax_idx =
int(Utility::argmax(&predict_batch[n * predict_shape[1]],
&predict_batch[(n + 1) * predict_shape[1]])); &predict_batch[(n + 1) * predict_shape[1]]));
max_value = max_value =
float(*std::max_element(&predict_batch[n * predict_shape[1]], float(*std::max_element(&predict_batch[n * predict_shape[1]],
...@@ -116,37 +117,35 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes, ...@@ -116,37 +117,35 @@ void CRNNRecognizer::Run(std::vector<std::vector<std::vector<int>>> boxes,
} }
score /= count; score /= count;
std::cout << "\tscore: " << score << std::endl; std::cout << "\tscore: " << score << std::endl;
delete[] input;
} }
} }
void CRNNRecognizer::LoadModel(const std::string &model_dir, bool use_gpu, void CRNNRecognizer::LoadModel(const std::string &model_dir) {
const int gpu_id, const int min_subgraph_size,
const int batch_size) {
AnalysisConfig config; AnalysisConfig config;
config.SetModel(model_dir + "/model", model_dir + "/params"); config.SetModel(model_dir + "/model", model_dir + "/params");
// for cpu if (this->use_gpu_) {
config.DisableGpu(); config.EnableUseGpu(this->gpu_mem_, this->gpu_id_);
config.EnableMKLDNN(); // 开启MKLDNN加速 } else {
config.SetCpuMathLibraryNumThreads(10); config.DisableGpu();
config.EnableMKLDNN(); // 开启MKLDNN加速
config.SetCpuMathLibraryNumThreads(this->cpu_math_library_num_threads_);
}
// 使用ZeroCopyTensor,此处必须设置为false // false for zero copy tensor
config.SwitchUseFeedFetchOps(false); config.SwitchUseFeedFetchOps(false);
// 若输入为多个,此处必须设置为true // true for multiple input
config.SwitchSpecifyInputNames(true); config.SwitchSpecifyInputNames(true);
// config.SwitchIrDebug(true); //
// 可视化调试选项,若开启,则会在每个图优化过程后生成dot文件 config.SwitchIrOptim(true);
// config.SwitchIrOptim(false);// 默认为true。如果设置为false,关闭所有优化
config.EnableMemoryOptim(); // 开启内存/显存复用 config.EnableMemoryOptim();
this->predictor_ = CreatePaddlePredictor(config); this->predictor_ = CreatePaddlePredictor(config);
} }
cv::Mat cv::Mat CRNNRecognizer::GetRotateCropImage(const cv::Mat &srcimage,
CRNNRecognizer::get_rotate_crop_image(const cv::Mat &srcimage, std::vector<std::vector<int>> box) {
std::vector<std::vector<int>> box) {
cv::Mat image; cv::Mat image;
srcimage.copyTo(image); srcimage.copyTo(image);
std::vector<std::vector<int>> points = box; std::vector<std::vector<int>> points = box;
...@@ -200,19 +199,4 @@ CRNNRecognizer::get_rotate_crop_image(const cv::Mat &srcimage, ...@@ -200,19 +199,4 @@ CRNNRecognizer::get_rotate_crop_image(const cv::Mat &srcimage,
} }
} }
std::vector<std::string> CRNNRecognizer::ReadDict(const std::string &path) {
std::ifstream in(path);
std::string filename;
std::string line;
std::vector<std::string> m_vec;
if (in) {
while (getline(in, line)) {
m_vec.push_back(line);
}
} else {
std::cout << "no such file" << std::endl;
}
return m_vec;
}
} // namespace PaddleOCR } // namespace PaddleOCR
\ No newline at end of file
...@@ -34,8 +34,7 @@ void PostProcessor::GetContourArea(float **box, float unclip_ratio, ...@@ -34,8 +34,7 @@ void PostProcessor::GetContourArea(float **box, float unclip_ratio,
distance = area * unclip_ratio / dist; distance = area * unclip_ratio / dist;
} }
cv::RotatedRect PostProcessor::unclip(float **box) { cv::RotatedRect PostProcessor::UnClip(float **box, const float &unclip_ratio) {
float unclip_ratio = 2.0;
float distance = 1.0; float distance = 1.0;
GetContourArea(box, unclip_ratio, distance); GetContourArea(box, unclip_ratio, distance);
...@@ -136,7 +135,7 @@ PostProcessor::order_points_clockwise(std::vector<std::vector<int>> pts) { ...@@ -136,7 +135,7 @@ PostProcessor::order_points_clockwise(std::vector<std::vector<int>> pts) {
return rect; return rect;
} }
float **PostProcessor::get_mini_boxes(cv::RotatedRect box, float &ssid) { float **PostProcessor::GetMiniBoxes(cv::RotatedRect box, float &ssid) {
ssid = box.size.width >= box.size.height ? box.size.height : box.size.width; ssid = box.size.width >= box.size.height ? box.size.height : box.size.width;
cv::Mat points; cv::Mat points;
...@@ -169,7 +168,7 @@ float **PostProcessor::get_mini_boxes(cv::RotatedRect box, float &ssid) { ...@@ -169,7 +168,7 @@ float **PostProcessor::get_mini_boxes(cv::RotatedRect box, float &ssid) {
return array; return array;
} }
float PostProcessor::box_score_fast(float **box_array, cv::Mat pred) { float PostProcessor::BoxScoreFast(float **box_array, cv::Mat pred) {
auto array = box_array; auto array = box_array;
int width = pred.cols; int width = pred.cols;
int height = pred.rows; int height = pred.rows;
...@@ -207,10 +206,11 @@ float PostProcessor::box_score_fast(float **box_array, cv::Mat pred) { ...@@ -207,10 +206,11 @@ float PostProcessor::box_score_fast(float **box_array, cv::Mat pred) {
} }
std::vector<std::vector<std::vector<int>>> std::vector<std::vector<std::vector<int>>>
PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) { PostProcessor::BoxesFromBitmap(const cv::Mat pred, const cv::Mat bitmap,
const float &box_thresh,
const float &det_db_unclip_ratio) {
const int min_size = 3; const int min_size = 3;
const int max_candidates = 1000; const int max_candidates = 1000;
const float box_thresh = 0.5;
int width = bitmap.cols; int width = bitmap.cols;
int height = bitmap.rows; int height = bitmap.rows;
...@@ -229,7 +229,7 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) { ...@@ -229,7 +229,7 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) {
for (int _i = 0; _i < num_contours; _i++) { for (int _i = 0; _i < num_contours; _i++) {
float ssid; float ssid;
cv::RotatedRect box = cv::minAreaRect(contours[_i]); cv::RotatedRect box = cv::minAreaRect(contours[_i]);
auto array = get_mini_boxes(box, ssid); auto array = GetMiniBoxes(box, ssid);
auto box_for_unclip = array; auto box_for_unclip = array;
// end get_mini_box // end get_mini_box
...@@ -239,17 +239,16 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) { ...@@ -239,17 +239,16 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) {
} }
float score; float score;
score = box_score_fast(array, pred); score = BoxScoreFast(array, pred);
// end box_score_fast
if (score < box_thresh) if (score < box_thresh)
continue; continue;
// start for unclip // start for unclip
cv::RotatedRect points = unclip(box_for_unclip); cv::RotatedRect points = UnClip(box_for_unclip, det_db_unclip_ratio);
// end for unclip // end for unclip
cv::RotatedRect clipbox = points; cv::RotatedRect clipbox = points;
auto cliparray = get_mini_boxes(clipbox, ssid); auto cliparray = GetMiniBoxes(clipbox, ssid);
if (ssid < min_size + 2) if (ssid < min_size + 2)
continue; continue;
...@@ -273,9 +272,9 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) { ...@@ -273,9 +272,9 @@ PostProcessor::boxes_from_bitmap(const cv::Mat pred, const cv::Mat bitmap) {
return boxes; return boxes;
} }
std::vector<std::vector<std::vector<int>>> PostProcessor::filter_tag_det_res( std::vector<std::vector<std::vector<int>>>
std::vector<std::vector<std::vector<int>>> boxes, float ratio_h, PostProcessor::FilterTagDetRes(std::vector<std::vector<std::vector<int>>> boxes,
float ratio_w, cv::Mat srcimg) { float ratio_h, float ratio_w, cv::Mat srcimg) {
int oriimg_h = srcimg.rows; int oriimg_h = srcimg.rows;
int oriimg_w = srcimg.cols; int oriimg_w = srcimg.cols;
......
...@@ -97,7 +97,7 @@ void ResizeImgType0::Run(const cv::Mat &img, cv::Mat &resize_img, ...@@ -97,7 +97,7 @@ void ResizeImgType0::Run(const cv::Mat &img, cv::Mat &resize_img,
} }
void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio,
const std::vector<int> rec_image_shape) { const std::vector<int> &rec_image_shape) {
int imgC, imgH, imgW; int imgC, imgH, imgW;
imgC = rec_image_shape[0]; imgC = rec_image_shape[0];
imgH = rec_image_shape[1]; imgH = rec_image_shape[1];
......
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <ostream>
#include <vector>
#include <include/utility.h>
namespace PaddleOCR {
std::vector<std::string> Utility::ReadDict(const std::string &path) {
std::ifstream in(path);
std::string line;
std::vector<std::string> m_vec;
if (in) {
while (getline(in, line)) {
m_vec.push_back(line);
}
} else {
std::cout << "no such label file: " << path << ", exit the program..."
<< std::endl;
exit(1);
}
return m_vec;
}
} // namespace PaddleOCR
\ No newline at end of file
# model load config
use_gpu 0
gpu_id 0
gpu_mem 4000
cpu_math_library_num_threads 1
# det config
max_side_len 960
det_db_thresh 0.3
det_db_box_thresh 0.5
det_db_unclip_ratio 2.0
det_model_dir ./inference/det_db
# rec config
rec_model_dir ./inference/rec_crnn
char_list_file ./tools/ppocr_keys_v1.txt
img_path ../../doc/imgs/11.jpg
./build/ocr_system ./inference/det_db/ ./inference/rec_crnn/ ../../doc/imgs/12.jpg ./build/ocr_system ./tools/config.txt ../../doc/imgs/6.jpg
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册