Program.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. using OpenCvSharp;
  2. using PaddleOCRSharp;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using Tesseract;
  12. namespace OCRTest
  13. {
  14. internal class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. Console.WriteLine("请选择测试模式:");
  19. Console.WriteLine("1. 测试OCR识别引擎");
  20. Console.WriteLine("2. 创建训练项目示例");
  21. Console.WriteLine("3. 预处理训练图片");
  22. Console.WriteLine("4. 验证训练数据集");
  23. Console.WriteLine("5. 分析字符频率");
  24. Console.Write("\n请输入选项(1-5):");
  25. string choice = Console.ReadLine();
  26. switch (choice)
  27. {
  28. case "1":
  29. TestOCREngine();
  30. break;
  31. case "2":
  32. CreateTrainingProjectExample();
  33. break;
  34. case "3":
  35. PreprocessTrainingImagesExample();
  36. break;
  37. case "4":
  38. ValidateDatasetExample();
  39. break;
  40. case "5":
  41. AnalyzeCharactersExample();
  42. break;
  43. default:
  44. Console.WriteLine("无效选项,默认执行OCR识别测试");
  45. TestOCREngine();
  46. break;
  47. }
  48. }
  49. /// <summary>
  50. /// 测试新的OCR引擎
  51. /// </summary>
  52. static void TestOCREngine()
  53. {
  54. Console.WriteLine("=== OCR 识别测试 ===\n");
  55. // 测试图片路径(请修改为实际路径)
  56. string imagePath = "D:/work/WindowsFormsTest/TestImage/wechat_2025-10-16_143143_308.png";
  57. if (!File.Exists(imagePath))
  58. {
  59. Console.WriteLine($"错误:找不到图片文件 {imagePath}");
  60. return;
  61. }
  62. try
  63. {
  64. // 方式1:使用单例引擎(推荐,性能最优)
  65. Console.WriteLine("【方式1】使用单例引擎识别...");
  66. var ocrEngine = OCREngine.Instance;
  67. Stopwatch sw = Stopwatch.StartNew();
  68. string result1 = ocrEngine.RecognizeText(imagePath);
  69. sw.Stop();
  70. Console.WriteLine($"识别结果:{result1}");
  71. Console.WriteLine($"耗时:{sw.ElapsedMilliseconds} ms\n");
  72. // 方式2:指定语言识别(中文+英文)
  73. Console.WriteLine("【方式2】中英文混合识别...");
  74. var ocrEngineChi = OCREngine.GetInstance("chi_sim+eng");
  75. sw.Restart();
  76. string result2 = ocrEngineChi.RecognizeText(imagePath);
  77. sw.Stop();
  78. Console.WriteLine($"识别结果:{result2}");
  79. Console.WriteLine($"耗时:{sw.ElapsedMilliseconds} ms\n");
  80. // 方式3:使用自定义配置
  81. Console.WriteLine("【方式3】使用自定义配置识别...");
  82. var config = new OCRConfig
  83. {
  84. Language = "eng",
  85. EngineMode = EngineMode.LstmOnly, // 仅使用LSTM,速度更快
  86. Whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,!?-",
  87. EnablePreprocessing = true
  88. };
  89. var ocrEngineCustom = OCREngine.GetInstance(config);
  90. sw.Restart();
  91. string result3 = ocrEngineCustom.RecognizeText(imagePath);
  92. sw.Stop();
  93. Console.WriteLine($"识别结果:{result3}");
  94. Console.WriteLine($"耗时:{sw.ElapsedMilliseconds} ms\n");
  95. // 方式4:批量识别
  96. Console.WriteLine("【方式4】批量识别测试...");
  97. string[] imagePaths = new string[] { imagePath }; // 可以添加多个图片路径
  98. sw.Restart();
  99. var results = ocrEngine.RecognizeBatch(imagePaths);
  100. sw.Stop();
  101. for (int i = 0; i < results.Count; i++)
  102. {
  103. Console.WriteLine($"图片{i + 1}:{results[i]}");
  104. }
  105. Console.WriteLine($"批量识别总耗时:{sw.ElapsedMilliseconds} ms\n");
  106. // 方式5:从Bitmap识别
  107. Console.WriteLine("【方式5】从Bitmap识别...");
  108. using (var bitmap = new Bitmap(imagePath))
  109. {
  110. sw.Restart();
  111. string result5 = ocrEngine.RecognizeFromBitmap(bitmap);
  112. sw.Stop();
  113. Console.WriteLine($"识别结果:{result5}");
  114. Console.WriteLine($"耗时:{sw.ElapsedMilliseconds} ms\n");
  115. }
  116. Console.WriteLine("测试完成!按任意键退出...");
  117. Console.ReadKey();
  118. }
  119. catch (Exception ex)
  120. {
  121. Console.WriteLine($"发生错误:{ex.Message}");
  122. Console.WriteLine($"堆栈跟踪:{ex.StackTrace}");
  123. }
  124. }
  125. /// <summary>
  126. /// 创建训练项目示例
  127. /// </summary>
  128. static void CreateTrainingProjectExample()
  129. {
  130. Console.WriteLine("\n=== 创建训练项目示例 ===\n");
  131. string projectFolder = @"D:\work\WindowsFormsTest\OCRTest\TrainingProject";
  132. try
  133. {
  134. OCRTrainingHelper.CreateSampleProject(projectFolder);
  135. Console.WriteLine("\n项目创建成功!");
  136. Console.WriteLine($"项目路径:{projectFolder}");
  137. Console.WriteLine("\n下一步:");
  138. Console.WriteLine("1. 将训练图片放入 raw_images 文件夹");
  139. Console.WriteLine("2. 按照 README.md 的说明进行训练");
  140. }
  141. catch (Exception ex)
  142. {
  143. Console.WriteLine($"创建失败:{ex.Message}");
  144. }
  145. Console.WriteLine("\n按任意键继续...");
  146. Console.ReadKey();
  147. }
  148. /// <summary>
  149. /// 预处理训练图片示例
  150. /// </summary>
  151. static void PreprocessTrainingImagesExample()
  152. {
  153. Console.WriteLine("\n=== 预处理训练图片 ===\n");
  154. string inputFolder = @"D:\work\WindowsFormsTest\OCRTest\TrainingProject\raw_images";
  155. string outputFolder = @"D:\work\WindowsFormsTest\OCRTest\TrainingProject\processed_images";
  156. if (!Directory.Exists(inputFolder))
  157. {
  158. Console.WriteLine($"输入文件夹不存在:{inputFolder}");
  159. Console.WriteLine("请先创建训练项目并放入原始图片");
  160. return;
  161. }
  162. try
  163. {
  164. OCRTrainingHelper.PreprocessTrainingImages(
  165. inputFolder,
  166. outputFolder,
  167. targetWidth: 800,
  168. targetHeight: 0 // 自动计算高度
  169. );
  170. }
  171. catch (Exception ex)
  172. {
  173. Console.WriteLine($"处理失败:{ex.Message}");
  174. }
  175. Console.WriteLine("\n按任意键继续...");
  176. Console.ReadKey();
  177. }
  178. /// <summary>
  179. /// 验证数据集示例
  180. /// </summary>
  181. static void ValidateDatasetExample()
  182. {
  183. Console.WriteLine("\n=== 验证训练数据集 ===\n");
  184. string datasetFolder = @"D:\work\WindowsFormsTest\OCRTest\TrainingProject\processed_images";
  185. if (!Directory.Exists(datasetFolder))
  186. {
  187. Console.WriteLine($"数据集文件夹不存在:{datasetFolder}");
  188. return;
  189. }
  190. try
  191. {
  192. var missingFiles = OCRTrainingHelper.ValidateDataset(datasetFolder);
  193. if (missingFiles.Count == 0)
  194. {
  195. Console.WriteLine("\n✓ 数据集完整,可以开始训练");
  196. }
  197. else
  198. {
  199. Console.WriteLine($"\n✗ 发现 {missingFiles.Count} 个缺少标注文件的图片");
  200. Console.WriteLine("请为这些图片创建对应的 .txt 标注文件");
  201. }
  202. }
  203. catch (Exception ex)
  204. {
  205. Console.WriteLine($"验证失败:{ex.Message}");
  206. }
  207. Console.WriteLine("\n按任意键继续...");
  208. Console.ReadKey();
  209. }
  210. /// <summary>
  211. /// 分析字符频率示例
  212. /// </summary>
  213. static void AnalyzeCharactersExample()
  214. {
  215. Console.WriteLine("\n=== 分析字符频率 ===\n");
  216. string labelFolder = @"D:\work\WindowsFormsTest\OCRTest\TrainingProject\labels";
  217. if (!Directory.Exists(labelFolder))
  218. {
  219. Console.WriteLine($"标注文件夹不存在:{labelFolder}");
  220. return;
  221. }
  222. try
  223. {
  224. var frequency = OCRTrainingHelper.AnalyzeCharacterFrequency(labelFolder);
  225. Console.WriteLine("\n提示:根据字符频率可以优化白名单配置");
  226. Console.WriteLine("高频字符应该优先保证识别准确率");
  227. }
  228. catch (Exception ex)
  229. {
  230. Console.WriteLine($"分析失败:{ex.Message}");
  231. }
  232. Console.WriteLine("\n按任意键继续...");
  233. Console.ReadKey();
  234. }
  235. public static void OCRTest1()
  236. {
  237. OCRModelConfig config = null;
  238. PaddleOCREngine engine = new PaddleOCREngine(config, "");
  239. bool Image1Finsh = false;
  240. bool Image2Finsh = false;
  241. bool Image3Finsh = false;
  242. Mat image1 = Cv2.ImRead("D:/work/WindowsFormsTest/TestImage/Date1_20260411170215701.jpg");
  243. OCRResult ocrResult1 = engine.DetectText(image1.ToBytes());
  244. Stopwatch sw = Stopwatch.StartNew();
  245. Task.Run(() =>
  246. {
  247. Mat image = Cv2.ImRead("D:/work/WindowsFormsTest/TestImage/Date1_20260411170215701.jpg");
  248. OCRResult ocrResult = engine.DetectText(image.ToBytes());
  249. foreach (var item in ocrResult.TextBlocks)
  250. {
  251. Console.WriteLine("图像1结果:{0}", item.Text);
  252. }
  253. Image1Finsh = true;
  254. //if (Image1Finsh && Image2Finsh && Image3Finsh)
  255. //{
  256. sw.Stop();
  257. Console.WriteLine("耗时:" + sw.ElapsedMilliseconds);
  258. //}
  259. });
  260. //Task.Run(() =>
  261. //{
  262. // Mat image = Cv2.ImRead("D:/work/WindowsFormsTest/TestImage/3_20250908104000075.jpg", ImreadModes.Color);
  263. // OCRResult ocrResult = engine.DetectText(image.ToBytes());
  264. // foreach (var item in ocrResult.TextBlocks)
  265. // {
  266. // Console.WriteLine("图像2结果:{0}", item.Text);
  267. // }
  268. // Image2Finsh = true;
  269. // if (Image1Finsh && Image2Finsh && Image3Finsh)
  270. // {
  271. // sw.Stop();
  272. // Console.WriteLine("耗时:" + sw.ElapsedMilliseconds);
  273. // }
  274. //});
  275. //Task.Run(() =>
  276. //{
  277. // Mat image = Cv2.ImRead("D:/work/WindowsFormsTest/TestImage/3_20250908104000075.jpg", ImreadModes.Color);
  278. // OCRResult ocrResult = engine.DetectText(image.ToBytes());
  279. // foreach (var item in ocrResult.TextBlocks)
  280. // {
  281. // Console.WriteLine("图像3结果:{0}", item.Text);
  282. // }
  283. // Image3Finsh = true;
  284. // if (Image1Finsh && Image2Finsh && Image3Finsh)
  285. // {
  286. // sw.Stop();
  287. // Console.WriteLine("耗时:" + sw.ElapsedMilliseconds);
  288. // }
  289. //});
  290. Console.ReadKey();
  291. }
  292. public static string OCRTest2()
  293. {
  294. using (var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default))
  295. {
  296. // 只允许识别英文字母、数字和常见符号
  297. engine.SetVariable("tessedit_char_whitelist", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,!?-@#$%");
  298. using (var img = Pix.LoadFromFile("D:/work/WindowsFormsTest/TestImage/wechat_2025-10-16_143143_308.png"))
  299. {
  300. using (var page = engine.Process(img))
  301. {
  302. var text = page.GetText();
  303. Console.WriteLine(text);
  304. return text;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }