DevLab / utilities / screenshot-to-text-ocr-extractor
UTILITIES PYTHON BEGINNER

Screenshot to Text OCR Extractor

Engineers and system administrators frequently encounter text trapped inside visual formats: error dialogs in remote desktop sessions, system architecture

Python3.10+
OSLinux / macOS / Windows
Lines~144
Packages2 deps
Install Dependencies
$ pip install Pillow pytesseract
Usage
$ python3 ocr_extract.py --image screenshot.png --lang eng
#utilities#python#beginner#Pillow#pytesseract

Problem Statement

Engineers and system administrators frequently encounter text trapped inside visual formats: error dialogs in remote desktop sessions, system architecture diagrams, screenshot-based documentation, or locked PDF presentations. Manually transcribing logs or configuration strings from screenshots is slow, tedious, and prone to human error—especially when dealing with long cryptographic keys, stack traces, or complex URLs.

This script provides a lightweight command-line OCR (Optical Character Recognition) utility that converts image screenshots into clean, structured plain text. By integrating Pillow for image manipulation and pytesseract as an interface to the open-source Tesseract OCR engine, it offers a quick CLI tool for single images, automated batch pipelines, or shell script integration.


How It Works

The utility follows a linear pipeline: CLI argument parsing -> file validation -> image preprocessing -> OCR extraction -> text formatting/output.

When an image file path is provided, the script validates its existence and opens it using Pillow (PIL). Optional preprocessing steps—such as converting to grayscale, boosting contrast, or applying thresholding—can be applied before feeding the image to Tesseract. These adjustments significantly improve recognition accuracy for low-contrast screenshots or terminal capture outputs. Finally, pytesseract passes the image array to the underlying system Tesseract engine, which performs layout analysis and character recognition, returning the extracted text to standard output or a designated file.


Full Script

#!/usr/bin/env python3
"""
Screenshot to Text OCR Extractor
Extracts raw text from screenshot images using PIL and PyTesseract.
Supports optional image preprocessing to enhance OCR accuracy.
"""

import argparse
import os
import sys
from pathlib import Path
from typing import Optional

from PIL import Image, ImageEnhance, ImageFilter
import pytesseract

# Configure Tesseract binary path if set in environment
TESSERACT_CMD: Optional[str] = os.environ.get("TESSERACT_CMD")
if TESSERACT_CMD:
    pytesseract.pytesseract.tesseract_cmd = TESSERACT_CMD

# Default configuration options from environment variables
DEFAULT_LANG: str = os.environ.get("OCR_DEFAULT_LANG", "eng")
DEFAULT_PSM: int = int(os.environ.get("OCR_DEFAULT_PSM", "3"))


def preprocess_image(image: Image.Image, mode: str) -> Image.Image:
    """
    Applies image processing transforms to enhance text legibility for OCR.

    Args:
        image: Source PIL Image object.
        mode: Preprocessing technique ('grayscale', 'contrast', 'threshold', or 'none').

    Returns:
        Processed PIL Image object.
    """
    if mode == "none":
        return image

    # Convert to grayscale first for all processing modes
    gray_image = image.convert("L")

    if mode == "grayscale":
        return gray_image

    if mode == "contrast":
        enhancer = ImageEnhance.Contrast(gray_image)
        return enhancer.enhance(2.0)

    if mode == "threshold":
        # Simple binarization: pixels > 150 become white, others black
        threshold_value = 150
        return gray_image.point(lambda pixel: 255 if pixel > threshold_value else 0)

    return image


def extract_text(
    image_path: Path,
    lang: str = "eng",
    psm: int = 3,
    preprocess_mode: str = "none"
) -> str:
    """
    Loads an image file, preprocesses it, and performs OCR text extraction.

    Args:
        image_path: Path to the image file.
        lang: Tesseract language code (e.g., 'eng', 'spa', 'deu').
        psm: Page Segmentation Mode (0-13).
        preprocess_mode: Image transformation mode before extraction.

    Returns:
        Extracted text string.

    Raises:
        FileNotFoundError: If the image path does not exist.
        RuntimeError: If Tesseract fails or is not properly installed.
    """
    if not image_path.exists():
        raise FileNotFoundError(f"Target image file not found: {image_path}")

    try:
        with Image.open(image_path) as img:
            processed_img = preprocess_image(img, preprocess_mode)
            
            # Configure custom page segmentation mode
            custom_config = f"--psm {psm}"
            
            extracted_text = pytesseract.image_to_string(
                processed_img,
                lang=lang,
                config=custom_config
            )
            return extracted_text.strip()

    except pytesseract.TesseractNotFoundError:
        raise RuntimeError(
            "Tesseract OCR executable was not found on your system PATH.\n"
            "Please install Tesseract-OCR or set the TESSERACT_CMD environment variable."
        )
    except pytesseract.TesseractError as err:
        raise RuntimeError(f"Tesseract engine processing failed: {err}")
    except Exception as err:
        raise RuntimeError(f"An error occurred while reading image: {err}")


