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

Android Studio中Tesseract OCR提取印度语言PDF文本崩溃排查

印度语言PDF文本提取问题排查

问题情况

  • 已完成代码开发,将Tesseract训练数据文件放在assets目录,实现PDF转图片步骤,但Android Studio中用Java调用Tesseract OCR提取马拉地语、印地语等印度语言PDF时应用崩溃
  • 尝试用iText7库仅能提取PDF中的英文文本,无法提取印度语言

相关代码

PDFUtils类

public class PDFUtils {

    private static final String TAG = "pdf ocr";
    private static final String TESS_DATA = "/tessdata";
    private static final String LANG = "mar+hin";

    public static String extractText(Context context, Uri pdfUri) {
        // Initialize Tesseract OCR
        String dataPath = context.getFilesDir() + TESS_DATA;
        prepareTesseract(context, dataPath);
        TessBaseAPI tessBaseAPI = new TessBaseAPI();
        tessBaseAPI.init(dataPath, LANG);

        // Load and process PDF pages
        String extractedText = "";
        try {
            ParcelFileDescriptor fileDescriptor = context.getContentResolver().openFileDescriptor(pdfUri, "r");
            if (fileDescriptor != null) {
                PdfRenderer pdfRenderer = new PdfRenderer(fileDescriptor);
                int pageCount = pdfRenderer.getPageCount();

                for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
                    PdfRenderer.Page page = pdfRenderer.openPage(pageIndex);

                    // Render the PDF page as a bitmap image
                    Bitmap pageBitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(), Bitmap.Config.ARGB_8888);
                    page.render(pageBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

                    // Process the bitmap image using Tesseract
                    tessBaseAPI.setImage(pageBitmap);
                    extractedText += tessBaseAPI.getUTF8Text();

                    // Close the current page
                    page.close();
                }

                // Close the PDF renderer
                pdfRenderer.close();
                fileDescriptor.close();
            }
        } catch (IOException e) {
            Log.e(TAG, "Error loading PDF and extracting text: " + e.getMessage());
        }

        // Clean up
        tessBaseAPI.end();

        return extractedText;
    }

    private static void prepareTesseract(Context context, String dataPath) {
        try {
            String fileList[] = context.getAssets().list("");
            for (String fileName : fileList) {
                String pathToDataFile = dataPath + TESS_DATA + "/" + fileName;
                if (!(new File(pathToDataFile)).exists()) {
                    InputStream in = context.getAssets().open(fileName);
                    OutputStream out = new FileOutputStream(pathToDataFile);

                    byte[] buffer = new byte[1024];
                    int read;
                    while ((read = in.read(buffer)) != -1) {
                        out.write(buffer, 0, read);
                    }

                    out.flush();
                    out.close();
                    in.close();
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Error preparing Tesseract OCR data: " + e.getMessage());
        }
    }
}

调用代码

public class MyActivity extends AppCompatActivity {

    // ...

    public void yourPublicFunction() {
        Uri pdfUri = ...; // 设置PDF文件URI
        String extractedText = PDFUtils.extractText(this, pdfUri);
        Log.d(TAG, "Extracted Text: " + extractedText);
    }
}

问题排查与修复方案

1. Tesseract训练数据路径错误(崩溃核心原因)

prepareTesseract方法中路径拼接重复:

  • dataPath已经是context.getFilesDir() + "/tessdata",但后续拼接成dataPath + "/tessdata/" + fileName,最终路径变成/data/data/xxx/files/tessdata/tessdata/xxx.traineddata,Tesseract找不到训练数据,初始化失败导致崩溃。

修复代码:
修改prepareTesseract中的路径拼接:

private static void prepareTesseract(Context context, String dataPath) {
    try {
        // 创建tessdata目录(如果不存在)
        File tessDir = new File(dataPath);
        if (!tessDir.exists()) {
            tessDir.mkdirs();
        }

        String fileList[] = context.getAssets().list("");
        for (String fileName : fileList) {
            // 去掉重复的/tessdata
            String pathToDataFile = dataPath + "/" + fileName;
            File dataFile = new File(pathToDataFile);
            if (!dataFile.exists()) {
                InputStream in = context.getAssets().open(fileName);
                OutputStream out = new FileOutputStream(dataFile);

                byte[] buffer = new byte[1024];
                int read;
                while ((read = in.read(buffer)) != -1) {
                    out.write(buffer, 0, read);
                }

                out.flush();
                out.close();
                in.close();
            }
        }
    } catch (IOException e) {
        Log.e(TAG, "Error preparing Tesseract OCR data: " + e.getMessage());
    }
}

2. 增加Tesseract初始化异常捕获

当前代码未捕获TessBaseAPI.init()可能抛出的RuntimeException,导致直接崩溃,需要添加异常处理:

public static String extractText(Context context, Uri pdfUri) {
    String extractedText = "";
    TessBaseAPI tessBaseAPI = null;
    try {
        String dataPath = context.getFilesDir() + TESS_DATA;
        prepareTesseract(context, dataPath);
        tessBaseAPI = new TessBaseAPI();
        // 捕获初始化异常
        if (!tessBaseAPI.init(dataPath, LANG)) {
            Log.e(TAG, "Tesseract初始化失败,检查训练数据是否正确");
            return extractedText;
        }

        // 后续PDF处理逻辑...

    } catch (IOException e) {
        Log.e(TAG, "Error loading PDF and extracting text: " + e.getMessage());
    } catch (RuntimeException e) {
        Log.e(TAG, "Tesseract运行异常: " + e.getMessage());
    } finally {
        // 确保资源关闭
        if (tessBaseAPI != null) {
            tessBaseAPI.end();
        }
    }
    return extractedText;
}

3. 优化PDF渲染质量(提升OCR准确率)

当前渲染模式和分辨率可能导致印度语言字符识别不清,调整渲染参数:

// 获取设备密度,放大Bitmap提升清晰度
float scale = context.getResources().getDisplayMetrics().density;
int bitmapWidth = (int) (page.getWidth() * scale);
int bitmapHeight = (int) (page.getHeight() * scale);
Bitmap pageBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
// 使用打印模式渲染,清晰度更高
page.render(pageBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);

4. iText7无法提取印度语言的解决

iText7只能提取可编辑的文本型PDF,如果印度语言是图片格式(扫描件),iText7无法提取,必须用OCR。如果是文本型PDF仍无法提取:

  • 检查PDF是否嵌入了印度语言字体,若未嵌入,iText7无法正确解析字符
  • 确保使用最新版本的iText7,添加字体支持依赖,或手动加载对应印度语言字体

内容的提问来源于stack exchange,提问作者nikhil achalkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:35:38