• 【opencv】dnn示例-scene_text_detection.cpp 场景文本区域检测


    1231720d3cfefd83730932b9a6cf53c6.png

    63d560da5bec4e2b1459facb13d50753.png

    模型下载:

    1. - DB_IC15_resnet50.onnx:
    2. url: https://drive.google.com/uc?export=dowload&id=17_ABp79PlFt9yPCxSaarVc_DKTmrSGGf
    3. sha: bef233c28947ef6ec8c663d20a2b326302421fa3
    4. recommended parameter setting: -inputHeight=736, -inputWidth=1280;
    5. description: This model is trained on ICDAR2015, so it can only detect English text instances.
    6. - DB_IC15_resnet18.onnx:
    7. url: https://drive.google.com/uc?export=dowload&id=1vY_KsDZZZb_svd5RT6pjyI8BS1nPbBSX
    8. sha: 19543ce09b2efd35f49705c235cc46d0e22df30b
    9. recommended parameter setting: -inputHeight=736, -inputWidth=1280;
    10. description: This model is trained on ICDAR2015, so it can only detect English text instances.
    11. - DB_TD500_resnet50.onnx:
    12. url: https://drive.google.com/uc?export=dowload&id=19YWhArrNccaoSza0CfkXlA8im4-lAGsR
    13. sha: 1b4dd21a6baa5e3523156776970895bd3db6960a
    14. recommended parameter setting: -inputHeight=736, -inputWidth=736;
    15. description: This model is trained on MSRA-TD500, so it can detect both English and Chinese text instances.
    16. - DB_TD500_resnet18.onnx:
    17. url: https://drive.google.com/uc?export=dowload&id=1sZszH3pEt8hliyBlTmB-iulxHP1dCQWV
    18. sha: 8a3700bdc13e00336a815fc7afff5dcc1ce08546
    19. recommended parameter setting: -inputHeight=736, -inputWidth=736;
    20. description: This model is trained on MSRA-TD500, so it can detect both English and Chinese text instances.
    21. https://drive.google.com/drive/folders/1T9n0HTP3X3Y_nJ0D1ekMhCQRHntORLJG
    22. https://drive.google.com/drive/folders/1qzNCHfUJOS0NEUOIKn69eCtxdlNPpWbq

    代码地址:

    1. https://github.com/MhLiao/DB
    2. https://github.com/opencv/opencv/blob/4.x/samples/dnn/scene_text_detection.cpp

    这个程序是一个基于OpenCV和C++的文本检测应用。它使用了不同的二值化(Differentiable Binarization)算法来实时检测场景文本,并用多边形框出。它主要适用于两种模式:一种是处理输入图片并显示结果,另一种是基于指定的数据集做性能评估。

    程序的核心流程分为以下几个部分:

    定义命令行参数:用于获取从命令行传递进来的参数,如输入图像的路径,模型的路径,输入模型的高、宽,二值化阈值,多边形阈值,候选区域的最大数量,unclip比例,以及是否是评估模式等信息。

    参数解析和检查:解析命令行输入的参数,并进行简单的检查,确保必要的参数没有遗漏,并且路径有效等。

    载入文本检测模型:装载预训练的DB(TextDetectionModel_DB)模型。此外,还设置了模型的一些参数,如二值化阈值(binarizeThreshold)、多边形阈值(polygonThreshold)、unclip比例(unclipRatio)以及最大候选项(maxCandidates)等。

    处理图像:通过Object Detection API的接口设置输入参数(scale、inputSize、mean),处理图像并使用网络模型进行文本检测。读取图片,对图片进行处理,并使用检测器检测图中的文本。

    显示结果:将检测到的文本区域通过多边形(polyline)画在图像上,并显示出来。如果是评估模式,还会额外显示每个测试图像的标注信息。

    如果是评估模式,程序还会处理一个包含多个测试图像路径的列表,对每个图像进行处理,并显示原始图像以及标注信息。

    总的来说,此程序可以读取图片或从摄像头获取图像,然后应用一种深度学习文本检测方法高效地检测图像中的文本区域,并将检测到的文本用绿色的多边形框起来。在评估模式下,程序会在指定的数据集上运行,并显示性能评估结果,通常这涉及预测准确度的度量。程序最后通过OpenCV窗口展示检测的结果,如果是在评估模式下,则同时显示真实的标注框。

    1. // 包含标准输入输出流库
    2. #include
    3. // 包含文件输入输出流库
    4. #include
    5. // 包含OpenCV图像处理库
    6. #include
    7. // 包含OpenCV高阶GUI处理库
    8. #include
    9. // 包含OpenCV深度神经网络模块库
    10. #include
    11. // 使用命名空间cv,cv::dnn以简化代码
    12. using namespace cv;
    13. using namespace cv::dnn;
    14. // 字符串常量声明 (参数解析所需要的关键字和说明)
    15. std::string keys =
    16. "{ help h | | Print help message. }"
    17. "{ inputImage i | td2.jpg| Path to an input image. Skip this argument to capture frames from a camera. }"
    18. "{ modelPath mp | DB_IC15_resnet18.onnx| Path to a binary .onnx file contains trained DB detector model. "
    19. "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}"
    20. "{ inputHeight ih |736| image height of the model input. It should be multiple by 32.}"
    21. "{ inputWidth iw |736| image width of the model input. It should be multiple by 32.}"
    22. "{ binaryThreshold bt |0.3| Confidence threshold of the binary map. }"
    23. "{ polygonThreshold pt |0.5| Confidence threshold of polygons. }"
    24. "{ maxCandidate max |200| Max candidates of polygons. }"
    25. "{ unclipRatio ratio |2.0| unclip ratio. }"
    26. "{ evaluate e |false| false: predict with input images; true: evaluate on benchmarks. }"
    27. "{ evalDataPath edp | | Path to benchmarks for evaluation. "
    28. "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}";
    29. // 定义一个用于字符串分割的静态函数
    30. static
    31. void split(const std::string& s, char delimiter, std::vector& elems)
    32. {
    33. // 首先清空传入的字符串向量
    34. elems.clear();
    35. // 初始化当前位置和之前位置变量
    36. size_t prev_pos = 0;
    37. size_t pos = 0;
    38. // 当能在字符串s中找到分隔符时执行循环体
    39. while ((pos = s.find(delimiter, prev_pos)) != std::string::npos)
    40. {
    41. // 将分隔符之前的字符串添加到字符串向量elems中
    42. elems.emplace_back(s.substr(prev_pos, pos - prev_pos));
    43. // 更新之前位置为当前找到的分隔符之后的位置
    44. prev_pos = pos + 1;
    45. }
    46. // 当最后一个分隔符后还有字符时,将剩余部分添加到elems
    47. if (prev_pos < s.size())
    48. elems.emplace_back(s.substr(prev_pos, s.size() - prev_pos));
    49. }
    50. // 程序的主函数
    51. int main(int argc, char** argv)
    52. {
    53. // 解析命令行参数
    54. CommandLineParser parser(argc, argv, keys);
    55. // 提供脚本及其使用方法的简介
    56. parser.about("Use this script to run the official PyTorch implementation (https://github.com/MhLiao/DB) of "
    57. "Real-time Scene Text Detection with Differentiable Binarization (https://arxiv.org/abs/1911.08947)\n"
    58. "The current version of this script is a variant of the original network without deformable convolution");
    59. // 如果未提供任何参数或需要帮助,则打印帮助信息
    60. if (argc == 0 || parser.has("help"))
    61. {
    62. parser.printMessage();
    63. return 0;
    64. }
    65. // 从命令行参数中获取具体参数值
    66. float binThresh = parser.get<float>("binaryThreshold");
    67. float polyThresh = parser.get<float>("polygonThreshold");
    68. uint maxCandidates = parser.get("maxCandidate");
    69. String modelPath = parser.get("modelPath");
    70. double unclipRatio = parser.get<double>("unclipRatio");
    71. int height = parser.get<int>("inputHeight");
    72. int width = parser.get<int>("inputWidth");
    73. // 检查解析的参数是否有错误
    74. if (!parser.check())
    75. {
    76. // 如果有错误则打印错误信息并退出程序
    77. parser.printErrors();
    78. return 1;
    79. }
    80. // 载入模型
    81. CV_Assert(!modelPath.empty());
    82. // 构造文本检测模型对象
    83. TextDetectionModel_DB detector(modelPath);
    84. // 设置模型的参数
    85. detector.setBinaryThreshold(binThresh)
    86. .setPolygonThreshold(polyThresh)
    87. .setUnclipRatio(unclipRatio)
    88. .setMaxCandidates(maxCandidates);
    89. // 模型输入的图像预处理参数
    90. double scale = 1.0 / 255.0;
    91. Size inputSize = Size(width, height);
    92. Scalar mean = Scalar(122.67891434, 116.66876762, 104.00698793);
    93. // 设置模型输入参数
    94. detector.setInputParams(scale, inputSize, mean);
    95. // 创建显示检测结果的窗口
    96. static const std::string winName = "TextDetectionModel";
    97. // 如果命令行参数中提供了评估模式开关
    98. if (parser.get<bool>("evaluate")) {
    99. // 进入评估模式
    100. // 从参数中获取评估数据集路径
    101. String evalDataPath = parser.get("evalDataPath");
    102. CV_Assert(!evalDataPath.empty());
    103. // 构造评估数据集中的测试列表文件路径
    104. String testListPath = evalDataPath + "/test_list.txt";
    105. // 打开测试列表文件
    106. std::ifstream testList;
    107. testList.open(testListPath);
    108. // 检测测试列表文件是否成功打开
    109. CV_Assert(testList.is_open());
    110. // 创建一个用于显示真实标注信息的窗口
    111. static const std::string winNameGT = "GT";
    112. // 定义一个字符串变量用于存储测试图像路径
    113. String testImgPath;
    114. // 读取评估数据集中的图片列表,并进行处理
    115. // 进入循环,通过文件流逐行读取测试图片路径
    116. while (std::getline(testList, testImgPath)) {
    117. // 组合出完整的测试图片路径
    118. String imgPath = evalDataPath + "/test_images/" + testImgPath;
    119. // 打印图片路径
    120. std::cout << "Image Path: " << imgPath << std::endl;
    121. // 使用OpenCV函数读取图片
    122. Mat frame = imread(samples::findFile(imgPath), IMREAD_COLOR);
    123. // 确保图片读取成功
    124. CV_Assert(!frame.empty());
    125. // 复制一个frame以便后续的标注
    126. Mat src = frame.clone();
    127. // Inference
    128. // 存储检测结果的向量
    129. std::vector> results;
    130. // 检测文本
    131. detector.detect(frame, results);
    132. // 使用多边形标注检测到的文本,并在窗口中显示
    133. polylines(frame, results, true, Scalar(0, 255, 0), 2);
    134. imshow(winName, frame);
    135. // load groundtruth
    136. // 从测试图片路径中除去后缀,获取图片名称
    137. String imgName = testImgPath.substr(0, testImgPath.length() - 4);
    138. // 组合出标注数据的完整路径
    139. String gtPath = evalDataPath + "/test_gts/" + imgName + ".txt";
    140. // 打开标注文件
    141. std::ifstream gtFile;
    142. gtFile.open(gtPath);
    143. // 确保标注文件打开成功
    144. CV_Assert(gtFile.is_open());
    145. // 存储真实标注数据的向量
    146. std::vector> gts;
    147. String gtLine;
    148. // 逐行读取标注文件
    149. while (std::getline(gtFile, gtLine)) {
    150. // 检索到最后一个逗号的位置,因为之后的内容是文字标注
    151. size_t splitLoc = gtLine.find_last_of(',');
    152. // 提取文字标注
    153. String text = gtLine.substr(splitLoc+1);
    154. // 如果文字标注中含有忽略标记则跳过
    155. if ( text == "###\r" || text == "1") {
    156. // 忽略难识别的实例
    157. continue;
    158. }
    159. // 除去文字标注部分,只保留坐标数据
    160. gtLine = gtLine.substr(0, splitLoc);
    161. // 临时变量存储分割后的字符串
    162. std::vector v;
    163. // 分割坐标数据
    164. split(gtLine, ',', v);
    165. // 存储解析后的坐标数据
    166. std::vector<int> loc;
    167. std::vector pts;
    168.                 // 将字符串类型的坐标数据转为整型,并逐点构造Point类型
    169. // 遍历解析完毕的字符串向量
    170. for (auto && s : v) {
    171. // 将字符串转换成整型并存储到整型向量中
    172. loc.push_back(atoi(s.c_str()));
    173. }
    174. // 从整型向量中构建Point对象,每个Point由一对坐标构成
    175. for (size_t i = 0; i < loc.size() / 2; i++) {
    176. // 创建点并添加到点集中
    177. pts.push_back(Point(loc[2 * i], loc[2 * i + 1]));
    178. }
    179. // 将点集添加到标准答案标注集中
    180. gts.push_back(pts);
    181. }
    182. // 在原图克隆图上标注真实的多边形文本区域
    183. polylines(src, gts, true, Scalar(0, 255, 0), 2);
    184. // 显示标注了真实文本区域的图片窗口
    185. imshow(winNameGT, src);
    186. // 等待任意键继续,用于暂停程序查看结果
    187. waitKey();
    188. }
    189. } else {
    190. // 如果不是评估模式,直接打开指定的图像文件
    191. CV_Assert(parser.has("inputImage"));
    192. // 读取指定路径的图像
    193. Mat frame = imread(samples::findFile(parser.get("inputImage")));
    194. // 确保读取的图像非空
    195. CV_Assert(!frame.empty());
    196. // 存储检测结果的向量
    197. std::vector> results;
    198. // 进行文本检测
    199. detector.detect(frame, results);
    200. // 将检测到的文本区域多边形轮廓标注在图像上
    201. polylines(frame, results, true, Scalar(0, 255, 0), 2);
    202. // 展示检测结果的窗口
    203. imshow(winName, frame);
    204. // 等待任意键继续,用于暂停程序查看结果
    205. waitKey();
    206. }
    207. // 程序正常退出,返回0
    208. return 0;
    209. }

    段代码实现了使用OpenCV和预先训练的深度学习模型来检测图片中的文本区域的功能。通过解析命令行参数,用户能够指定图片路径、模型路径、输入图片大小以及相应的检测阈值等参数。程序支持两种模式操作:

    普通模式:用户指定一张图片,程序将检测图片中的文本,并将检测结果以绿色多边形框标注在图片上,并将其展示出来。

    评估模式:用户指定一个包含多个图片以及对应文本区域标记的数据集,程序将检测这些图片中的文本区域,并将检测结果和真实的文本标记一起在窗口中展示出来,用以评估模型的检测效果。

    代码中还包含了图片的加载、模型参数的设置以及窗口创建等辅助步骤。

  • 相关阅读:
    centos jdk 安装
    椎弓根三角新算法
    Haskell网络编程:从数据采集到图片分析
    有效的括号(Java版)
    行为引擎-暴力破解
    Weblogic SSRF 漏洞(CVE-2014-4210)分析
    正则表达式
    Azure 开发者新闻快讯丨开发者6月大事记一览
    深度学习计算 - 参数管理
    初识Docker
  • 原文地址:https://blog.csdn.net/cxyhjl/article/details/137852747