## TL;DR
easyocr's CUDA out-of-memory on a batch of scanned exhibits is the GPU trying to hold too many high-resolution pages at once: easyocr batches input images on the device, and a batch of print-resolution exhibits overflows VRAM. Process pages one at a time (batch_size=1), clear the CUDA cache between pages, and keep the model on GPU - you lose batching throughput but the job completes. If single pages still OOM, downscale the input images or move the overflow pages to CPU.

## The query
```text
easyocr CUDA out of memory on a batch of scanned exhibits  -  how to fix
```

## Use this when
- easyocr raises CUDA out of memory on a batch of scanned exhibits
- The first pages process fine and later ones die
- Single pages work but the full batch does not

## Not for
- OOM on CPU-only runs - that is system RAM, a different resource with different fixes
- CUDA errors on the very first page - check the install and GPU visibility first
- Slow GPU OCR without OOM - a performance question, not a memory failure

## Steps
### 1. Drop to batch_size=1 and rerun
The immediate fix: feed easyocr one page per call instead of a list. Batching is a throughput optimization; correctness does not need it.
```python
import easyocr
reader = easyocr.Reader(["en"], gpu=True)
for img in page_images:
    result = reader.readtext(img, batch_size=1)
    save(result)
```
Expected output: pages process sequentially with no CUDA OOM.

### 2. Clear the CUDA cache between pages
PyTorch holds freed GPU memory in its cache, so peak usage creeps up across pages even at batch_size=1. Emptying the cache between pages keeps the high-water mark at one page's worth.
```python
import torch
for img in page_images:
    result = reader.readtext(img, batch_size=1)
    save(result)
    torch.cuda.empty_cache()
```
Expected output: stable GPU memory across hundreds of pages instead of a slow climb to OOM.

### 3. Downscale oversized exhibit images
Scanned exhibits at 600 DPI are far larger than the recognizer needs. Downscaling to 300 DPI (or capping the long edge) cuts VRAM per page dramatically with negligible accuracy loss on printed text.
```python
from PIL import Image
img = Image.open("exhibit.png")
img.thumbnail((2480, 3508))  # cap at ~300 DPI A4
```
Expected output: per-page VRAM drops several-fold; the whole batch fits the original loop.

### 4. Fall back to CPU for the overflow, not the whole job
If a few pages are enormous (foldouts, engineering drawings), process just those with gpu=False in a separate reader. The bulk of the exhibits keeps GPU speed.
```python
cpu_reader = easyocr.Reader(["en"], gpu=False)
result = cpu_reader.readtext(huge_img, batch_size=1)
```
Expected output: the oversized pages complete slowly on CPU while the rest stay fast on GPU.

## Tool compatibility
easyocr with PyTorch CUDA backend; Pillow for downscaling. The batching and cache behavior is PyTorch's, so the pattern applies to any GPU OCR pipeline.

## Variant phrasings
- easyocr CUDA out of memory batch scanned exhibits
- easyocr readtext CUDA OOM batch_size
- easyocr GPU memory leak pages torch.cuda.empty_cache
- easyocr gpu=False fallback large images

## Why it happens
easyocr stacks the input images into one GPU batch tensor, so VRAM scales with batch size times image resolution. Print-resolution scans are huge tensors, and PyTorch's caching allocator additionally retains freed blocks, so memory grows across batches even when each batch is freed. The OOM is therefore a function of batching policy and image size - both fully in your control - not of the model itself.

## Edge cases / pitfalls
- empty_cache() has a small synchronization cost; call it between pages, not between batches of a healthy run.
- Multi-GPU machines can shard pages across devices, but fix the per-page memory first - sharding a leak just leaks in parallel.
- Half-precision inference cuts VRAM further if your easyocr/PyTorch build supports it; verify accuracy on a sample first.
- Monitor nvidia-smi during a run once; the steady-state number tells you the real per-page cost for capacity planning.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_eaoIlskHhBRy73mqq4uViQ