def build_cli_parser() -> argparse.ArgumentParser:
    """Builds and returns the command line argument parser."""
    parser = argparse.ArgumentParser(
        description="Extract text from screenshot images using Tesseract OCR."
    )
    
    parser.add_argument(
        "-i", "--image",
        type=Path,
        required=True,
        help="Path to the screenshot image file."
    )
    parser.add_argument(
        "-o", "--output",
        type=Path,
        default=None,
        help="Optional path to save extracted text output."
    )
    parser.add_argument(
        "-l", "--lang",
        type=str,
        default=DEFAULT_LANG,
        help=f"Language for OCR processing (default: {DEFAULT_LANG})."
    )
    parser.add_argument(
        "--psm",
        type=int,
        default=DEFAULT_PSM,
        help=f"Page Segmentation Mode (0-13, default: {DEFAULT_PSM})."
    )
    parser.add_argument(
        "-p", "--preprocess",
        choices=["none", "grayscale", "contrast", "threshold"],
        default="none",
        help="Image preprocessing mode to improve extraction quality."
    )

    return parser


def main() -> None:
    """CLI entrypoint for the OCR script."""
    parser = build_cli_parser()
    args = parser.parse_args()

    try:
        text = extract_text(
            image_path=args.image,
            lang=args.lang,
            psm=args.psm,
            preprocess_mode=args.preprocess
        )

        if not text:
            print("Warning: No text could be detected in the provided image.", file=sys.stderr)

        if args.output:
            args.output.parent.mkdir(parents=True, exist_ok=True)
            args.output.write_text(text, encoding="utf-8")
            print(f"Successfully saved extracted text to {args.output}")
        else:
            print(text)

    except (FileNotFoundError, RuntimeError) as err:
        print(f"Error: {err}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()

Configuration

This script supports configuration through both system environment variables and command-line flags.

Environment Variable Default Value Description
TESSERACT_CMD None Path to the binary executable if Tesseract is not installed in standard system PATH.
OCR_DEFAULT_LANG eng Default 3-letter ISO language code used when --lang is omitted.
OCR_DEFAULT_PSM 3 Default Page Segmentation Mode used when --psm is omitted.

System Prerequisites

Before running the script, ensure the Tesseract system library is installed:

  • macOS: brew install tesseract
  • Ubuntu/Debian: sudo apt-get install tesseract-ocr
  • Windows: Download installer from Tesseract GitHub repository and set TESSERACT_CMD="C:\Program Files\Tesseract-OCR\tesseract.exe".

Usage Examples

Example 1: Basic Extraction to Console

Extract text from a standard terminal screenshot and print directly to stdout.

python3 ocr_extract.py --image terminal_error.png

Output:

[ERROR] 2026-03-30 10:14:02 - Failed to bind port 8080: Address already in use
Traceback (most recent call last):
  File "server.py", line 42, in start
    server.bind(("0.0.0.0", 8080))
OSError: [Errno 98] Address already in use

Example 2: Saving Output with Image Preprocessing

Process a low-contrast image using grayscale conversion and contrast enhancement, saving the result directly to a file.

python3 ocr_extract.py --image low_contrast_log.png --preprocess contrast --output extracted_log.txt

Output:

Successfully saved extracted text to extracted_log.txt

Example 3: Changing OCR Language and Segmentation Mode

Extract text from a single line of text in Spanish using Page Segmentation Mode 7 (Treat image as a single text line).

python3 ocr_extract.py --image Spanish_Banner.png --lang spa --psm 7

Output:

Acceso denegado. Consulte con el administrador.

Error Handling

The script provides explicit error reporting for common execution failures:

  1. Missing Input Image (FileNotFoundError): Verifies that the source image path exists on the filesystem prior to attempting to read it.
  2. Missing Tesseract Engine (TesseractNotFoundError): Catches missing system binaries and provides clear instructions on setting TESSERACT_CMD or installing the package.
  3. Invalid Language Data (TesseractError): If a language code specified via --lang is missing its corresponding traineddata file (e.g., spa.traineddata), Tesseract raises an engine error, which is caught and printed without dumping Python backtraces.
  4. Empty Image Content: Detects when OCR runs successfully but returns no plain text content, warning the user via stderr.

Extending Ideas

Here are several ways you can expand this script for operational workflows:

  • Clipboard Integration: Integrate pyperclip to automatically capture screenshots straight from the OS system clipboard without needing an intermediate saved file.
  • Automated Directory Watcher: Wrap this utility with watchdog to automatically scan and convert any new image files added to a designated ~/Screenshots folder.
  • Structured Output (JSON/PDF): Modify the pytesseract call to generate bounding box coordinates (image_to_boxes) or search-searchable PDFs (image_to_pdf_or_hocr) rather than raw text.
  • Regex Processing: Add an optional pipeline stage using Python's re module to filter output specifically for URLs, IP addresses, AWS Access Keys, or log timestamps.
// RELATED_SCRIPTS
← Back to DevLab valtersit.com