decomposition op• Data kinds: image → image
• Call: fullseye.apply(img, "dc_rpca_lowrank", a=0.5, b=0.5) (the 2-D model is one image plus two scalar knobs a,b∈[0,1])

*The figure is the actual output on a synthetic 128×128 input. Left: input, right: output. Point clouds are drawn as a top-down scatter (brightness = z), 1-D series as a line plot, volumes as the maximum-intensity projection along z, videos as the middle frame, complex images as magnitude; return values that are not pictures are shown as the values themselves.*
Sweeping knob a (0.1 / 0.5 / 0.9, the other knob at its default):
▸ dc_rpca_lowrank: knob a sweep (docs site)
*Knob b does not change the output (measured: identical at 0.1 / 0.5 / 0.9).*
On other images (synthetic scene / photo / coins. Top row: inputs, bottom row: their outputs. Knobs at default):
▸ dc_rpca_lowrank: other inputs (docs site)
*The 4th column is a colour (H,W,3) input. This op handles colour without crossing channels (it does not convolve the colour channel as a third spatial axis).*
Robust-PCA low-rank (background) part.
Decomposes the image matrix M into M = L + S (low-rank L + sparse S) by solving Principal Component Pursuit with inexact ALM (Lin/Chen/Ma 2010), and returns L. The weight of the sparse term is λ = (0.5 + 1.5*a) / sqrt(max(m, n)) (m, n are the matrix dimensions at decomposition); the larger a, the sparser S, and correspondingly the components (rank) remaining in L increase. At a=0, λ is small, most of the variation is absorbed into S, and L becomes featureless. b is unused. At most 60 iterations, with the convergence test ||M - L - S||_F <= 1e-7 * ||M||_F.
Images whose longer side exceeds 64 are downscaled to 64 for decomposition, and only L is brought back to the original size by linear interpolation (because the low-rank part tolerates downscaling). The input is brought to 2-D float64 in [0,1] (3-D is channel-averaged); the return value has the same shape, clipped to [0,1]. An all-zero image returns the input unchanged. The number of BLAS threads is limited with fsthreads only during decomposition (for SVD of small matrices, more threads are slower). On exception it is fail-soft: a clipped version of the input is returned and recorded in the ledger.
Since this decomposition treats "structure repeating across rows and columns" (stripes, gradients, periodic patterns) as background, even for a single 2-D image it is well suited to separating isolated defects from periodic backgrounds such as fabric, sheets or display pixels. On non-periodic backgrounds like natural images, L is merely a low-rank approximation and does not become a meaningful background. The paired defect side is dc_rpca_sparse (L + (S - 0.5) == input). To extract structure with edge-preserving smoothing, use dc_structure_texture.
• gallery2d_texture_freq family guide
• blas_threads_and_memory — Why matrix decompositions are slow — BLAS threads, caches, memory layout
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• The canonical algorithm (author, year) and its uses are named in the family usage guide above.
The program below has been verified to run (same input as the figure). In Studio's help this block becomes buttons that load and run it on the spot.
dc_rpca_lowrank 0.50 0.50
▸ Load this pipeline · Load & run
• blas_thread_budget — py -3.11 examples/blas_thread_budget.py
• gallery2d_texture_freq — py -3.11 examples/gallery2d_texture_freq.py
image as input)identity · gaussian · mean_box · bilateral · unsharp · median · min_filter · max_filter
decomposition)dc_structure_texture · dc_texture_residual · dc_rpca_sparse · dc_retinex · dc_local_contrast_norm · dc_homomorphic
*Provenance: ops.py — 2D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.