You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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();
    }
}

关键修改说明

  1. 目标区域传递:给DoOCR方法新增Rectangle targetArea参数,直接传入你需要识别的矩形区域。
  2. 文字块筛选逻辑:MODI识别后会将内容拆分为独立的Word对象,每个对象包含自身的位置矩形。我们将其转换为.NET标准Rectangle,通过IntersectsWith判断是否落在目标区域内,只保留符合条件的文字。
  3. 资源优化:
    • 用foreach替代原始的IEnumerator遍历文件,代码更简洁。
    • 使用using语句自动管理文件流,避免手动关闭时的资源泄漏。
    • 手动释放MODI的COM对象(Marshal.ReleaseComObject),因为MODI是COM组件,GC无法及时回收,容易导致内存占用过高。
  4. 坐标兼容:MODI的坐标系统和GDI+完全一致,你给出的X=1367,Y=420等参数可以直接使用,若识别区域偏差,检查图片分辨率是否和你获取坐标时的一致即可。

可选调整

  • 如果需要完全包含在目标区域内的文字块,将IntersectsWith替换为targetArea.Contains(wordRect)。
  • 根据图片实际语言修改OCR语言参数,比如中文场景改为MODI.MiLANGUAGES.miLANG_CHINESE_SIMPLIFIED。

内容的提问来源于stack exchange,提问作者fasih ullah khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:16:17