如何通过MODI对指定矩形区域执行批量图片OCR?
解决MODI批量OCR指定矩形区域的问题
我明白你必须使用MODI的限制,虽然它没有直接提供区域截取OCR的API,但我们可以通过识别整张图片后筛选目标区域内的文字块来实现需求。下面是修改后的完整代码,核心是在DoOCR方法中遍历图片识别出的文字块,只保留落在指定矩形内的内容。
修改后的完整代码
// 定义你需要识别的目标区域(可根据需求调整参数) private readonly Rectangle _targetArea = new Rectangle { X = 1367, Y = 420, Height = 57, Width = 411 }; private void button1_Click(object sender, EventArgs e) { CommonOpenFileDialog dialog = new CommonOpenFileDialog { InitialDirectory = "C:\\Users", IsFolderPicker = true }; if (dialog.ShowDialog() == CommonFileDialogResult.Ok) { invoicePath = dialog.FileName; CheckFileAndDoOCR(invoicePath); } } public string CheckFileAndDoOCR(string directoryPath) { string TheTxt = ""; // 用foreach替代IEnumerator,代码更简洁易读 foreach (string filePath in Directory.GetFiles(directoryPath)) { FileInfo foo = new FileInfo(filePath); // 忽略大小写判断图片格式 if (foo.Extension.Equals(".jpg", StringComparison.OrdinalIgnoreCase)) { // 调用修改后的DoOCR,传入目标区域参数 TheTxt = DoOCR(foo.FullName, _targetArea); string txtFileName = Path.Combine(foo.DirectoryName, foo.Name.Replace(foo.Extension, "") + ".txt"); // 使用using语句自动释放文件资源,避免手动Close遗漏 using (FileStream createFile = new FileStream(txtFileName, FileMode.OpenOrCreate)) using (StreamWriter writeFile = new StreamWriter(createFile)) { writeFile.Write(TheTxt); } } try { foo.Delete(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } return TheTxt; } public string DoOCR(string fullPath, Rectangle targetArea) { MODI.Document md = null; try { md = new MODI.Document(); md.Create(fullPath); // 根据图片实际语言调整,中文简体可改为miLANG_CHINESE_SIMPLIFIED md.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false); MODI.Image image = (MODI.Image)md.Images[0]; MODI.Layout layout = image.Layout; StringBuilder sb = new StringBuilder(); // 遍历所有识别出的文字块(Word对象) foreach (MODI.Word word in layout.Words) { // 将MODI的IMiRect转换为.NET标准Rectangle Rectangle wordRect = new Rectangle( word.Rect.Left, word.Rect.Top, word.Rect.Right - word.Rect.Left, word.Rect.Bottom - word.Rect.Top ); // 判断文字块是否与目标区域有交集(若需要完全包含,可改为targetArea.Contains(wordRect)) if (targetArea.IntersectsWith(wordRect)) { sb.Append(word.Text).Append(" "); } } return sb.ToString().Trim(); } finally { // 手动释放MODI COM对象,避免内存泄漏 if (md != null) { md.Close(false); System.Runtime.InteropServices.Marshal.ReleaseComObject(md); } GC.Collect(); GC.WaitForPendingFinalizers(); } }
关键修改说明
- 目标区域传递:给
DoOCR方法新增Rectangle targetArea参数,直接传入你需要识别的矩形区域。 - 文字块筛选逻辑:MODI识别后会将内容拆分为独立的
Word对象,每个对象包含自身的位置矩形。我们将其转换为.NET标准Rectangle,通过IntersectsWith判断是否落在目标区域内,只保留符合条件的文字。 - 资源优化:
- 用
foreach替代原始的IEnumerator遍历文件,代码更简洁。 - 使用
using语句自动管理文件流,避免手动关闭时的资源泄漏。 - 手动释放MODI的COM对象(
Marshal.ReleaseComObject),因为MODI是COM组件,GC无法及时回收,容易导致内存占用过高。
- 用
- 坐标兼容:MODI的坐标系统和GDI+完全一致,你给出的
X=1367,Y=420等参数可以直接使用,若识别区域偏差,检查图片分辨率是否和你获取坐标时的一致即可。
可选调整
- 如果需要完全包含在目标区域内的文字块,将
IntersectsWith替换为targetArea.Contains(wordRect)。 - 根据图片实际语言修改OCR语言参数,比如中文场景改为
MODI.MiLANGUAGES.miLANG_CHINESE_SIMPLIFIED。
内容的提问来源于stack exchange,提问作者fasih ullah khan
相关产品推荐
相关产品推荐

