mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-23 00:29:35 +08:00
Fix Diff & Improve OCR readme (#184)
* Add PaddleOCR Support * Add PaddleOCR Support * Add PaddleOCRv3 Support * Add PaddleOCRv3 Support * Update README.md * Update README.md * Update README.md * Update README.md * Add PaddleOCRv3 Support * Add PaddleOCRv3 Supports * Add PaddleOCRv3 Suport * Fix Rec diff * Remove useless functions * Remove useless comments * Add PaddleOCRv2 Support * Add PaddleOCRv3 & PaddleOCRv2 Support * remove useless parameters * Add utils of sorting det boxes * Fix code naming convention * Fix code naming convention * Fix code naming convention * Fix bug in the Classify process * Imporve OCR Readme * Fix diff in Cls model * Update Model Download Link in Readme
This commit is contained in:
@@ -46,7 +46,7 @@ bool Classifier::Initialize() {
|
|||||||
cls_thresh = 0.9;
|
cls_thresh = 0.9;
|
||||||
cls_image_shape = {3, 48, 192};
|
cls_image_shape = {3, 48, 192};
|
||||||
cls_batch_num = 1;
|
cls_batch_num = 1;
|
||||||
mean = {0.485f, 0.456f, 0.406f};
|
mean = {0.5f, 0.5f, 0.5f};
|
||||||
scale = {0.5f, 0.5f, 0.5f};
|
scale = {0.5f, 0.5f, 0.5f};
|
||||||
is_scale = true;
|
is_scale = true;
|
||||||
|
|
||||||
|
@@ -144,10 +144,11 @@ bool DBDetector::Postprocess(
|
|||||||
|
|
||||||
std::vector<std::vector<std::vector<int>>> boxes;
|
std::vector<std::vector<std::vector<int>>> boxes;
|
||||||
|
|
||||||
post_processor_.BoxesFromBitmap(pred_map, &boxes, bit_map, det_db_box_thresh,
|
boxes =
|
||||||
det_db_unclip_ratio, det_db_score_mode);
|
post_processor_.BoxesFromBitmap(pred_map, bit_map, det_db_box_thresh,
|
||||||
|
det_db_unclip_ratio, det_db_score_mode);
|
||||||
|
|
||||||
post_processor_.FilterTagDetRes(&boxes, ratio_h, ratio_w, im_info);
|
boxes = post_processor_.FilterTagDetRes(boxes, ratio_h, ratio_w, im_info);
|
||||||
|
|
||||||
// boxes to boxes_result
|
// boxes to boxes_result
|
||||||
for (int i = 0; i < boxes.size(); i++) {
|
for (int i = 0; i < boxes.size(); i++) {
|
||||||
|
@@ -36,7 +36,7 @@ void PPOCRSystemv2::Detect(cv::Mat* img,
|
|||||||
void PPOCRSystemv2::Recognize(cv::Mat* img,
|
void PPOCRSystemv2::Recognize(cv::Mat* img,
|
||||||
fastdeploy::vision::OCRResult* result) {
|
fastdeploy::vision::OCRResult* result) {
|
||||||
std::tuple<std::string, float> rec_result;
|
std::tuple<std::string, float> rec_result;
|
||||||
|
this->recognizer->rec_image_shape[1] = 32;
|
||||||
this->recognizer->Predict(img, &rec_result);
|
this->recognizer->Predict(img, &rec_result);
|
||||||
|
|
||||||
result->text.push_back(std::get<0>(rec_result));
|
result->text.push_back(std::get<0>(rec_result));
|
||||||
|
@@ -94,7 +94,6 @@ bool PPOCRSystemv3::Predict(cv::Mat* img,
|
|||||||
for (int i = 0; i < img_list.size(); i++) {
|
for (int i = 0; i < img_list.size(); i++) {
|
||||||
if ((result->cls_labels)[i] % 2 == 1 &&
|
if ((result->cls_labels)[i] % 2 == 1 &&
|
||||||
(result->cls_scores)[i] > this->classifier->cls_thresh) {
|
(result->cls_scores)[i] > this->classifier->cls_thresh) {
|
||||||
std::cout << "Rotate this image " << std::endl;
|
|
||||||
cv::rotate(img_list[i], img_list[i], 1);
|
cv::rotate(img_list[i], img_list[i], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -250,9 +250,8 @@ float PostProcessor::BoxScoreFast(std::vector<std::vector<float>> box_array,
|
|||||||
|
|
||||||
//这个应该是DB(差分二值化)相关的内容,方法从 Bitmap 图中获取检测框
|
//这个应该是DB(差分二值化)相关的内容,方法从 Bitmap 图中获取检测框
|
||||||
//涉及到box_thresh(低于这个阈值的boxs不予显示)和det_db_unclip_ratio(文本框扩张的系数,关系到文本框的大小)
|
//涉及到box_thresh(低于这个阈值的boxs不予显示)和det_db_unclip_ratio(文本框扩张的系数,关系到文本框的大小)
|
||||||
void PostProcessor::BoxesFromBitmap(
|
std::vector<std::vector<std::vector<int>>> PostProcessor::BoxesFromBitmap(
|
||||||
const cv::Mat pred, std::vector<std::vector<std::vector<int>>> *boxes,
|
const cv::Mat pred, const cv::Mat bitmap, const float &box_thresh,
|
||||||
const cv::Mat bitmap, const float &box_thresh,
|
|
||||||
const float &det_db_unclip_ratio, const std::string &det_db_score_mode) {
|
const float &det_db_unclip_ratio, const std::string &det_db_score_mode) {
|
||||||
const int min_size = 3;
|
const int min_size = 3;
|
||||||
const int max_candidates = 1000;
|
const int max_candidates = 1000;
|
||||||
@@ -269,6 +268,8 @@ void PostProcessor::BoxesFromBitmap(
|
|||||||
int num_contours =
|
int num_contours =
|
||||||
contours.size() >= max_candidates ? max_candidates : contours.size();
|
contours.size() >= max_candidates ? max_candidates : contours.size();
|
||||||
|
|
||||||
|
std::vector<std::vector<std::vector<int>>> boxes;
|
||||||
|
|
||||||
for (int _i = 0; _i < num_contours; _i++) {
|
for (int _i = 0; _i < num_contours; _i++) {
|
||||||
if (contours[_i].size() <= 2) {
|
if (contours[_i].size() <= 2) {
|
||||||
continue;
|
continue;
|
||||||
@@ -318,45 +319,42 @@ void PostProcessor::BoxesFromBitmap(
|
|||||||
0, float(dest_height)))};
|
0, float(dest_height)))};
|
||||||
intcliparray.push_back(a);
|
intcliparray.push_back(a);
|
||||||
}
|
}
|
||||||
boxes->push_back(intcliparray);
|
boxes.push_back(intcliparray);
|
||||||
|
|
||||||
} // end for
|
} // end for
|
||||||
// return true;
|
return boxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//方法根据识别结果获取目标框位置
|
std::vector<std::vector<std::vector<int>>> PostProcessor::FilterTagDetRes(
|
||||||
void PostProcessor::FilterTagDetRes(
|
std::vector<std::vector<std::vector<int>>> boxes, float ratio_h,
|
||||||
std::vector<std::vector<std::vector<int>>> *boxes, const float ratio_h,
|
float ratio_w, const std::map<std::string, std::array<float, 2>> &im_info) {
|
||||||
const float ratio_w,
|
|
||||||
const std::map<std::string, std::array<float, 2>> &im_info) {
|
|
||||||
int oriimg_h = im_info.at("input_shape")[0];
|
int oriimg_h = im_info.at("input_shape")[0];
|
||||||
int oriimg_w = im_info.at("input_shape")[1];
|
int oriimg_w = im_info.at("input_shape")[1];
|
||||||
|
|
||||||
for (int n = 0; n < boxes->size(); n++) {
|
std::vector<std::vector<std::vector<int>>> root_points;
|
||||||
(*boxes)[n] = OrderPointsClockwise((*boxes)[n]);
|
for (int n = 0; n < boxes.size(); n++) {
|
||||||
for (int m = 0; m < (*boxes)[0].size(); m++) {
|
boxes[n] = OrderPointsClockwise(boxes[n]);
|
||||||
(*boxes)[n][m][0] /= ratio_w;
|
for (int m = 0; m < boxes[0].size(); m++) {
|
||||||
(*boxes)[n][m][1] /= ratio_h;
|
boxes[n][m][0] /= ratio_w;
|
||||||
|
boxes[n][m][1] /= ratio_h;
|
||||||
|
|
||||||
(*boxes)[n][m][0] = int(_min(_max((*boxes)[n][m][0], 0), oriimg_w - 1));
|
boxes[n][m][0] = int(_min(_max(boxes[n][m][0], 0), oriimg_w - 1));
|
||||||
(*boxes)[n][m][1] = int(_min(_max((*boxes)[n][m][1], 0), oriimg_h - 1));
|
boxes[n][m][1] = int(_min(_max(boxes[n][m][1], 0), oriimg_h - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//此时已经拿到所有的点. 再进行下面的筛选
|
for (int n = 0; n < boxes.size(); n++) {
|
||||||
for (int n = (*boxes).size() - 1; n >= 0; n--) {
|
|
||||||
int rect_width, rect_height;
|
int rect_width, rect_height;
|
||||||
rect_width = int(sqrt(pow((*boxes)[n][0][0] - (*boxes)[n][1][0], 2) +
|
rect_width = int(sqrt(pow(boxes[n][0][0] - boxes[n][1][0], 2) +
|
||||||
pow((*boxes)[n][0][1] - (*boxes)[n][1][1], 2)));
|
pow(boxes[n][0][1] - boxes[n][1][1], 2)));
|
||||||
rect_height = int(sqrt(pow((*boxes)[n][0][0] - (*boxes)[n][3][0], 2) +
|
rect_height = int(sqrt(pow(boxes[n][0][0] - boxes[n][3][0], 2) +
|
||||||
pow((*boxes)[n][0][1] - (*boxes)[n][3][1], 2)));
|
pow(boxes[n][0][1] - boxes[n][3][1], 2)));
|
||||||
|
if (rect_width <= 4 || rect_height <= 4) continue;
|
||||||
//小于4的删除掉. erase配合逆序遍历.
|
root_points.push_back(boxes[n]);
|
||||||
if (rect_width <= 4 || rect_height <= 4) {
|
|
||||||
boxes->erase(boxes->begin() + n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return root_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ocr
|
} // namespace ocr
|
||||||
} // namespace vision
|
} // namespace vision
|
||||||
} // namespace fastdeploy
|
} // namespace fastdeploy
|
@@ -52,15 +52,13 @@ class PostProcessor {
|
|||||||
float BoxScoreFast(std::vector<std::vector<float>> box_array, cv::Mat pred);
|
float BoxScoreFast(std::vector<std::vector<float>> box_array, cv::Mat pred);
|
||||||
float PolygonScoreAcc(std::vector<cv::Point> contour, cv::Mat pred);
|
float PolygonScoreAcc(std::vector<cv::Point> contour, cv::Mat pred);
|
||||||
|
|
||||||
void BoxesFromBitmap(const cv::Mat pred,
|
std::vector<std::vector<std::vector<int>>> BoxesFromBitmap(
|
||||||
std::vector<std::vector<std::vector<int>>> *boxes,
|
const cv::Mat pred, const cv::Mat bitmap, const float &box_thresh,
|
||||||
const cv::Mat bitmap, const float &box_thresh,
|
const float &det_db_unclip_ratio, const std::string &det_db_score_mode);
|
||||||
const float &det_db_unclip_ratio,
|
|
||||||
const std::string &det_db_score_mode);
|
|
||||||
|
|
||||||
void FilterTagDetRes(
|
std::vector<std::vector<std::vector<int>>> FilterTagDetRes(
|
||||||
std::vector<std::vector<std::vector<int>>> *boxes, const float ratio_h,
|
std::vector<std::vector<std::vector<int>>> boxes, float ratio_h,
|
||||||
const float ratio_w,
|
float ratio_w,
|
||||||
const std::map<std::string, std::array<float, 2>> &im_info);
|
const std::map<std::string, std::array<float, 2>> &im_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -65,8 +65,6 @@ void CpuInfer(const std::string& det_model_dir,
|
|||||||
if (!rec_model_dir.empty()) {
|
if (!rec_model_dir.empty()) {
|
||||||
auto rec_option = fastdeploy::RuntimeOption();
|
auto rec_option = fastdeploy::RuntimeOption();
|
||||||
rec_option.UseCpu();
|
rec_option.UseCpu();
|
||||||
rec_option.UsePaddleBackend(); // OCRv2的rec模型暂不支持ORT后端
|
|
||||||
|
|
||||||
rec_model = fastdeploy::vision::ocr::Recognizer(
|
rec_model = fastdeploy::vision::ocr::Recognizer(
|
||||||
rec_model_file, rec_params_file, rec_label, rec_option);
|
rec_model_file, rec_params_file, rec_label, rec_option);
|
||||||
|
|
||||||
|
@@ -65,7 +65,6 @@ def build_det_option(args):
|
|||||||
|
|
||||||
def build_cls_option(args):
|
def build_cls_option(args):
|
||||||
option = fd.RuntimeOption()
|
option = fd.RuntimeOption()
|
||||||
option.use_paddle_backend()
|
|
||||||
|
|
||||||
if args.device.lower() == "gpu":
|
if args.device.lower() == "gpu":
|
||||||
option.use_gpu()
|
option.use_gpu()
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
# PaddleOCR 模型部署
|
# PaddleOCR 模型部署
|
||||||
|
|
||||||
## 模型版本说明
|
## PaddleOCR系列预测模型下载
|
||||||
|
|
||||||
- [PaddleOCR Release/2.5](https://github.com/PaddlePaddle/PaddleOCR/tree/release/2.5)
|
| 模型 | 参数文件大小 | 说明 | 模型格式 | 版本 |
|
||||||
|
|:---------------------------------------------------------------- |:----- |:----- | :------- | :--- |
|
||||||
|
| [ch_PP-OCRv3_det](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_infer.tar) | 3.8MB | OCRv3的检测模型 | PADDLE | [Release/2.6](https://github.com/PaddlePaddle/PaddleOCR) |
|
||||||
|
| [ch_PP-OCRv3_rec](https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_infer.tar) | 12.4MB | OCRv3的识别模型 | PADDLE | [Release/2.6](https://github.com/PaddlePaddle/PaddleOCR) |
|
||||||
|
| [ch_ppocr_mobile_v2.0_cls](https://bj.bcebos.com/paddlehub/fastdeploy/ch_ppocr_mobile_v2.0_cls_infer.tar.gz) | 1.38MB | OCRv2和v3通用的分类模型 | PADDLE | [Release/2.6](https://github.com/PaddlePaddle/PaddleOCR) |
|
||||||
|
| [ch_PP-OCRv2_det](https://paddleocr.bj.bcebos.com/PP-OCRv2/chinese/ch_PP-OCRv2_det_infer.tar)| 3MB | OCRv2的检测模型 | PADDLE | [Release/2.6](https://github.com/PaddlePaddle/PaddleOCR) |
|
||||||
|
| [ch_PP-OCRv2_rec](https://bj.bcebos.com/paddlehub/fastdeploy/ch_PP-OCRv2_rec_infer) | 8.5MB | OCRv2的识别模型 | PADDLE | [Release/2.6](https://github.com/PaddlePaddle/PaddleOCR) |
|
||||||
|
|
||||||
目前FastDeploy支持如下模型的部署
|
|
||||||
|
|
||||||
- [PaddleOCRv3系列模型](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/models_list.md)
|
|
||||||
|
|
||||||
## 准备PaddleOCRv3部署模型
|
|
||||||
用户在[PP-OCR系列模型列表](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/models_list.md)下载相应的的OCRv3系列推理模型即可.
|
|
||||||
|
|
||||||
## 详细部署文档
|
## 详细部署文档
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user