提交 acae8ea8 编写于 作者: L LDOUBLEV

update readme

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