The Hebrew OCR Engine provides a complete solution for optical character recognition of Hebrew text, including both regular Hebrew and Rashi script. The engine is designed with a modular architecture that allows for easy customization and extension.
- Installation
- Quick Start
- Core Components
- Configuration
- OCR Operations
- Training
- Interactive Correction
- Error Handling
- Examples
go get github.com/hebrew-ocr/enginepackage main
import (
"fmt"
"log"
"github.com/hebrew-ocr/engine/pkg/ocr"
"github.com/hebrew-ocr/engine/pkg/classification"
)
func main() {
// Create OCR engine configuration
config := &ocr.Config{
FontType: ocr.RegularHebrew,
MinConfidence: 0.5,
OutputFormat: ocr.PlainText,
MaxConcurrency: 4,
}
// Initialize engine
engine := ocr.NewOCREngine(config)
// Load trained model
classifier := classification.NewCharacterClassifier(ocr.RegularHebrew)
model := classifier.GetModel()
if err := model.Load("models/hebrew_regular.model"); err != nil {
log.Fatal(err)
}
engine.SetClassifier(model)
// Perform OCR
result, err := engine.RecognizeFile("image.png")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Text: %s\n", result.Text)
fmt.Printf("Confidence: %.2f%%\n", result.Confidence*100)
}The main engine that orchestrates the OCR pipeline.
type OCREngine struct {
// Internal fields
}
// Create a new OCR engine
func NewOCREngine(config *Config) *OCREngine
// Recognize text from an image
func (e *OCREngine) RecognizeImage(img image.Image) (*OCRResult, error)
// Recognize text from a file
func (e *OCREngine) RecognizeFile(path string) (*OCRResult, error)
// Process multiple images in batch
func (e *OCREngine) RecognizeBatch(images []image.Image) []BatchResult
// Interactive recognition with detailed character information
func (e *OCREngine) RecognizeInteractive(img image.Image) (*InteractiveResult, error)Configuration options for the OCR engine.
type Config struct {
// Font type: RegularHebrew, RashiScript, or AutoDetect
FontType FontType
// Minimum confidence threshold (0.0 to 1.0)
MinConfidence float64
// Enable debug mode with verbose logging
EnableDebug bool
// Output format: PlainText, JSON, or HOCR
OutputFormat OutputFormat
// Maximum number of concurrent image processing operations
MaxConcurrency int
}The result of OCR processing.
type OCRResult struct {
// Recognized text as UTF-8 string
Text string
// Average confidence score (0.0 to 1.0)
Confidence float64
// Detailed information for each recognized character
Characters []RecognizedChar
// Total processing time
ProcessingTime time.Duration
// Additional metadata
Metadata map[string]interface{}
}Information about a single recognized character.
type RecognizedChar struct {
// The recognized Unicode character
Char rune
// Recognition confidence score (0.0 to 1.0)
Confidence float64
// Center point of the character
Position image.Point
// Rectangular region containing the character
BoundingBox image.Rectangle
// Whether this character has low confidence (< 0.5)
Uncertain bool
}const (
RegularHebrew FontType = iota // Standard Hebrew print font
RashiScript // Rashi script for Talmudic commentary
AutoDetect // Automatically detect font type
)const (
PlainText OutputFormat = iota // Plain text output
JSON // Structured JSON with metadata
HOCR // hOCR format (HTML-based)
)// Recognize from image
result, err := engine.RecognizeImage(img)
if err != nil {
log.Fatal(err)
}
// Recognize from file
result, err := engine.RecognizeFile("document.png")
if err != nil {
log.Fatal(err)
}images := []image.Image{img1, img2, img3}
results := engine.RecognizeBatch(images)
for i, result := range results {
if result.Error != nil {
log.Printf("Image %d failed: %v", i, result.Error)
continue
}
fmt.Printf("Image %d: %s\n", i, result.Result.Text)
}// Get detailed character information
result, err := engine.RecognizeInteractive(img)
if err != nil {
log.Fatal(err)
}
// Access character details
for i, charDetail := range result.CharacterDetails {
fmt.Printf("Char %d: %c (confidence: %.2f)\n",
i, charDetail.Char, charDetail.Confidence)
}// Create training samples
samples := []ocr.TrainingSample{
{
Features: featureVector1,
Label: 'א',
},
{
Features: featureVector2,
Label: 'ב',
},
}
// Train model
classifier := classification.NewCharacterClassifier(ocr.RegularHebrew)
model := classifier.GetModel()
if err := model.Train(samples); err != nil {
log.Fatal(err)
}
// Save trained model
if err := model.Save("my_model.model"); err != nil {
log.Fatal(err)
}classifier := classification.NewCharacterClassifier(ocr.RegularHebrew)
model := classifier.GetModel()
if err := model.Load("models/hebrew_regular.model"); err != nil {
log.Fatal(err)
}
engine.SetClassifier(model)import "github.com/hebrew-ocr/engine/pkg/correction"
// Create correction manager
correctionManager := correction.NewCorrectionManager(
"corrections.json",
classifier,
)
engine.SetCorrectionManager(correctionManager)// Perform interactive recognition
result, err := engine.RecognizeInteractive(img)
if err != nil {
log.Fatal(err)
}
// Correct a character
charDetail := &result.CharacterDetails[0]
if err := engine.CorrectCharacter(charDetail, 'ב'); err != nil {
log.Fatal(err)
}// Apply corrections to model (incremental training)
if err := engine.ApplyCorrections(); err != nil {
log.Fatal(err)
}
// Save corrections to disk
cm := engine.GetCorrectionManager()
if err := cm.SaveCorrections(); err != nil {
log.Fatal(err)
}The engine uses typed errors for better error handling:
result, err := engine.RecognizeFile("image.png")
if err != nil {
if ocrErr, ok := err.(*ocr.OCRError); ok {
switch ocrErr.Code {
case ocr.ErrInvalidImage:
log.Println("Invalid image format")
case ocr.ErrModelNotLoaded:
log.Println("Model not loaded")
case ocr.ErrClassificationFailed:
log.Println("Classification failed")
default:
log.Printf("OCR error: %v", ocrErr)
}
}
return
}ErrInvalidImage- The image is invalid or corruptedErrUnsupportedFormat- Image format not supportedErrCorruptedFile- File is corrupted or unreadableErrLowResolution- Image resolution too lowErrSegmentationFailed- Character segmentation failedErrClassificationFailed- Character classification failedErrModelNotLoaded- Classification model not loadedErrInvalidTrainingData- Training data is invalidErrModelSaveFailed- Model serialization failedErrModelLoadFailed- Model deserialization failed
package main
import (
"fmt"
"log"
"github.com/hebrew-ocr/engine/pkg/ocr"
"github.com/hebrew-ocr/engine/pkg/classification"
)
func main() {
config := &ocr.Config{
FontType: ocr.RegularHebrew,
MinConfidence: 0.5,
OutputFormat: ocr.PlainText,
}
engine := ocr.NewOCREngine(config)
classifier := classification.NewCharacterClassifier(ocr.RegularHebrew)
model := classifier.GetModel()
model.Load("models/hebrew_regular.model")
engine.SetClassifier(model)
result, err := engine.RecognizeFile("document.png")
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Text)
}config := &ocr.Config{
FontType: ocr.RegularHebrew,
OutputFormat: ocr.JSON,
}
engine := ocr.NewOCREngine(config)
// ... setup classifier ...
result, err := engine.RecognizeFile("document.png")
if err != nil {
log.Fatal(err)
}
// Result.Text contains JSON string
fmt.Println(result.Text)files := []string{"page1.png", "page2.png", "page3.png"}
images := make([]image.Image, len(files))
for i, file := range files {
img, err := loadImage(file)
if err != nil {
log.Fatal(err)
}
images[i] = img
}
results := engine.RecognizeBatch(images)
for i, result := range results {
if result.Error != nil {
log.Printf("Page %d failed: %v", i+1, result.Error)
continue
}
fmt.Printf("Page %d: %s\n", i+1, result.Result.Text)
}// Perform OCR with detailed character info
result, err := engine.RecognizeInteractive(img)
if err != nil {
log.Fatal(err)
}
// Display results
for i, char := range result.CharacterDetails {
fmt.Printf("%d: %c (%.2f%%)\n", i, char.Char, char.Confidence*100)
}
// Correct a character
if result.CharacterDetails[0].Confidence < 0.5 {
err := engine.CorrectCharacter(&result.CharacterDetails[0], 'א')
if err != nil {
log.Fatal(err)
}
}
// Apply corrections
if err := engine.ApplyCorrections(); err != nil {
log.Fatal(err)
}For large images, the engine automatically uses tiling:
config := &ocr.Config{
// ... other settings ...
MaxConcurrency: 4, // Limit concurrent processing
}Process multiple images efficiently:
// Set appropriate concurrency
config.MaxConcurrency = 4
// Process in batches
results := engine.RecognizeBatch(images)Enable profiling to measure performance:
config := &ocr.Config{
EnableDebug: true, // Enables profiling
}
result, _ := engine.RecognizeFile("image.png")
// Check processing time
fmt.Printf("Processing time: %v\n", result.ProcessingTime)
// Check metadata for detailed timing
if profiling, ok := result.Metadata["profiling"]; ok {
fmt.Printf("Profiling data: %v\n", profiling)
}- Always load a trained model before performing OCR
- Use appropriate font type for your documents
- Set reasonable confidence thresholds (0.5 is a good default)
- Handle errors properly using typed error checking
- Use batch processing for multiple images
- Enable debug mode during development
- Save corrections for incremental training
- Monitor memory usage for large images
For issues, questions, or contributions, please visit:
- GitHub: https://github.com/hebrew-ocr/engine
- Documentation: https://hebrew-ocr.github.io/engine
MIT License - see LICENSE file for details