diff --git a/deploy/imgs/demo.png b/deploy/imgs/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..761bfb9baa505cf3450d0702151555bba4196ec5 Binary files /dev/null and b/deploy/imgs/demo.png differ diff --git a/deploy/lite/db_post_process.cc b/deploy/lite/db_post_process.cc index 53a796de9c8ae7aadbe689ba4c1928073ee0f654..78d1194167abb58263a611996f24900344a471b3 100644 --- a/deploy/lite/db_post_process.cc +++ b/deploy/lite/db_post_process.cc @@ -12,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "db_post_process.h" // NOLINT +#include "db_post_process.h" // NOLINT #include #include -void GetContourArea(std::vector> box, - float unclip_ratio, - float& distance) { +void GetContourArea(std::vector> box, float unclip_ratio, + float &distance) { int pts_num = 4; float area = 0.0f; float dist = 0.0f; @@ -78,34 +77,38 @@ std::vector> Mat2Vector(cv::Mat mat) { } bool XsortFp32(std::vector a, std::vector b) { - if (a[0] != b[0]) return a[0] < b[0]; + if (a[0] != b[0]) + return a[0] < b[0]; return false; } bool XsortInt(std::vector a, std::vector b) { - if (a[0] != b[0]) return a[0] < b[0]; + if (a[0] != b[0]) + return a[0] < b[0]; return false; } -std::vector> OrderPointsClockwise( - std::vector> pts) { +std::vector> +OrderPointsClockwise(std::vector> pts) { std::vector> box = pts; std::sort(box.begin(), box.end(), XsortInt); std::vector> leftmost = {box[0], box[1]}; std::vector> rightmost = {box[2], box[3]}; - if (leftmost[0][1] > leftmost[1][1]) std::swap(leftmost[0], leftmost[1]); + if (leftmost[0][1] > leftmost[1][1]) + std::swap(leftmost[0], leftmost[1]); - if (rightmost[0][1] > rightmost[1][1]) std::swap(rightmost[0], rightmost[1]); + if (rightmost[0][1] > rightmost[1][1]) + std::swap(rightmost[0], rightmost[1]); - std::vector> rect = { - leftmost[0], rightmost[0], rightmost[1], leftmost[1]}; + std::vector> rect = {leftmost[0], rightmost[0], rightmost[1], + leftmost[1]}; return rect; } -std::vector> GetMiniBoxes(cv::RotatedRect box, float& ssid) { - ssid = box.size.width >= box.size.height ? box.size.height : box.size.width; +std::vector> GetMiniBoxes(cv::RotatedRect box, float &ssid) { + ssid = std::max(box.size.width, box.size.height); cv::Mat points; cv::boxPoints(box, points); @@ -146,14 +149,14 @@ float BoxScoreFast(std::vector> box_array, cv::Mat pred) { float box_x[4] = {array[0][0], array[1][0], array[2][0], array[3][0]}; float box_y[4] = {array[0][1], array[1][1], array[2][1], array[3][1]}; - int xmin = clamp( - int(std::floorf(*(std::min_element(box_x, box_x + 4)))), 0, width - 1); - int xmax = clamp( - int(std::ceilf(*(std::max_element(box_x, box_x + 4)))), 0, width - 1); - int ymin = clamp( - int(std::floorf(*(std::min_element(box_y, box_y + 4)))), 0, height - 1); - int ymax = clamp( - int(std::ceilf(*(std::max_element(box_y, box_y + 4)))), 0, height - 1); + int xmin = clamp(int(std::floorf(*(std::min_element(box_x, box_x + 4)))), 0, + width - 1); + int xmax = clamp(int(std::ceilf(*(std::max_element(box_x, box_x + 4)))), 0, + width - 1); + int ymin = clamp(int(std::floorf(*(std::min_element(box_y, box_y + 4)))), 0, + height - 1); + int ymax = clamp(int(std::ceilf(*(std::max_element(box_y, box_y + 4)))), 0, + height - 1); cv::Mat mask; mask = cv::Mat::zeros(ymax - ymin + 1, xmax - xmin + 1, CV_8UC1); @@ -163,7 +166,7 @@ float BoxScoreFast(std::vector> box_array, cv::Mat pred) { root_point[1] = cv::Point(int(array[1][0]) - xmin, int(array[1][1]) - ymin); root_point[2] = cv::Point(int(array[2][0]) - xmin, int(array[2][1]) - ymin); root_point[3] = cv::Point(int(array[3][0]) - xmin, int(array[3][1]) - ymin); - const cv::Point* ppt[1] = {root_point}; + const cv::Point *ppt[1] = {root_point}; int npt[] = {4}; cv::fillPoly(mask, ppt, npt, 1, cv::Scalar(1)); @@ -175,10 +178,9 @@ float BoxScoreFast(std::vector> box_array, cv::Mat pred) { return score; } -std::vector>> BoxesFromBitmap( - const cv::Mat pred, - const cv::Mat bitmap, - std::map Config) { +std::vector>> +BoxesFromBitmap(const cv::Mat pred, const cv::Mat bitmap, + std::map Config) { const int min_size = 3; const int max_candidates = 1000; const float box_thresh = float(Config["det_db_box_thresh"]); @@ -190,8 +192,8 @@ std::vector>> BoxesFromBitmap( std::vector> contours; std::vector hierarchy; - cv::findContours( - bitmap, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE); + cv::findContours(bitmap, contours, hierarchy, cv::RETR_LIST, + cv::CHAIN_APPROX_SIMPLE); int num_contours = contours.size() >= max_candidates ? max_candidates : contours.size(); @@ -213,7 +215,8 @@ std::vector>> BoxesFromBitmap( float score; score = BoxScoreFast(array, pred); // end box_score_fast - if (score < box_thresh) continue; + if (score < box_thresh) + continue; // start for unclip cv::RotatedRect points = Unclip(box_for_unclip, unclip_ratio); @@ -222,35 +225,31 @@ std::vector>> BoxesFromBitmap( cv::RotatedRect clipbox = points; auto cliparray = GetMiniBoxes(clipbox, ssid); - if (ssid < min_size + 2) continue; + if (ssid < min_size + 2) + continue; int dest_width = pred.cols; int dest_height = pred.rows; std::vector> intcliparray; for (int num_pt = 0; num_pt < 4; num_pt++) { - std::vector a{ - int(clamp( - roundf(cliparray[num_pt][0] / float(width) * float(dest_width)), - float(0), - float(dest_width))), - int(clamp( - roundf(cliparray[num_pt][1] / float(height) * float(dest_height)), - float(0), - float(dest_height)))}; + std::vector a{int(clamp(roundf(cliparray[num_pt][0] / float(width) * + float(dest_width)), + float(0), float(dest_width))), + int(clamp(roundf(cliparray[num_pt][1] / float(height) * + float(dest_height)), + float(0), float(dest_height)))}; intcliparray.push_back(a); } boxes.push_back(intcliparray); - } // end for + } // end for return boxes; } -std::vector>> FilterTagDetRes( - std::vector>> boxes, - float ratio_h, - float ratio_w, - cv::Mat srcimg) { +std::vector>> +FilterTagDetRes(std::vector>> boxes, float ratio_h, + float ratio_w, cv::Mat srcimg) { int oriimg_h = srcimg.rows; int oriimg_w = srcimg.cols; @@ -272,7 +271,8 @@ std::vector>> FilterTagDetRes( pow(boxes[n][0][1] - boxes[n][1][1], 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))); - if (rect_width <= 10 || rect_height <= 10) continue; + if (rect_width <= 10 || rect_height <= 10) + continue; root_points.push_back(boxes[n]); } return root_points; diff --git a/deploy/lite/readme.md b/deploy/lite/readme.md index 7e7d407d7146d0a227813a690ba779fe0d55ec20..604ce0a91eb309c12ea0687fae82b5c17a237090 100644 --- a/deploy/lite/readme.md +++ b/deploy/lite/readme.md @@ -1,6 +1,6 @@ # PaddleOCR 模型部署 -PaddleOCR是集训练、预测、部署于一体的实用OCR工具库。本教程将介绍在安卓移动端部署PaddleOCR超轻量中文检测、识别模型的主要流程。 +PaddleOCR是集训练、预测、端侧部署于一体的实用OCR工具库。本教程将介绍在安卓移动端部署PaddleOCR超轻量中文检测、识别模型的主要流程。 ## 1. 准备环境 @@ -144,9 +144,9 @@ wget https://paddleocr.bj.bcebos.com/ch_models/ch_rec_mv3_crnn_infer.tar && tar # 进入OCR demo的工作目录 cd demo/cxx/ocr/ # 将C++预测动态库so文件复制到debug文件夹中 - cp ../../../cxx/lib/libpaddle_light_api_shared.so ./debug/ + cp ../../../../cxx/lib/libpaddle_light_api_shared.so ./debug/ ``` - 准备测试图像,以`PaddleOCR/doc/imgs/12.jpg`为例,将测试的图像复制到`demo/cxx/ocr/debug/`文件夹下。 + 准备测试图像,以`PaddleOCR/doc/imgs/11.jpg`为例,将测试的图像复制到`demo/cxx/ocr/debug/`文件夹下。 准备字典文件,中文超轻量模型的字典文件是`PaddleOCR/ppocr/utils/ppocr_keys_v1.txt`,将其复制到`demo/cxx/ocr/debug/`文件夹下。 执行完成后,ocr文件夹下将有如下文件格式: @@ -156,16 +156,17 @@ demo/cxx/ocr/ |-- debug/ | |--ch_det_mv3_db_opt.nb 优化后的检测模型文件 | |--ch_rec_mv3_crnn_opt.nb 优化后的识别模型文件 -| |--12.jpg 待测试图像 +| |--11.jpg 待测试图像 | |--ppocr_keys_v1.txt 字典文件 | |--libpaddle_light_api_shared.so C++预测库文件 -|-- utils/ -| |-- clipper.cpp Clipper库的cpp文件 -| |-- clipper.hpp Clipper库的hpp文件 -| |-- crnn_process.cpp 识别模型CRNN的预处理和后处理cpp文件 -| |-- db_post_process.cpp 检测模型DB的后处理cpp文件 +|-- config.txt DB-CRNN超参数配置 +|-- crnn_process.cc 识别模型CRNN的预处理和后处理文件 +|-- crnn_process.h +|-- db_post_process.cc 检测模型DB的后处理文件 +|-- db_post_process.h |-- Makefile 编译文件 |-- ocr_db_crnn.cc C++预测源文件 + ``` 5. 启动调试 @@ -184,7 +185,10 @@ demo/cxx/ocr/ adb shell cd /data/local/tmp/debug export LD_LIBRARY_PATH=/data/local/tmp/debug:$LD_LIBRARY_PATH - ./ocr_db_crnn ch_det_mv3_db_opt.nb ch_rec_mv3_crnn_opt.nb ./12.jpg + ./ocr_db_crnn ch_det_mv3_db_opt.nb ch_rec_mv3_crnn_opt.nb ./11.jpg ppocr_keys_v1.txt ``` 如果对代码做了修改,则需要重新编译并push到手机上。 + + 运行效果如下: + ![](..imgs/demo.png)