Function: Blemish Blaster - setiastro/setiastrosuitepro GitHub Wiki

Blemish Blaster

An interactive, fast “click-to-heal” tool for removing small artifacts (hot pixels, cosmic rays, dust motes, satellite specks) in astro images. Designed for smooth UX with live preview, threaded processing, undo/redo, and optional auto-stretch (preview only).


What it does

  • Removes localized defects by sampling nearby clean neighborhoods and blending a robust statistic back into a circular target area.
  • Works with RGB and mono sources. Internally normalizes to float32 [0,1].
  • Non-destructive until you click Apply to Document.

Core algorithm

  1. Neighborhood selection

    • Around the click point (x,y) and chosen radius, compute the target median inside the circle.
    • Place 6 neighbor centers at angles [0°, 60°, 120°, 180°, 240°, 300°] at a distance 1.5 × radius.
    • Measure the circle median at each neighbor; pick the 3 neighbors whose medians are closest to the target median (most similar background).
  2. Per-pixel repair

    • For each pixel inside the target circle:

      • Gather aligned samples from the 3 selected neighbor positions (offset-mapped back to the current pixel).

      • Take the median of those samples as the replacement value (robust against outliers).

      • Compute a feather weight (linear falloff from center to edge):

        weight = 1.0                      if feather == 0
               = max(0, (radius - dist) / (radius * feather)) otherwise
        
      • Blend with opacity:

        new = (1 - opacity*weight)*orig + (opacity*weight)*median
        
    • Channels are processed independently (RGB) or as a single plane (mono).

  3. Threaded execution

    • The heal operation runs in a _BlemishWorker (QRunnable) on the global QThreadPool for a responsive UI.

Dialog: BlemishBlasterDialogPro

UI & workflow

  • Canvas: QGraphicsView shows a 3-channel preview buffer (mono inputs are replicated to RGB for display).
  • Cursor ring: Hover shows the current radius (dashed circle).
  • Click to heal: Left-click runs the threaded repair at cursor position.
  • Undo / Redo: Standard shortcuts (Ctrl/Cmd-Z / Ctrl/Cmd-Shift-Z).
  • Zoom: Mouse wheel (bounded 0.05–4.0×), auto-fit on first paint.

Controls

  • Radius (1–900 px): size of the blemish area to repair.

  • Feather (0–100%): edge falloff; 0% = hard replace, higher = smoother blend.

  • Opacity (0–100%): overall strength of the repair.

  • Auto-stretch preview (checkbox): display-only contrast stretch.

    • Target median (0.01–0.60): stretch aim.
    • Linked color channels: apply identical curve to RGB (typical astro workflow).
  • Apply to Document: Writes the corrected data back to the host document.

Data I/O

  • Input is normalized to float32 [0,1].

  • On Apply, output is clipped to [0,1] and:

    • For mono sources, the preview’s RGB is collapsed back to one channel (shape preserved).
    • Tries doc.set_image(..., step_name="Blemish Blaster"), then doc.apply_numpy(...), then direct doc.image = ....

Public types & internals

  • Worker

    • _BlemishWorker(image, x, y, radius, feather, opacity, channels_to_process)

    • Emits finished(np.ndarray) with the corrected image.

    • Key helpers:

      • _remove_blemish(...) — implements the algorithm above.
      • _median_circle(image, cx, cy, radius, channels) — robust per-channel circular median.
  • Signals

    • _BBWorkerSignals.finished(np.ndarray)
  • Preview stretch

    • Color: stretch_color_image(...)
    • Mono: stretch_mono_image(...)
    • These affect only the display (_display), never the working data (_image).

Notes & best practices

  • Pick radius just large enough to cover the defect plus a small margin; too large a radius may pull in gradients or structures.
  • Feather + Opacity control how gently the fix merges with its surroundings.
  • The neighbor selection prefers regions with similar background—good for sky noise and faint gradients while avoiding bright structures.
  • For mono workflows, enabling auto-stretch still displays in RGB for clarity, but the write-back is correctly mono.

Typical usage

# Inside your app:
dlg = BlemishBlasterDialogPro(parent=self, doc=current_doc)
dlg.exec()  # left-click to heal, tweak sliders, Apply to commit

Error handling

  • Raises on unsupported image shapes; guards array bounds during sampling.
  • UI warns on write-back failures; stays responsive thanks to threaded workers.

Performance

  • O(N) in circle area per click; sampling is vectorized/NumPy-based.
  • Threaded execution keeps the GUI fluid during repairs.