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
相关产品推荐
相关产品推荐

