Model: Tesseract OCR Integration
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt
- app/src/main/assets/tessdata/README.md
- README.md
- app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt
- app/src/main/java/com/musagenius/ocrapp/domain/model/OCRResult.kt
- ROADMAP.md
- TODO.md
The Tesseract OCR integration is a core feature of the application, providing offline text recognition from images. It is built using the tess-two library, a Java wrapper for the Tesseract 3.05 and Leptonica 1.74.1 native libraries. This system is designed to be robust, thread-safe, and decoupled from the UI, following Clean Architecture principles.
The integration is encapsulated within the data layer and exposed to the rest of the app through a service and use cases. It handles everything from engine initialization and language data management to image preprocessing and text extraction. The entire process runs on-device, ensuring user privacy and functionality without an internet connection.
Sources: README.md, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt
Architecture Overview
The Tesseract OCR functionality is integrated into the app's MVVM and Clean Architecture structure. The flow begins at the OCRViewModel in the presentation layer, which invokes a use case from the domain layer. This use case, in turn, utilizes the OCRService implemented in the data layer, which directly interacts with the Tesseract TessBaseAPI.
This diagram illustrates the architectural layering and dependency flow for an OCR request.
Core Component: OCRServiceImpl
OCRServiceImpl is a singleton class that acts as the primary wrapper for the Tesseract engine. It manages the lifecycle of the TessBaseAPI, ensures thread-safe operations, and orchestrates the entire OCR process.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:28-32
Key Responsibilities
- Tesseract API Management: It initializes, configures, and cleans up the
TessBaseAPIinstance. - Thread Safety: All access to the
TessBaseAPIis serialized using aMutexto prevent race conditions and ensure that only one OCR operation occurs at a time. - Language Data Management: It handles the on-demand copying of
.traineddatafiles from the app's assets to the device storage where Tesseract can access them. - Image Preprocessing: It coordinates with an
ImagePreprocessorto prepare bitmaps for optimal recognition. - Text Recognition: It provides methods to perform OCR, returning the results in a structured
OCRResultobject.
Thread Safety
To prevent concurrent access to the native Tesseract library, which is not inherently thread-safe, OCRServiceImpl uses a kotlinx.coroutines.sync.Mutex. Every public method that interacts with TessBaseAPI, such as initialize and recognizeText, must acquire a lock on this mutex before proceeding.
// app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:34-35
// Mutex to serialize all access to tessBaseAPI, preventing race conditions
private val tessMutex = Mutex()
// app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:111-114
suspend fun recognizeText(
bitmap: Bitmap,
config: OCRConfig = OCRConfig()
): Result<OCRResult> = tessMutex.withLock {
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:35, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:111-114
Configuration (OCRConfig)
The OCR process is highly configurable via the OCRConfig data class. This allows the calling code (e.g., a use case or ViewModel) to specify parameters for each recognition task.
The following table details the available configuration options:
| Parameter | Type | Default Value | Description |
|---|---|---|---|
language | String | "eng" | The three-letter language code for OCR (e.g., "eng", "fra"). |
pageSegmentationMode | PageSegMode | PageSegMode.AUTO | Defines how Tesseract segments the image into lines and words. |
engineMode | EngineMode | EngineMode.DEFAULT | Specifies which Tesseract engine to use (Legacy, LSTM, or both). |
preprocessImage | Boolean | true | If true, the image will be preprocessed (e.g., grayscale, scaling) before recognition. |
maxImageDimension | Int | 2000 | The maximum width or height in pixels for the image after scaling. This prevents memory issues with large images. |
enableAutoRotation | Boolean | false | If true, enables Tesseract's automatic page rotation detection. (Note: This is a planned feature, currently defaulted to false). |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:6-12, app/src/test/java/com/musagenius/ocrapp/domain/model/OCRConfigTest.kt:20-27
Page Segmentation Modes (PageSegMode)
This enum corresponds to Tesseract's Page Segmentation Modes, which instruct the engine on how to interpret the page layout.
| Mode | Value | Description |
|---|---|---|
OSD_ONLY | 0 | Orientation and script detection only. |
AUTO | 3 | Fully automatic page segmentation (default). |
SINGLE_LINE | 7 | Treat the image as a single text line. |
SPARSE_TEXT | 11 | Find as much text as possible in no particular order. |
| (...and others) | ... | Other modes for specific layouts. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:21-34
Engine Modes (EngineMode)
This enum controls which OCR engine version is used.
| Mode | Value | Description |
|---|---|---|
TESSERACT_ONLY | 0 | Legacy engine only. |
LSTM_ONLY | 1 | Neural nets (LSTM) engine only. |
TESSERACT_LSTM | 2 | Both legacy and LSTM engines. |
DEFAULT | 3 | Default, based on what is available. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRConfig.kt:40-45
Data Flow and Usage
Initialization Flow
Before OCR can be performed, the Tesseract engine must be initialized. This process is handled internally by OCRServiceImpl and is triggered by the first call to recognizeText or recognizeTextWithProgress.
The initialization sequence is as follows:
- The
tessdatadirectory is created in the app's external storage if it doesn't exist. - The required language file (e.g.,
eng.traineddata) is checked. - If the language file is missing, it's copied from the app's bundled assets (
/assets/tessdata/). - The
TessBaseAPIis initialized with the path to thetessdatadirectory and the specified language.
This diagram shows the initialization sequence.
Text Recognition Flow
The main text recognition process is initiated from the OCRViewModel and flows through the layers to the Tesseract engine.
This sequence diagram details the steps involved in recognizing text from a Bitmap.
Progress Tracking
OCRServiceImpl also provides a recognizeTextWithProgress method that returns a Flow of OCRProgress updates. This is used to provide feedback to the user during long operations. The progress is divided into stages: INITIALIZING, PREPROCESSING, RECOGNIZING, and COMPLETED.
It is important to note that Tesseract does not provide a native real-time progress callback for the recognition step. Therefore, the progress during the RECOGNIZING stage is simulated by emitting incremental progress values with small delays.
Sources: app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:153-238
Trained Data Management
The accuracy of Tesseract depends on language-specific trained data files (.traineddata).
- Storage: These files must be placed in the
app/src/main/assets/tessdata/directory during development. - Distribution: On the app's first run for a specific language,
OCRServiceImplcopies the corresponding.traineddatafile from the assets to the device's external storage path (<external_storage>/tessdata/). - Source: The recommended source for these files is the official
tessdata_bestrepository, which offers high accuracy. - Exclusion: Due to their large size,
.traineddatafiles are ignored by Git to keep the repository lightweight. Developers must add them manually.
Sources: app/src/main/assets/tessdata/README.md, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt:243-268
Data Models
OCRResult
This data class represents the direct output of an OCR operation.
| Field | Type | Description |
|---|---|---|
text | String | The extracted text. |
confidence | Float | The average confidence score from 0.0 to 1.0. |
processingTimeMs | Long | The total time taken for the OCR process in ms. |
language | String | The language used for recognition. |
wordCount | Int | The number of words in the extracted text. |
characterCount | Int | The number of characters in the extracted text. |
Sources: app/src/main/java/com/musagenius/ocrapp/domain/model/OCRResult.kt:6-12
ScanResult
After a successful OCR operation, the OCRViewModel uses the OCRResult to create a ScanResult object, which is the domain model used for persisting the scan in the local Room database.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/viewmodel/OCRViewModel.kt:205-219
Conclusion
The Tesseract OCR integration is a well-architected, self-contained module that provides the app's core text recognition capabilities. By using OCRServiceImpl as a thread-safe singleton, the system ensures stable and predictable access to the native Tesseract engine. The use of OCRConfig provides flexibility, while the clear separation of concerns within the app's architecture makes the feature maintainable and testable. This on-device processing model is fundamental to the app's promise of offline functionality and user privacy.
Sources: README.md, ROADMAP.md, app/src/main/java/com/musagenius/ocrapp/data/ocr/OCRServiceImpl.kt