文章目录
OCR 中文字符识别
本章节在 Lockzhiner Vision Module 上基于OcrLiteNcnn模型, 实现了一个OCR中文字符识别系统。
1. 基本知识讲解
1.1 OCR中文字符识别简介
光学字符识别(OCR)是一种将图像中的文字转换为可编辑文本的技术,其中中文OCR因汉字结构复杂、字形多样而更具挑战性。通过图像预处理、深度学习模型(如CNN+RNN)及语言校正,系统能精准识别印刷体或手写中文,并适应不同字体、排版与复杂背景。该技术广泛应用于文档数字化、证件识别、智能办公等领域,尤其在处理海量纸质资料、提升信息处理效率方面具有重要意义。
1.2 OCR中文字符识别的核心步骤
要实现一个OCR中文字符识别,主要包含以下几个步骤:
- 图像预处理:
- 灰度化与二值化:将彩色图像转换为黑白图像,增强文字与背景的对比度。
- 降噪与倾斜校正:去除噪声,校正因拍摄导致的倾斜角度。
- 文字定位与区域检测:
- 一般利用深度学习模型来检测图像中的文字区域。
- 字符分割:
- 将连续文字块拆分为单个字符,解决粘连字符问题。
- 特征提取与识别:
- 提取字符的几何特征或通过深度学习模型生成抽象特征。
- 后处理与校正
2. C++ API 文档
2.1 Net类
2.1.1 头文件
#include <ncnn/net.h>
- 作用:用于声明Net类,使得Net类可以在当前文件中使用。
2.1.2 构造类函数
ncnn::Net dbnet;
- 作用:创建一个Net类型的对象实例,用于实现文字区域的检测。
- 参数说明:
- 无
- 返回值:
- 无
ncnn::Net ocr_net;
- 作用:创建一个Net类型的对象实例,用于实现文字的识别。
- 参数说明:
- 无
- 返回值:
- 无
2.1.3 load_param函数
int load_param(const DataReader& dr);
- 参数说明:
- dr:传入的参数文件路径。
- 返回值:
- 返回值为0表示加载参数文件成功。
2.1.4 load_model函数
int load_model(const DataReader& dr);
- 参数说明:
- dr:传入的模型文件路径。
- 返回值:返回值为0表示加载模型成功。
2.1.5 from_pixels函数
ncnn::Mat::from_pixels(srcResize.data, ncnn::Mat::PIXEL_BGR, srcResize.cols, srcResize.rows);
- 参数说明:
- srcResize.data:输入图像的像素数据指针。
- ncnn::Mat::PIXEL_BGR:输入像素数据的颜色格式。
- srcResize.cols:输入图像的宽度。
- srcResize.rows:输入图像的高度。
- 返回值:适配成 NCNN 所需的格式的包含图像数据的新对象。
2.2 Extractor类
2.2.1 头文件
#include <ncnn/net.h>
- 作用:用于声明Extractor类,使得Extractor类可以在当前文件中使用。
2.2.2 构造类函数
ncnn::Extractor dbnet_extractor = dbnet.create_extractor();
- 作用:从已经加载了神经网络模型的 dbnet 中创建一个 Extractor 实例,用于执行文本区域检测的推理任务。
- 参数说明:
- 无
- 返回值:
- 无
cnn::Extractor ocr_extractor = ocr_net.create_extractor();
- 作用:从已经加载了神经网络模型的 ocr_net 中创建一个 Extractor 实例,用于执行文本识别的推理任务。
- 参数说明:
- 无
- 返回值:
- 无
3. OCR 中文字符识别代码解析
3.1 流程图
开始
│
├── 参数检查 (argc == 7)
│ └── 错误 → 输出Usage并退出
│
├── 加载字符集 keys.txt 到 keys 向量
│ └── 文件未找到或格式错误 → 错误退出
│
├── 初始化 DBNet 和 OCR 模型
│ ├── 禁用不支持的功能
│ ├── 加载模型参数和权重文件
│ └── 任一模型加载失败 → 错误退出
│
├── 读取并预处理输入图像
│ ├── 计算缩放参数
│ ├── resize 图像
│ └── 准备 NCNN 输入数据
│
├── 文本检测
│ ├── 模型推理
│ ├── findRsBoxes() 查找文本框
│ └── 坐标还原回原图尺寸
│
├── 文本识别
│ ├── 裁剪文本区域
│ ├── processFrame() 进行OCR识别
│ └── 结果保存至文本框结构体
│
├── 结果排序与可视化
│ ├── 根据中心点排序文本框
│ ├── 绘制文本框边界
│ ├── 输出识别文本
│ └── 显示结果图像
│
└── 程序结束
3.2 核心代码解析
3.2.1 向量归一化
cv::Point2f normalize(const cv::Point2f& v);
- 作用:
- 计算向量长度并归一化,用于后续几何变换(如多边形扩展方向计算)。
- 参数说明:
- v:待归一化的二维向量。
- 返回值:
- 返回单位长度的向量,若输入向量为零向量则返回(0, 0)。
3.2.2 多边形边界扩张
std::vector<cv::Point> expandPolygon(const std::vector<cv::Point>& inBox, float distance);
- 作用:
- 基于邻边法线方向计算角平分线,向外扩展多边形边界,增强文本检测框的包容性。
- 参数说明:
- inBox:输入的多边形顶点集合。
- distance:扩展距离,控制文本框膨胀程度。
- 返回值:
- 返回扩展后的新多边形顶点集合。
3.2.3 文本检测框提取
std::vector<TextBox> findRsBoxes(const cv::Mat &fMapMat, const cv::Mat &norfMapMat, ScaleParam &s, const float boxScoreThresh, const float unClipRatio);
- 作用:
- 结合轮廓检测与UNet式后处理,生成最终文本检测框。
- 参数说明:
- fMapMat:DBNet输出的概率图。
- norfMapMat:二值化后的概率图。
- s:图像缩放参数结构体。
- boxScoreThresh:文本框置信度阈值。
- unClipRatio:边界扩展系数。
- 返回值:
- 返回包含文本框坐标、置信度的结构体列表。
3.2.4 OCR文本识别
void processFrame(Mat &src, ncnn::Net &ocr_net, const std::vector<std::string> &keys,
const float ocr_mean[], const float ocr_norm[], int dstHeight, std::string &outputText);
- 作用:
- 执行图像预处理,模型推理,Softmax解码,字符拼接全流程。
- 参数说明:
- src:待识别的文本区域图像。
- ocr_net:OCR识别模型。
- keys:字符表(字符到索引映射)。
- ocr_mean:图像归一化均值。
- ocr_norm:图像归一化标准差。
- dstHeight:目标高度。
- outputText:输出识别结果字符串。
- 返回值:
- 无
3.3 完整代码实现
👉 点击获取完整源码
4. 编译调试
4.1 编译环境搭建
- 请确保你已经按照 开发环境搭建指南 正确配置了开发环境。
- 同时已经正确连接开发板。
4.2 Cmake介绍
cmake_minimum_required(VERSION 3.10)
project(ocr_synthesis)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 定义项目根目录路径
set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../..")
message("PROJECT_ROOT_PATH = " ${PROJECT_ROOT_PATH})
include("${PROJECT_ROOT_PATH}/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake")
# 定义 OpenCV SDK 路径
set(OpenCV_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/opencv-mobile-4.10.0-lockzhiner-vision-module")
set(OpenCV_DIR "${OpenCV_ROOT_PATH}/lib/cmake/opencv4")
find_package(OpenCV REQUIRED)
set(OPENCV_LIBRARIES "${OpenCV_LIBS}")
# 定义 LockzhinerVisionModule SDK 路径
set(LockzhinerVisionModule_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk")
set(LockzhinerVisionModule_DIR "${LockzhinerVisionModule_ROOT_PATH}/lib/cmake/lockzhiner_vision_module")
find_package(LockzhinerVisionModule REQUIRED)
# ncnn配置
set(NCNN_ROOT_DIR "${PROJECT_ROOT_PATH}/third_party/ncnn-20240820-lockzhiner-vision-module") # 确保third_party层级存在
message(STATUS "Checking ncnn headers in: ${NCNN_ROOT_DIR}/include/ncnn")
# 验证头文件存在
if(NOT EXISTS "${NCNN_ROOT_DIR}/include/ncnn/net.h")
message(FATAL_ERROR "ncnn headers not found. Confirm the directory contains ncnn: ${NCNN_ROOT_DIR}")
endif()
set(NCNN_INCLUDE_DIRS "${NCNN_ROOT_DIR}/include")
set(NCNN_LIBRARIES "${NCNN_ROOT_DIR}/lib/libncnn.a")
add_executable(Test-OcrLite OcrLite.cc)
target_include_directories(Test-OcrLite PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS} ${NCNN_INCLUDE_DIRS})
target_link_libraries(Test-OcrLite PRIVATE ${OPENCV_LIBRARIES} ${NCNN_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES})
install(
TARGETS Test-OcrLite
RUNTIME DESTINATION .
)
4.3 编译项目
使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目
# 进入Demo所在目录
cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/Cpp_example/D07_ocr_synthesis
# 创建编译目录
rm -rf build && mkdir build && cd build
# 配置交叉编译工具链
export TOOLCHAIN_ROOT_PATH="/LockzhinerVisionModuleWorkSpace/arm-rockchip830-linux-uclibcgnueabihf"
# 使用cmake配置项目
cmake ..
# 执行编译项目
make -j8 && make install
在执行完上述命令后,会在build目录下生成可执行文件。
5. 执行结果
5.1 运行前准备
- 请确保已经下载了模型,并保存在当前目录下。
5.2 运行过程
chmod 777 Test-OcrLite
./Test-OcrLite <image_path> dbnet_op.param dbnet_op.bin crnn_lite_op.param crnn_lite_op.bin keys.txt
5.3 运行结果
-
原始图像
-
识别结果
6. 总结
通过上述内容,我们成功实现了一个简单的OCR中文字符识别系统,包括:
- 加载模型和待识别图像。
- 进行文本区域检测推理和文本识别推理。
rockchip830-linux-uclibcgnueabihf"
使用cmake配置项目
cmake ...
执行编译项目
make -j8 && make install
在执行完上述命令后,会在build目录下生成可执行文件。
5. 执行结果
5.1 运行前准备
- 请确保已经下载了模型,并保存在当前目录下。
5.2 运行过程
chmod 777 Test-OcrLite
./Test-OcrLite <image_path> dbnet_op.param dbnet_op.bin crnn_lite_op.param crnn_lite_op.bin keys.txt
5.3 运行结果
-
原始图像
-
识别结果
6. 总结
通过上述内容,我们成功实现了一个简单的OCR中文字符识别系统,包括:
- 加载模型和待识别图像。
- 进行文本区域检测推理和文本识别推理。
- 打印并保存推理结果。
🚀 开发者生态:
- 订阅 更新日志 获取新模型支持
🔧 问题反馈:
遇到技术问题?请到凌智视觉模块官方仓库**凌智视觉模块** 提交Issue