Skip to main content

This library provides functionality to measure focus levels in images

Project description

focus_response v0.1.4

A Python library for detecting focus regions in images using Ring Difference Filters (RDF) and Kernel Density Estimation (KDE).

frame_223 output_2

output_3

Above outputs were generated using:

detect_focus_regions(image_path, normalize="mad",top_percent=30, bandwidth_px =100)

Installation

pip install focus_response

Usage

Single Image Processing

Process a single image to detect focus regions:

from focus_response import detect_focus_regions

# Basic usage - detect focus regions in an image
results = detect_focus_regions(
    image_path="path/to/image.jpg",
    radii=[(1, 3)],              # Single scale: inner radius=1, outer radius=3
    top_percent=25.0,             # Use top 25% of focus pixels for KDE
    bandwidth_px=10.0,            # KDE smoothing bandwidth in pixels
    power=2,                      # Squared differences (2) or absolute (1)
    normalize="p99",              # Normalization: 'none', 'p99', or 'mad'
    include_strength=False,       # Weight KDE by focus intensity
    show_visualizations=True,     # Display visualization plots
    border_mode='reflect'         # Border handling: 'reflect', 'replicate', 'constant'
)

# Access results
fused_map = results['fused']              # RDF focus map (same size as input)
density_map = results['density']          # KDE density map (0-1 normalized)
threshold = results['threshold']          # Focus threshold value
individual_maps = results['individual_maps']  # List of RDF maps per scale
fuse_time = results['fuse_time']          # RDF computation time (seconds)
kde_time = results['kde_time']            # KDE computation time (seconds)
total_time = results['total_time']        # Total processing time (seconds)

Output Format (Single Image):

  • fused: np.ndarray of shape (H, W) with dtype float32 - Combined RDF focus map
  • density: np.ndarray of shape (H, W) with dtype float32 - KDE density map normalized to [0, 1]
  • threshold: float - The focus value threshold used for selecting top pixels
  • individual_maps: list[np.ndarray] - Individual RDF maps for each scale
  • fuse_time: float - Time spent computing RDF (seconds)
  • kde_time: float - Time spent computing KDE (seconds)
  • total_time: float - Total processing time (seconds)

Batch Processing

Process multiple images efficiently with parallel processing:

from focus_response import batch_process_images, get_image_files, save_results

# Get all images from a folder
image_paths = get_image_files(
    folder_path="path/to/images",
    extensions=('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif'),
    recursive=False  # Set True to search subdirectories
)

print(f"Found {len(image_paths)} images")

# Batch process all images
results = batch_process_images(
    image_paths=image_paths,
    radii=[(1, 3), (2, 5), (3, 7)],  # Multi-scale processing
    top_percent=25.0,
    bandwidth_px=10.0,
    power=2,
    normalize="p99",
    include_strength=False,
    max_workers=None,                 # Auto-detect CPU count
    use_processes=True,               # Use processes (default) or threads (False)
    progress_callback=None,           # Optional: callback(completed, total, path)
    batch_size=None,                  # Process all at once (None) or in batches
    output_folder=None,               # Set to save results incrementally (returns empty dict)
    save_arrays=True,                 # Save .npy arrays (when output_folder is set)
    save_visualizations=False,        # Save .png visualizations (when output_folder is set)
    border_mode='reflect'             # Border handling: 'reflect', 'replicate', 'constant'
)

# Save results manually (if output_folder not specified above)
save_results(
    results=results,
    output_folder="output",
    save_arrays=True,                 # Save raw .npy arrays
    save_visualizations=True,         # Save .png visualizations
    clear_results=False               # Clear results dict after saving to free memory
)

print(f"Processed {len(results)} images successfully!")

Output Format (Batch Processing):

The batch_process_images function returns a dictionary mapping image paths to their processing results.

Note: When output_folder is specified, results are saved to disk incrementally and the function returns an empty dictionary to conserve memory. Results are automatically saved after processing each batch.

{
    'path/to/image1.jpg': {
        'fused': np.ndarray,              # Shape (H, W), dtype float32
        'density': np.ndarray,            # Shape (H, W), dtype float32, range [0, 1]
        'threshold': float,               # Focus threshold value
        'individual_maps': list[np.ndarray],  # Per-scale RDF maps
        'fuse_time': float,               # RDF time in seconds
        'kde_time': float,                # KDE time in seconds
        'total_time': float               # Total time in seconds
    },
    'path/to/image2.jpg': { ... },
    ...
}

Saved Output Structure (when using save_results or output_folder):

output/
├── filter_arrays/          # Raw RDF fused maps (.npy files)
│   ├── image1_filter.npy   # np.ndarray, shape (H, W), dtype float32
│   └── image2_filter.npy
├── kde_arrays/             # Raw KDE density maps (.npy files)
│   ├── image1_kde.npy      # np.ndarray, shape (H, W), dtype float32, range [0, 1]
│   └── image2_kde.npy
├── filter_vis/             # RDF visualizations (optional .png files)
│   ├── image1_filter.png   # Grayscale visualization (0-255)
│   └── image2_filter.png
└── kde_vis/                # KDE visualizations (optional .png files)
    ├── image1_kde.png      # Colored heatmap using COLORMAP_JET
    └── image2_kde.png

Advanced: Using Individual Components

You can also use the individual processing components:

import cv2
from focus_response import fuse_rdf_sum, kde_on_fused, visualize_kde_density

# Load image
img = cv2.imread("path/to/image.jpg", cv2.IMREAD_GRAYSCALE)

# Step 1: Compute RDF focus map
fused, maps = fuse_rdf_sum(
    img=img,
    radii=[(1, 3), (2, 5)],
    power=2,
    use_numba=False,
    normalize="p99",
    parallel=True,
    downsample=None,                  # Optional: downsample factor (e.g., 2 or 4) for large images
    border_mode='reflect'             # Border handling: 'reflect', 'replicate', 'constant'
)

# Step 2: Apply KDE to get density map
density, threshold = kde_on_fused(
    fused=fused,
    top_percent=25.0,
    bandwidth_px=10.0,
    include_strength=False,
    clip_percentile=99.5,
    normalize=True
)

# Step 3: Visualize results
visualize_kde_density(img, fused, density, show_on="image")  # Overlay on original
visualize_kde_density(img, fused, density, show_on="focus")  # Overlay on focus map

Development

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black .

# Lint
flake8

References

  1. Surh, J., Jeon, H. G., Park, Y., Im, S., Ha, H., & So Kweon, I. (2017). Noise robust depth from focus using a ring difference filter. In Proceedings of the IEEE conference on computer vision and pattern recognition (pp. 6328-6337).

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

focus_response-0.1.5.tar.gz (26.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

focus_response-0.1.5-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

Details for the file focus_response-0.1.5.tar.gz.

File metadata

  • Download URL: focus_response-0.1.5.tar.gz
  • Upload date:
  • Size: 26.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for focus_response-0.1.5.tar.gz
Algorithm Hash digest
SHA256 419c84708708513c4567f31107ca0564d0dfee7aca03595ccb491abec19a9edf
MD5 46c47d9fee9fc9a42a6633585cd7c3f8
BLAKE2b-256 29ed75e5c39a289949610e2abd486a552b12954fc3c9f8f5638cb7a361ce8a90

See more details on using hashes here.

Provenance

The following attestation bundles were made for focus_response-0.1.5.tar.gz:

Publisher: python-publish.yml on rishik18/focus_response

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file focus_response-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: focus_response-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 20.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for focus_response-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 fdcc2a07db0b405d5b68596d34244962891b856e4156e9a46acffdd655bde248
MD5 c4dbcb020af261e5145b155bfdbdb925
BLAKE2b-256 25e04088b0acfd55d67d6b9ff31cf598005ee9884b25963b245964735d02a78f

See more details on using hashes here.

Provenance

The following attestation bundles were made for focus_response-0.1.5-py3-none-any.whl:

Publisher: python-publish.yml on rishik18/focus_response

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page