Documentation
¶
Overview ¶
Package unpixel reconstructs text hidden behind pixelation.
UnPixel attempts to recover the original text from a pixelated (mosaic-blurred) image region. The algorithm works by rendering each candidate string into an off-screen image, re-applying the same block-average pixelation with the same grid origin, and measuring the pixel-level distance against the redacted region. A guided depth-first search explores the candidate space character by character, pruning branches whose cumulative score exceeds the configured threshold.
Usage ¶
Obtain or synthesise an image.Image containing the pixelated region, construct an Engine with New, and call Run. Import the defaults package for its side-effect to wire the standard renderer, pixelator, metric, and search strategy; without it the components must be supplied explicitly in Config.
import _ "github.com/oioio-space/unpixel/defaults" // wire default components
eng, err := unpixel.New(img, unpixel.Config{})
if err != nil { ... }
progCh, resCh := eng.Run(ctx)
unpixel.OnProgress(progCh, func(p unpixel.Progress) {
fmt.Println(p.BestGuess)
})
for r := range resCh {
fmt.Println(r.BestGuess, r.BestScore)
}
UnPixel is a faithful Go port of Bishop Fox's unredacter (GPL-3.0).
Example ¶
Example demonstrates the quick-start usage of UnPixel: construct an Engine from a pixelated image, run the search, consume progress events, then collect results. The image here is a small synthetic white rectangle used purely to keep the example self-contained and fast; in practice, supply the actual pixelated screenshot region.
package main
import (
"context"
"fmt"
"image"
"image/color"
"github.com/oioio-space/unpixel"
_ "github.com/oioio-space/unpixel/defaults"
)
func main() {
// Build a tiny synthetic image to stand in for a real pixelated screenshot.
img := image.NewRGBA(image.Rect(0, 0, 64, 16))
for y := range img.Bounds().Dy() {
for x := range img.Bounds().Dx() {
img.SetRGBA(x, y, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
}
}
eng, err := unpixel.New(img, unpixel.Config{
Charset: "ab ",
MaxLength: 2,
BlockSize: unpixel.DefaultBlockSize,
})
if err != nil {
fmt.Println("new:", err)
return
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
progCh, resCh := eng.Run(ctx)
// Consume progress events concurrently while collecting results below.
// OnProgress blocks until the progress channel is closed (EventDone).
done := make(chan struct{})
go func() {
defer close(done)
unpixel.OnProgress(progCh, func(p unpixel.Progress) {
if p.Kind == unpixel.EventNewBest {
fmt.Println("new best:", p.BestGuess)
}
})
}()
for r := range resCh {
if r.Err != nil {
fmt.Println("result error:", r.Err)
continue
}
fmt.Println("result:", r.BestGuess)
}
<-done
}
Output:
Index ¶
- Constants
- Variables
- func InferBlockSize(img image.Image) int
- func InferBlockSizeRobust(img image.Image) (blockSize int, support float64)
- func InferBlurSigma(img image.Image) float64
- func InferDarkBackground(img image.Image) bool
- func InferFontSize(img image.Image) float64
- func InferGridPhase(img *image.RGBA, block int) (image.Point, bool)
- func InferImpulseNoise(img image.Image) float64
- func InferXStretch(mosaic image.Image, blockSize int, refWidthPx int) (float64, bool)
- func LocateRedaction(img image.Image) (image.Rectangle, bool)
- func OnProgress(ch <-chan Progress, fn func(Progress))
- type BlockGrid
- type Config
- type Engine
- type Eval
- type EventKind
- type FontResult
- type ImageVerdict
- type Metric
- type Offset
- type Option
- func WithAuto() Option
- func WithAutoBlur() Option
- func WithAutoCalibrate() Option
- func WithAutoColorspace() Option
- func WithAutoCrop() Option
- func WithBeamWidth(width int) Option
- func WithBlockSize(n int) Option
- func WithCharset(charset string) Option
- func WithCharsetTopK(k int) Option
- func WithConfig(cfg Config) Option
- func WithCrop(band image.Rectangle) Option
- func WithExpectedFormat(f secrets.Format) Option
- func WithFontPrior() Option
- func WithFontPriorTopK(k int) Option
- func WithL0Deblur(fns ...func(*deblur.L0Options)) Option
- func WithLanguageModel(score func(string) float64) Option
- func WithMaxLength(n int) Option
- func WithMetric(m Metric) Option
- func WithNormalize(fns ...func(*deblur.Options)) Option
- func WithPixelator(p Pixelator) Option
- func WithPrefix(prefix string) Option
- func WithPriors(priors ...func(string) float64) Option
- func WithRemosaic() Option
- func WithRemosaicGrid(b int) Option
- func WithRemosaicLinear() Option
- func WithRenderer(r Renderer) Option
- func WithRerankWeight(w float64) Option
- func WithStrategy(s Strategy) Option
- func WithStyle(s Style) Option
- func WithThreshold(t float64) Option
- func WithTopN(n int) Option
- func WithVerifyThreshold(t float64) Option
- func WithWorkers(n int) Option
- type Pixelator
- type Progress
- type Renderer
- type Result
- func Recover(ctx context.Context, redacted image.Image, opts ...Option) (Result, error)
- func RecoverBlurred(ctx context.Context, img image.Image, opts ...Option) (Result, error)
- func RecoverBlurredFile(ctx context.Context, path string, opts ...Option) (Result, error)
- func RecoverBlurredReader(ctx context.Context, r io.Reader, opts ...Option) (Result, error)
- func RecoverBytes(ctx context.Context, data []byte, opts ...Option) (Result, error)
- func RecoverFile(ctx context.Context, path string, opts ...Option) (Result, error)
- func RecoverReader(ctx context.Context, r io.Reader, opts ...Option) (Result, error)
- type SkewInfo
- type Strategy
- type Style
- type Verdict
- func Verify(ctx context.Context, img image.Image, candidates []string, opts ...Option) ([]Verdict, error)
- func VerifyBytes(ctx context.Context, data []byte, candidates []string, opts ...Option) ([]Verdict, error)
- func VerifyFile(ctx context.Context, path string, candidates []string, opts ...Option) ([]Verdict, error)
- func VerifyReader(ctx context.Context, r io.Reader, candidates []string, opts ...Option) ([]Verdict, error)
Examples ¶
Constants ¶
const ( // CharsetLower is lowercase ASCII letters plus space (the faithful default). CharsetLower = DefaultCharset // CharsetDigits is the ten decimal digits — the narrowest useful alphabet, for // PINs, card numbers, and other purely numeric secrets. The tighter the charset // the smaller the search, so prefer this when the target is known to be numeric. CharsetDigits = "0123456789" // CharsetHex is the lowercase hexadecimal alphabet (0-9a-f), for hashes, hex // tokens, and colour codes. CharsetHex = "0123456789abcdef" // CharsetAlnum adds uppercase letters and digits to CharsetLower. CharsetAlnum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " // CharsetASCII is every printable ASCII character (0x20–0x7E). Use it for // source code and other symbol-heavy text. CharsetASCII = " !\"#$%&'()*+,-./0123456789:;<=>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" )
Candidate-alphabet presets for Config.Charset (or WithCharset). A wider charset recovers more text but enlarges the search space, so prefer the narrowest one that fits the target.
const ( // DefaultCharset is the candidate alphabet: lowercase ASCII letters and space. DefaultCharset = "abcdefghijklmnopqrstuvwxyz " // DefaultMaxLength is the maximum candidate string length the search explores. DefaultMaxLength = 20 // DefaultBlockSize is the pixelation block side length in pixels. DefaultBlockSize = 8 // DefaultThreshold is the per-block score gate for non-space characters; // candidates scoring above this value are pruned. DefaultThreshold = 0.25 // DefaultSpaceThreshold is the per-block score gate for the space character, // which is visually ambiguous and requires a more permissive threshold. DefaultSpaceThreshold = 0.5 // DefaultTopN is the default maximum number of ranked candidates retained // per grid offset and exposed on Result.TopN. DefaultTopN = 5 // DefaultBeamWidth is the number of candidates retained per depth level by // BeamStrategy. Larger values improve recall at the cost of more evaluations. DefaultBeamWidth = 16 // DefaultCacheSize is the maximum number of stageImage results held by // CachingScorer. Zero disables caching. DefaultCacheSize = 4096 )
Default configuration values, matching the original unredacter reference implementation.
const RobustSupportThreshold = 0.5
RobustSupportThreshold is the minimum autocorrelation support score (in [0, 1]) that InferBlockSizeRobust considers a detectable periodic block structure. A value of 0.5 means at least half of the boundary signal must align with the dominant period; below this the detector reports no grid.
const ( // VerifyMatchThreshold is the absolute distance below which a candidate is // considered a confident physical match. Calibrated so that exact recoveries // (distance ≈ 0) match and clearly-wrong candidates do not. VerifyMatchThreshold = 0.10 )
Variables ¶
var DefaultBlurStrategy func() Strategy
DefaultBlurStrategy is a hook that returns the default Strategy used by RecoverBlurred when the caller has not supplied one via WithStrategy. It is populated by importing the defaults package for its side-effect.
The default is BeamStrategy: beam search bounds the per-level branching factor to DefaultBeamWidth candidates, giving O(length × width) evaluations regardless of charset size — critical for longer words (≥5 chars) behind blur, where per-character image signal is too weak for guided DFS's unbounded expansion to finish in reasonable time. Callers that need full recall (at higher cost) can override with WithStrategy(defaults.GuidedStrategy()).
var DefaultComponents func(cfg *Config) error
DefaultComponents is a hook that wires the standard Renderer, Pixelator, Metric, and Strategy into cfg for any fields that are still nil. It is populated by importing the defaults package for its side-effect, which avoids an import cycle between the root package and its internal implementations. Applications that supply all component fields explicitly need not set this.
var DefaultConstrainedStrategy func(prefix string) Strategy
DefaultConstrainedStrategy is a hook populated by importing the defaults package for its side-effect. It returns a Strategy that runs GuidedDFS constrained to the given prefix string. A nil hook silently falls back to the unconstrained GuidedDFS (byte-identical behaviour), so callers that supply all components explicitly and do not use WithPrefix need not import defaults.
var DefaultFormatStrategy func(format secrets.Format) Strategy
DefaultFormatStrategy is a hook populated by importing the defaults package for its side-effect. It returns a Strategy that runs GuidedDFS constrained to the given structured-secret format (per-position feasibility plus a leaf validity filter). A nil hook means WithExpectedFormat is a no-op, so callers that wire all components explicitly and do not use WithExpectedFormat need not import defaults.
DefaultLocateMosaicBand is a hook populated by importing the defaults package for its side-effect. It finds the grid-aligned bounding box of a pixelated (block-constant) region inside img and is called by New when WithAutoCrop is active. A nil hook disables auto-crop silently, so callers that supply all components explicitly and do not need auto-crop need not import defaults.
var DefaultVerifyCore func(ctx context.Context, rgba *image.RGBA, cfg Config, candidates []string) ([]Verdict, error)
DefaultVerifyCore is a hook populated by importing the defaults package for its side-effect. It scores each candidate string against the already-prepped rgba image using the faithful forward model (PipelineScorer + DiscoverOffsets) and returns one Verdict per candidate, in input order. Verify delegates the search-package work to this hook to avoid an import cycle between the root package and internal/search (which imports the root package itself). A nil hook causes Verify to return ErrNoComponents.
var DefaultVerifyImageCore func(ctx context.Context, redacted, restored *image.RGBA, cfg Config) (ImageVerdict, error)
DefaultVerifyImageCore is a hook populated by importing the defaults package for its side-effect. It physically verifies an already-prepped restored image against the prepped redaction by re-applying the forward operator (cfg's Pixelator) at the best grid phase and comparing with cfg's Metric. VerifyImage delegates to it to avoid an import cycle with internal packages. A nil hook makes VerifyImage return ErrNoComponents.
var ErrNilImage = errors.New("redacted image must not be nil")
ErrNilImage is returned by New when a nil image is passed.
var ErrNoComponents = errors.New("unpixel: missing component and no DefaultComponents wired; " +
"import github.com/oioio-space/unpixel/defaults or set the component via options")
ErrNoComponents is returned by the Recover helpers when the Config leaves a component (Renderer, Pixelator, Metric, or Strategy) nil and the defaults package has not been imported to wire them.
Functions ¶
func InferBlockSize ¶ added in v0.2.0
InferBlockSize estimates the pixelation block size, in pixels, of a mosaic- redacted image by detecting the spacing of its block grid. It scans for the columns and rows where the colour changes — the boundaries between constant- colour blocks — and returns the greatest common divisor of the gaps between them, which equals the block side length even when some adjacent blocks happen to share a colour (their gap is then a multiple of the block size).
It returns 0 when the grid cannot be determined — a uniform image, an image smaller than 2×2, or a non-pixelated image whose gaps reduce to 1. New uses it to fill a non-positive Config.BlockSize, falling back to DefaultBlockSize when inference returns 0.
func InferBlockSizeRobust ¶ added in v0.9.0
InferBlockSizeRobust detects the mosaic block size using autocorrelation of the boundary signal, tolerating noisy or anti-aliased block edges caused by resampling, JPEG compression, or screenshot scaling.
It builds a binary boundary signal (1 at each column/row where the colour changes appreciably, 0 elsewhere), computes its autocorrelation, and finds the dominant period in the range [minRobustPeriod, maxRobustPeriod]. The support score in [0, 1] reflects how consistently boundaries align with that period: 1.0 means every boundary falls exactly on a grid line; values above RobustSupportThreshold indicate a detectable periodic structure.
When the exact-GCD result from InferBlockSize is available and its implied autocorrelation support exceeds the autocorrelation peak, the exact result wins (preserving byte-identical behaviour for clean mosaics). When the image is too small, uniform, or has no detectable period, it returns (0, 0).
func InferBlurSigma ¶ added in v0.4.0
InferBlurSigma estimates the Gaussian-blur standard deviation (in pixels) of a blurred image using an edge-spread formula with a density-adaptive gradient percentile. The approach is purely spatial — no FFT — and is calibrated for both sparse step-edge inputs (large images, small σ) and dense text images (small images, large σ) (Polyblur / Chen & Ma gradient-ratio insight, Hill 2016 redaction paper).
Method ¶
For a Gaussian-blurred step edge, the peak gradient is contrast/(σ·√(2π)). Inverting: σ = contrast/(gPeak·√(2π)). The challenge is robustly estimating gPeak from the gradient distribution:
- A fixed high percentile (e.g. 99th) over-selects for dense-edge images (text) but under-selects for sparse-edge images (single step in a large field), landing on the gradient shoulder rather than the peak.
- A fixed very-high percentile (e.g. 99.9th) works for sparse edges but over-selects for dense-edge text images, picking noise outliers.
The solution: measure the edge density (fraction of gradient pairs above 5% of contrast), and adaptively choose the percentile as:
pct = clamp(1 − edgeFrac × 0.05, 0.95, 0.999)
This keeps the selected gradient within the true-peak region of the edge distribution regardless of whether edges cover 1% (large step) or 20% (dense text) of the image area. The constant 0.05 is calibrated to within ±35% accuracy for σ ∈ [1,8] on both step-edge and rendered-text inputs.
It returns 0 when the image is too small or essentially flat (contrast < 8). A returned value near 0 means the image is sharp (probably not blurred); a larger value is the estimated blur radius. The estimate is a starting point for the σ-sweep in RecoverBlurred — accuracy within ±35% is sufficient.
func InferDarkBackground ¶ added in v0.3.0
InferDarkBackground reports whether img looks like dark text/content on a dark background (e.g. a dark-mode screenshot), judged from its border pixels. New uses it to decide whether to invert the image so it matches the dark-on-light rendering pipeline.
func InferFontSize ¶ added in v0.4.0
InferFontSize estimates the point size of the text in img from its content height, for zero-config calibration: rendered text spans about 0.92×fontSize vertically (ascenders to descenders), so fontSize ≈ contentHeight / 0.92. "Content" is any row that differs from the image's background colour.
It returns 0 when no content stands out. The estimate is a ballpark — a short word without ascenders/descenders, or blur spreading the glyphs, skews it — so it is best used to seed the search (optionally with a small size sweep) rather than as an exact value. Measure it on the redacted region (see LocateRedaction) or on a screenshot's sharp reference text, whichever is cleaner.
func InferGridPhase ¶ added in v0.15.0
InferGridPhase estimates the (x, y) phase offset of the block grid in img for a grid whose block size is already known (block). It detects the pixel positions where adjacent rows or columns differ appreciably, and returns the modal residue of those positions modulo block as the phase.
Unlike InferBlockGrid, which auto-detects block size, InferGridPhase skips that step and is therefore faster when the caller already knows the block size (e.g. from --block-size or a prior InferBlockGrid call).
The returned image.Point holds (PhaseX, PhaseY): block boundaries fall at columns x ≡ PhaseX (mod block) and rows y ≡ PhaseY (mod block).
It returns ok=false when the image is smaller than 2×2 or has no detectable colour boundaries (uniform or near-uniform image), in which case the phase cannot be estimated and the zero Point is returned.
func InferImpulseNoise ¶ added in v0.7.0
InferImpulseNoise estimates the fraction [0, 1] of impulse-corrupted pixels in img. It is a cheap sampled estimate (O(samples), ≤ 50 000 pixels checked) used by blind.Recover to decide whether to apply a median pre-filter automatically before block-size detection and decoding.
Method (RVIN / local-extremum test from the SAPN literature): for each sampled interior pixel p, collect the BT.601 luminance of its 8 neighbours. Pixel p is counted as an impulse if both of the following hold:
- |lum(p) – median8| > impulseNoiseThreshold (large deviation from context).
- lum(p) is the strict minimum OR strict maximum among the 9 values in the 3×3 window (isolated spike, not part of a ramp).
Condition 2 rejects smooth gradients and structured block edges — an edge pixel sits between two blocks whose colours straddle its own, so it is never the strict extremum of its 3×3 neighbourhood.
Returns impulse_count / samples_checked. An empty or sub-3×3 image returns 0.
func InferXStretch ¶ added in v0.15.0
InferXStretch estimates the anisotropic horizontal scale factor applied to the text before it was pixelated — for example, the ~1.06× stretch that GIMP applies when its canvas DPI differs from the font DPI.
Method: the mosaic's non-background content spans some number of columns; multiplying that span by blockSize gives the observed width in pixels. Dividing by refWidthPx — the pixel width that the renderer produces at stretch 1.0 for the same text — yields the stretch factor.
Parameters:
- mosaic: the pixelated region (any image.Image subtype).
- blockSize: the mosaic block side length in pixels (e.g. from InferBlockGrid).
- refWidthPx: the pixel advance of the reference render at stretch=1.0, e.g. the sentinelX returned by render.XImage.Render for the same text and font size.
It returns ok=false when refWidthPx ≤ 0, when the image is too small to analyse (< 2×2), or when no non-background content is detectable in the image.
Accuracy: the mosaic quantises the content edge to the nearest block boundary, introducing an inherent ±½ block uncertainty. For a typical 32 pt / 8 px block / 120 px text span the rounding error is ≤ 3 %, so the estimate is useful as a search seed but not as an exact calibration.
func LocateRedaction ¶ added in v0.4.0
LocateRedaction returns the bounding box of a blurred region inside img — for zero-config recovery of a redaction embedded in a larger screenshot. A blurred edge has a bounded peak gradient (≈ contrast/(σ·√(2π)), far below sharp text), so a row/column is "blurred content" when it carries contrast yet its peak luminance gradient stays low. The result is the tight box of the largest such band; ok is false when no blurred region stands out (e.g. an all-sharp image).
It is the missing piece for screenshots: estimating sigma or recovering on the whole image is skewed by sharp surrounding text (on the Bishop Fox challenge, whole-image σ≈0.6 vs ≈5.6 on the blurred line), so crop to this box first.
func OnProgress ¶
OnProgress drains the progress channel returned by Engine.Run, calling fn for every event in order. It blocks until the channel is closed (i.e. until EventDone has been delivered and consumed). It is a convenience wrapper around a range loop and does not start a goroutine.
Types ¶
type BlockGrid ¶ added in v0.6.0
type BlockGrid struct {
// Size is the block side length in pixels, equal to InferBlockSize.
Size int
// PhaseX is the horizontal grid origin offset: block boundaries fall at
// column positions x ≡ PhaseX (mod Size).
PhaseX int
// PhaseY is the vertical grid origin offset: block boundaries fall at
// row positions y ≡ PhaseY (mod Size).
PhaseY int
// Confidence is the fraction of detected boundary positions whose residue
// (mod Size) matches the modal residue, averaged across X and Y. It is in
// [0, 1]: 1.0 for a perfectly axis-aligned mosaic; near 0 for a rotated or
// irregular image.
Confidence float64
}
BlockGrid describes a detected axis-aligned mosaic lattice.
A mosaic image has piecewise-constant blocks of size Size×Size pixels. The block boundaries fall at positions x ≡ PhaseX (mod Size) in X and y ≡ PhaseY (mod Size) in Y. Confidence measures how consistently the detected colour-change positions agree with this lattice.
func InferBlockGrid ¶ added in v0.6.0
InferBlockGrid detects the mosaic lattice — block size and grid origin phase — of a pixelated image. It returns the detected BlockGrid and ok=true when a regular axis-aligned grid is found, or the zero BlockGrid and ok=false when the image is too small, uniform, or has no regular grid (same cases where InferBlockSize returns 0).
Block-size detection uses a three-stage cascade, each stage activating only when the previous one fails or produces an apparent sub-harmonic:
Exact GCD: the GCD of all inter-boundary gaps (fast, zero regression risk for clean axis-aligned mosaics). Returns the true block size when every detected boundary is a genuine grid line.
Dominant-gap fallback (partial-edge robustness): when the exact GCD is < 2 — which happens when a partial-edge block creates a small gap (equal to the grid phase offset) that poisons the GCD — the most frequent gap value (the mode) is used instead. A single atypical gap cannot bias the mode, so images like marx.png (19 px blocks, 5 px partial leading block) are correctly recovered.
Sub-harmonic guard: after stages 1–2, if the robust autocorrelation of the threshold-filtered boundary signal strongly supports a period that is a strict multiple of the current candidate AND the robust signal does not already support the current candidate, the larger period wins. The double condition separates two cases: (a) sub-harmonic lock — the exact GCD is a divisor of the true period and robust support at the GCD is near zero; (b) clean mosaics — the exact GCD is correct and robust support at that period is already high, so no upgrade is needed despite any coincidental autocorrelation peaks from text-character spacing.
PhaseX is the most common residue of boundary column positions modulo Size; PhaseY likewise for rows. Confidence is the fraction of boundary positions consistent with that modal residue, averaged over the X and Y axes.
type Config ¶
type Config struct {
// Renderer is the component that rasterises candidate strings to RGBA.
// Defaults to the XImage renderer (wired by the defaults package).
Renderer Renderer
// Pixelator is the component that applies block-average pixelation.
// Defaults to BlockAverage (wired by the defaults package).
Pixelator Pixelator
// Metric is the component that measures pixel-level image distance.
// Defaults to Pixelmatch (wired by the defaults package).
Metric Metric
// Strategy is the component that drives the search algorithm.
// Defaults to GuidedDFS (wired by the defaults package).
Strategy Strategy
// LanguageModel optionally scores a candidate string's linguistic
// plausibility (higher = more plausible). When set, the final ranking breaks
// ties between candidates of equal image distance toward plausible text — the
// image cannot separate visually near-identical candidates (especially behind
// heavy blur), but a language prior can. nil disables it (the default).
LanguageModel func(string) float64
// ThresholdFor returns the acceptance threshold for a given candidate
// character. It defaults to a closure that returns SpaceThreshold for ' '
// and Threshold for all other runes. Override to apply per-class thresholds
// without modifying search logic.
ThresholdFor func(rune) float64
// Charset is the ordered set of candidate characters tried at each search
// depth. Defaults to DefaultCharset (a–z plus space).
Charset string
// CharsetTopK, when > 0 and LanguageModel is set, prunes the per-position
// charset to the K most-likely next characters (by the language prior) before
// evaluating any — turning a wide charset (e.g. full ASCII) into K renders per
// position. It trades a little recall (the true char must be in the top K) for
// speed; 0 (the default) evaluates the whole charset and never loses recall.
CharsetTopK int
// Style controls the font size, weight, and padding used when rendering
// candidates. Zero fields use the design defaults (32 pt, 8 px padding).
Style Style
// MaxLength is the maximum number of characters the search will attempt
// before backtracking. Defaults to DefaultMaxLength.
MaxLength int
// BlockSize is the side length in pixels of each pixelation block. It must
// match the block size used to produce the redacted image. When left
// non-positive, New auto-detects it from the image via InferBlockSize,
// falling back to DefaultBlockSize if the grid cannot be determined.
BlockSize int
// Threshold is the per-block score below which a non-space candidate is
// accepted and the search descends deeper. Lower values are stricter.
// Defaults to DefaultThreshold.
Threshold float64
// SpaceThreshold is the acceptance threshold applied specifically to the
// space character, which is harder to distinguish visually. Defaults to
// DefaultSpaceThreshold.
SpaceThreshold float64
// TopN is the maximum number of ranked candidates retained per grid offset
// in Result.TopN. Candidates are sorted ascending by score (lowest first);
// ties are broken by Guess string so results are deterministic. Zero or
// negative values are replaced by DefaultTopN in applyDefaults.
TopN int
// BeamWidth is the maximum number of candidates retained per depth level
// when using BeamStrategy. Values <= 0 are replaced by DefaultBeamWidth.
// Only BeamStrategy reads this field; other strategies ignore it.
BeamWidth int
// CacheSize is the maximum number of stageImage results held by
// CachingScorer. Zero disables prefix-render memoization; positive values
// enable an LRU cache of that capacity shared across all Eval calls for a
// single Search invocation. Defaults to DefaultCacheSize.
CacheSize int
// Workers is the maximum number of grid offsets probed and searched
// concurrently. Values <= 0 default to runtime.GOMAXPROCS. Set to 1 to force
// fully sequential execution. Results are merged deterministically regardless
// of Workers, so this affects throughput only, never the output.
Workers int
// FontPrior, when true, signals callers (CLI, MCP) to route a multi-font
// recovery through the blind font prior in the fontprior package, which
// reorders the sweep so the likeliest font is tried first. It is inert in the
// core search (Recover/RecoverMultiFont ignore it); fontprior.RecoverWithPrior
// reorders unconditionally regardless of this flag. Default false.
FontPrior bool
// FontPriorTopK, when > 0, prunes the prior-ordered multi-font sweep to the K
// best-ranked fonts (see fontprior.RecoverWithPrior). 0 (default) or a value
// >= the font count means reorder-only (no truncation). Pruning can change the
// result, so it is opt-in.
FontPriorTopK int
// RerankWeight, when > 0, enables the post-search re-rank stage in the rerank
// package: candidate ordering blends physical Verify distance with a language
// score (blended = distance − RerankWeight·(lmScore − bestLM)). 0 (default)
// means physical order only. It is inert in the core search (Recover/Verify/
// RankFinal ignore it); only rerank.Rerank reads it. A conservative starting
// value is ~0.05–0.1; too high lets the language model override correct physics.
RerankWeight float64
// contains filtered or unexported fields
}
Config holds all tunable parameters for an Engine. Every field is optional: zero values are replaced by the package defaults (see the Default* constants) when New is called. Component fields (Renderer, Pixelator, Metric, Strategy) are filled by importing the defaults package for its side-effect, or can be supplied directly for custom implementations.
func (Config) VerifyThreshold ¶ added in v0.21.0
VerifyThreshold returns the effective Verify Match threshold for this config: the value set by WithVerifyThreshold when positive, else VerifyMatchThreshold.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine orchestrates the full unpixel pipeline: grid-origin discovery, candidate rendering, re-pixelation, distance measurement, and guided search. Create one with New and call Run to start the search.
func New ¶
New creates an Engine for the given pixelated image. Scalar zero values in cfg are replaced by package defaults; nil component fields are left for Run to fill via DefaultComponents (or must be set explicitly). New returns ErrNilImage if redacted is nil.
func (*Engine) Config ¶ added in v0.2.0
Config returns the engine's resolved configuration, with scalar defaults applied and BlockSize auto-inferred. Component fields (Renderer, Pixelator, Metric, Strategy) are non-nil only after Run has wired them. It is intended for introspection — for example, reading the inferred BlockSize.
func (*Engine) DeskewedImage ¶ added in v0.6.0
DeskewedImage returns the internal RGBA image used by the Engine — after any dark-background inversion and deskew rotation performed by New. When no deskew was applied it is the same pixel data that was passed to New (after optional inversion); when a deskew was applied it is the rotated version. The returned pointer is the live internal buffer; callers must not modify it.
func (*Engine) Run ¶
Run starts the search and returns a progress channel and a results channel. The progress channel carries Progress events and is closed after EventDone is delivered. The results channel receives one Result per surviving grid offset and is closed once all offsets have been searched. Cancelling ctx causes both channels to be closed promptly after the in-flight search step completes.
If any component field in cfg is nil, Run invokes DefaultComponents to fill it before starting. If DefaultComponents is also nil, Run panics with a descriptive message directing the caller to import the defaults package.
type Eval ¶
type Eval struct {
// GuessImage is a cropped, pixelated rendering of Guess, populated only
// when the caller opts in via the Strategy implementation.
GuessImage *image.RGBA
// Guess is the candidate string evaluated at this node.
Guess string
// Score is the marginal region diff score for the most recently added
// character (lower is better; compared against the threshold).
Score float64
// TooBig is true when the rendered candidate is wider than the redacted
// image; such candidates are pruned regardless of score.
TooBig bool
}
Eval holds the result of evaluating a single candidate string at one search node.
type EventKind ¶
type EventKind int
EventKind identifies the type of a Progress event delivered on the channel returned by Engine.Run.
const ( // EventCandidate is emitted for every candidate string evaluated during // the search. It is high-frequency; the channel is non-blocking and events // are dropped when the buffer is full. EventCandidate EventKind = iota // EventOffsetProbed is emitted after each grid-origin probe during the // offset-discovery phase. It is high-frequency with the same drop semantics // as EventCandidate. EventOffsetProbed // EventNewBest is emitted whenever the search finds a new overall best // guess. Delivery is guaranteed: the sender blocks (with context) until the // consumer reads the event. EventNewBest // EventDone is the terminal event, delivered exactly once after all offsets // have been searched or the context is cancelled. Delivery is guaranteed. EventDone )
type FontResult ¶ added in v0.3.0
type FontResult struct {
// Result is the recovery produced with this renderer.
Result Result
// Index is the position of the renderer in the slice passed to
// RecoverMultiFont, identifying which font produced this Result.
Index int
}
FontResult pairs one candidate renderer with the Result it produced, as returned by RecoverMultiFont.
func RecoverMultiFont ¶ added in v0.3.0
func RecoverMultiFont(ctx context.Context, redacted image.Image, renderers []Renderer, opts ...Option) ([]FontResult, error)
RecoverMultiFont runs Recover once per renderer and returns the results ranked best-fit first, so the caller can recover a redaction without knowing its exact typeface — supply several candidate fonts and let the tool pick.
Ranking is by Result.BestTotal, the whole-image distance of the best guess: unlike BestScore (a per-character marginal score that ties at ~0 across fonts), BestTotal is comparable between separate runs, so the lowest-BestTotal font is the one that reconstructs the redaction most faithfully. ret[0] is the best fit. A renderer with an empty recovery is ranked last; a renderer whose run errors is omitted. RecoverMultiFont returns an error only when redacted is nil, renderers is empty, or every renderer failed.
The runs execute in parallel within a core budget — the resolved Config.Workers (set via WithWorkers or WithConfig), or runtime.GOMAXPROCS when unset: min(len(renderers), budget) run concurrently, each search using an equal share of workers, so the two layers never oversubscribe the CPU. The per-run renderer and worker count are set internally, overriding any WithRenderer/WithWorkers already in opts.
Build the renderers with github.com/oioio-space/unpixel/defaults.RendererFromFonts:
var rs []unpixel.Renderer
for _, data := range fontData {
r, err := defaults.RendererFromFonts(data, nil)
if err != nil { return err }
rs = append(rs, r)
}
ranked, err := unpixel.RecoverMultiFont(ctx, img, rs, unpixel.WithBlockSize(5))
best := ranked[0]
type ImageVerdict ¶ added in v0.18.0
type ImageVerdict struct {
// Distance is the whole-image distance in [0,1] between the redaction and the
// re-pixelated restored image at its best grid phase (lower = more consistent).
Distance float64
// Match reports whether Distance is below VerifyMatchThreshold.
Match bool
}
ImageVerdict is the result of physically verifying a restored image against a redaction by re-applying the forward operator and comparing.
func VerifyImage ¶ added in v0.18.0
func VerifyImage(ctx context.Context, redacted, restored image.Image, opts ...Option) (ImageVerdict, error)
VerifyImage physically verifies a restored (clean) image against a redaction: it re-applies the engine's forward operator to restored (re-pixelate at the mosaic block, or blur when a blur Pixelator is set via WithPixelator) and compares the result to redacted with the faithful metric, at the best grid phase. It is the image-input analogue of Verify: VerifyImage(redacted, render(text)) is the physical core of Verify(redacted, []string{text}).
Use it as an anti-hallucination gate for an external restorer (e.g. a diffusion sidecar): a faithful restoration re-pixelates back to the observed redaction (low Distance, Match=true); a hallucination does not — except where the mosaic is genuinely ambiguous (many restorations map to the same mosaic), which no physical check can disambiguate.
VerifyImage returns ErrNilImage when either image is nil and ErrNoComponents when the defaults package is not imported. opts mirror Verify's (WithBlockSize/WithCharset/WithPixelator/WithAuto…); for blurred redactions pass an explicit blur operator via WithPixelator, like Verify.
type Metric ¶
Metric measures the visual distance between two same-sized RGBA images. Compare returns a value in [0, 1] where 0 means pixel-perfect identical.
type Offset ¶
type Offset struct {
// X is the horizontal grid origin in pixels.
X int
// Y is the vertical grid origin in pixels.
Y int
// Score is the image-distance score for this origin (lower is better).
Score float64
}
Offset represents one candidate grid origin for the pixelation block alignment. The search probes multiple (X, Y) origins and ranks them by Score before committing to the full character-level search.
type Option ¶ added in v0.3.0
type Option func(*Config)
Option configures a Config for the high-level Recover helpers. Options are applied in order, so a later option overrides an earlier one; WithConfig (which replaces the whole Config) is therefore best passed first.
func WithAuto ¶ added in v0.15.0
func WithAuto() Option
WithAuto enables the full zero-config real-world recovery path in one call: it combines WithAutoCrop, WithAutoColorspace, WithAutoBlur, and WithAutoCalibrate. Use it as a convenience when the target image is a screenshot of unknown provenance — UnPixel will detect and crop the mosaic band, fingerprint the forward operator (mosaic colorspace and/or blur), and seed typographic calibration automatically. Default off.
func WithAutoBlur ¶ added in v0.18.0
func WithAutoBlur() Option
WithAutoBlur enables automatic mosaic-vs-blur detection via forensics fingerprinting. When set, New fingerprints the target image and, when confident (≥ 0.5), installs the matching blur or block pixelator. Below the confidence threshold the default BlockAverage is left untouched — byte-identical to the pre-fingerprint path. Default off.
func WithAutoCalibrate ¶ added in v0.15.0
func WithAutoCalibrate() Option
WithAutoCalibrate enables automatic typographic calibration. When set, New calls InferGridPhase and InferXStretch on the mosaic to seed the search:
- Grid phase: the inferred (PhaseX, PhaseY) is used as a diagnostic hint (offset discovery already covers all blockSize² origins, so phase never restricts the search).
- X-stretch: when a reference render width is derivable from the inferred block size and Style.FontSize, the stretch factor is used to seed Style.LetterSpacing so the renderer's advance more closely matches the original. The seed is overridden by an explicit WithStyle call.
Default off — without this option behaviour is byte-identical to before.
func WithAutoColorspace ¶ added in v0.15.0
func WithAutoColorspace() Option
WithAutoColorspace enables automatic colorspace detection for the mosaic pixelator. When set, New runs forensics fingerprinting on the (possibly cropped) target image after auto-detection of the block size, and selects the pixelator accordingly:
- confidence ≥ 0.5 and linear → LinearBlockAverage (GEGL/GIMP, CSS, etc.)
- confidence ≥ 0.5 and sRGB → BlockAverage (standard sRGB path, explicitly installed; output is pixel-identical to the pre-fingerprint default — panel 17/17 confirms no regression)
- confidence < 0.5 → Pixelator left nil; DefaultComponents wires the standard BlockAverage (byte-identical safe fallback)
Default off — without this option behaviour is byte-identical to before. The option has no effect when a Pixelator is already set explicitly via WithPixelator or [defaults.Wire] before Run is called.
func WithAutoCrop ¶ added in v0.15.0
func WithAutoCrop() Option
WithAutoCrop enables automatic mosaic-band detection and cropping. When set, New locates the block-pixelated region inside the image using internal/locate.LocateMosaicBand and crops to it before search. This is most useful for screenshots where the redacted block is surrounded by sharp text: without cropping the surrounding pixels confuse block-size detection and inflate the search region. Default off — without this option behaviour is byte-identical to before.
func WithBeamWidth ¶ added in v0.8.0
WithBeamWidth sets Config.BeamWidth (candidates retained per depth level by BeamStrategy). Values ≤ 0 defer to DefaultBeamWidth. Only BeamStrategy reads this field; other strategies ignore it.
func WithBlockSize ¶ added in v0.3.0
WithBlockSize sets Config.BlockSize. A non-positive value lets New auto-detect the block size from the image (see InferBlockSize).
func WithCharset ¶ added in v0.3.0
WithCharset sets Config.Charset (the ordered candidate alphabet).
func WithCharsetTopK ¶ added in v0.5.0
WithCharsetTopK sets Config.CharsetTopK: with a LanguageModel set, evaluate only the k most-likely next characters per position (k<=0 disables pruning).
func WithConfig ¶ added in v0.3.0
WithConfig uses cfg as the starting point before any other options are applied. Pass it first to layer further options on top of a full Config.
func WithCrop ¶ added in v0.18.0
WithCrop crops the input to an explicit redaction band (in image coordinates) before verification, padding it with a white margin so the verifier's alignment sweep has room to slide. Unlike WithAutoCrop it takes the rectangle directly — pass the band from LocateRedaction or an external analysis step (its convention matches LocateRedaction's returned rectangle).
This is the lever that makes whole-string Verify discriminate the truth on a real screenshot: without cropping, the surrounding margins dilute the whole-image distance and every candidate scores alike. Recover also honours it — it crops to the band (taking precedence over WithAutoCrop) before the search, so a redaction embedded in a larger image can be decoded without detection. The zero Rectangle (default) means no crop — behaviour is then byte-identical to before.
func WithExpectedFormat ¶ added in v0.18.0
WithExpectedFormat constrains the guided search to candidates feasible for a structured-secret format (credit card, IBAN, date, phone, numeric ID): each position is limited to the runes the format allows, the Luhn check digit is fixed at the last position of a fixed-length card, and complete candidates that fail the format's checksum/range rules are dropped before ranking.
It is strictly opt-in: WithExpectedFormat(secrets.FormatNone) or omitting the option leaves decoding byte-identical to the unconstrained search. Declaring the wrong format will wrongly reject the true answer, so use it only when the redaction's format is known. Ignored when WithPrefix is also set (prefix wins).
func WithFontPrior ¶ added in v0.18.0
func WithFontPrior() Option
WithFontPrior enables the blind font prior for multi-font recovery: callers such as the CLI and MCP server route the sweep through github.com/oioio-space/unpixel/fontprior.RecoverWithPrior, which ranks the bundled fonts by how well each explains the redaction and tries the likeliest first. Reordering alone does not change the result (the sweep still ranks by whole-image distance); it only speeds up the common case. Combine with WithFontPriorTopK to also prune the sweep.
func WithFontPriorTopK ¶ added in v0.18.0
WithFontPriorTopK prunes the prior-ordered multi-font sweep to the k best-ranked fonts. k <= 0 or k >= the font count means reorder-only. Pruning is faster but can drop the true font when k is too small, so it is opt-in; k >= 3 is recommended. Implies the font prior.
func WithL0Deblur ¶ added in v0.12.0
WithL0Deblur enables L0-regularised text deblurring (Pan et al., CVPR 2014) as an opt-in preprocessing step before blur recovery. It is only effective in RecoverBlurred; Recover and the mosaic path are unchanged.
When called with no arguments the defaults from the paper are used:
- Lambda: 2×10⁻³ (gradient L0 sparsity weight)
- Mu: 5×10⁻⁴ (two-tone intensity prior weight)
- Iterations: 20 (outer HQS alternating-minimisation steps)
Pass functional options to override individual parameters, e.g.:
unpixel.WithL0Deblur(
func(o *deblur.L0Options) { o.Iterations = 30 },
)
The sigma used for the PSF is the σ estimated by InferBlurSigma at the time RecoverBlurred is called (before the σ-search), so it does not need to be set by the caller. Result.L0Deblurred is set to true when active.
func WithLanguageModel ¶ added in v0.4.0
WithLanguageModel sets Config.LanguageModel, a plausibility scorer used to break ties between candidates of equal image distance toward plausible text.
func WithMaxLength ¶ added in v0.3.0
WithMaxLength sets Config.MaxLength (the maximum candidate length).
func WithMetric ¶ added in v0.3.0
WithMetric sets Config.Metric (the image-distance metric).
func WithNormalize ¶ added in v0.9.0
WithNormalize enables input normalisation before blur recovery. It is opt-in and only affects RecoverBlurred; Recover and the mosaic path are unchanged.
When called with no arguments, sensible defaults are used:
- BgDivide: divide out a multiplicative illumination estimate (vignette).
- InvertAuto: invert when the image is predominantly dark (dark-theme support).
- Stretch: false — enable a 1st/99th-percentile contrast stretch with o.Stretch = true.
- Deblock: 0 (off) — set to -1 (auto) or a positive radius to median-filter JPEG blocking.
- Binarize: false.
Pass deblur.Options values to customise individual steps, e.g.:
unpixel.WithNormalize(func(o *deblur.Options) { o.Deblock = 2 })
Result.Normalized is set to true when normalisation was applied.
func WithPixelator ¶ added in v0.4.0
WithPixelator sets Config.Pixelator (the redaction operator the search reproduces). Use it with defaults.GaussianBlur(sigma) and WithBlockSize(1) to recover blurred text instead of mosaic pixelation.
func WithPrefix ¶ added in v0.15.0
WithPrefix locks the first len(prefix) characters of every search candidate to the corresponding characters of prefix, constraining the search without altering scoring or thresholds. Characters beyond the prefix are still explored with the full Charset. An empty prefix is a no-op and the search is byte-identical to unconstrained.
Use it when part of the redacted text is already known — for example, a URL prefix "https://" or a log-line format "ERROR: ". The constraint is applied via internal/search.GuidedDFSConstrained and is compatible with all strategies that use GuidedDFS; it has no effect on BeamStrategy or MonospaceStrategy (which use their own DFS variants).
Default: empty (no constraint).
func WithPriors ¶ added in v0.5.0
WithPriors composes one or more plausibility priors into Config.LanguageModel. Each prior is a function from candidate string to a non-negative log-space score (higher = more plausible). Nil priors are silently skipped.
The resulting LanguageModel is the sum of all provided priors AND any LanguageModel already set on the Config, so WithPriors composes correctly regardless of option order:
unpixel.Recover(ctx, img,
unpixel.WithLanguageModel(myBigram), // set first
unpixel.WithPriors(secrets.Prior), // adds on top
)
The combined prior is used in two places:
- RankFinal breaks ties between candidates whose whole-image scores are within lmTieBand (0.01) of each other, preferring higher-prior strings.
- WithCharsetTopK prunes the per-position charset to the K most-likely next characters before evaluating any candidates, trading a little recall for speed on wide charsets.
func WithRemosaic ¶ added in v0.10.0
func WithRemosaic() Option
WithRemosaic enables the Hill–Zhou–Saul–Shacham PETS-2016 §4 remosaic path inside RecoverBlurred. When active the forward operator becomes:
render(candidate) → GaussianBlur(σ) → BlockAverage(b)
and the target image is pre-mosaiced by BlockAverage(b) once before the search. The mosaic stage collapses small pixel-level differences caused by σ-mismatch or JPEG compression noise, making the comparison more robust than plain GaussianBlur alone.
The grid size b is chosen automatically as max(2, round(σ)); use WithRemosaicGrid to override it. The linear-light block average is used when WithRemosaicLinear is passed instead of WithRemosaic; by default sRGB means are used (matching the plain mosaic path).
WithRemosaic has no effect on Recover or the mosaic path.
func WithRemosaicGrid ¶ added in v0.10.0
WithRemosaicGrid enables the remosaic path (like WithRemosaic) and additionally pins the block grid size to b pixels. b ≤ 0 selects auto (b = max(2, round(σ)), same as WithRemosaic).
func WithRemosaicLinear ¶ added in v0.10.0
func WithRemosaicLinear() Option
WithRemosaicLinear enables the remosaic path and uses linear-light block averaging instead of the default sRGB means. Use it when the target was redacted by a GEGL/GIMP-based tool that computes its block average in linear light.
func WithRenderer ¶ added in v0.3.0
WithRenderer sets Config.Renderer (the text rasteriser). Use it with a custom font, e.g. defaults.RendererFromFonts, to match the typeface of the redacted image.
func WithRerankWeight ¶ added in v0.18.0
WithRerankWeight sets Config.RerankWeight, the weight the rerank package uses to blend a candidate's language score into its physical distance when re-ordering the top-K. 0 (default) leaves candidates in physical-distance order. Higher values let a strong language preference override a small physical distance gap; keep it small (~0.05–0.1). See github.com/oioio-space/unpixel/rerank.Rerank.
func WithStrategy ¶ added in v0.3.0
WithStrategy sets Config.Strategy (the search algorithm).
func WithStyle ¶ added in v0.3.0
WithStyle sets Config.Style (font size, weight, and padding). It must match the style of the redacted text for recovery to succeed.
func WithThreshold ¶ added in v0.3.0
WithThreshold sets Config.Threshold (the per-block acceptance gate).
func WithVerifyThreshold ¶ added in v0.21.0
WithVerifyThreshold sets the maximum whole-image distance at which a Verify / VerifyImage candidate counts as a Match, overriding the default VerifyMatchThreshold for this call. Pass a smaller value to demand a closer physical fit (fewer false Matches on ambiguous mosaics), or a larger one to be more permissive. A value ≤ 0 keeps the package default. It affects only the Match flag; the raw Distance is always reported so callers can threshold themselves too.
func WithWorkers ¶ added in v0.3.0
WithWorkers sets Config.Workers (max grid offsets searched concurrently; non-positive means runtime.GOMAXPROCS).
type Pixelator ¶
Pixelator replaces every blockSize×blockSize region of an image with the mean RGBA colour of that region. The originX and originY parameters align the grid so that it matches the original pixelation applied to the source.
type Progress ¶
type Progress struct {
// Err carries any terminal error that caused the search to abort.
Err error
// PreviewImage is an optional deep copy of the pixelated guess image.
// It is non-nil only when the Strategy implementation populates it.
PreviewImage *image.RGBA
// BestGuess is the candidate string with the lowest score found so far
// across all offsets.
BestGuess string
// Guess is the candidate string that triggered this specific event.
Guess string
// Offset is the grid origin currently being searched.
Offset Offset
// Kind identifies which event this Progress value represents.
Kind EventKind
// BestScore is the total image-distance score of BestGuess (lower is better).
BestScore float64
// Score is the image-distance score of Guess.
Score float64
// Depth is the current search depth, equal to the character length of Guess.
Depth int
// Evaluated is the cumulative number of candidates evaluated since Run started.
Evaluated int
// OffsetsDone is the number of grid offsets fully searched so far.
OffsetsDone int
// OffsetsTotal is the total number of surviving grid offsets to be searched.
OffsetsTotal int
// Elapsed is the wall-clock duration since Engine.Run was called.
Elapsed time.Duration
// Done is true only on the EventDone event.
Done bool
}
Progress carries a snapshot of search state, streamed on the channel returned by Engine.Run. Consumers should switch on Kind to decide which fields are meaningful for a given event.
type Renderer ¶
type Renderer interface {
Render(text string, style Style) (img *image.RGBA, sentinelX int, err error)
}
Renderer renders candidate text to an RGBA image, placing a blue sentinel block immediately to the right of the text. It returns the image and the x-coordinate of that sentinel, which marks the text's right edge in pixels.
type Result ¶
type Result struct {
// Err is non-nil if the search for this offset aborted due to an error.
Err error
// BestGuess is the candidate string with the lowest overall score found
// during the search rooted at this offset.
BestGuess string
// Candidates holds every string that passed the threshold gate during the
// search, in discovery order.
Candidates []Eval
// TopN holds the best candidates sorted ascending by score (lowest score
// first), with ties broken by Guess string for determinism. Its length is
// at most Config.TopN. TopN[0] is the same candidate as BestGuess when the
// search produces any result. TopN is nil when no candidates were found.
TopN []Eval
// Offset is the grid origin that was searched to produce this result.
Offset Offset
// BestScore is the marginal-region diff score of BestGuess (lower is better).
BestScore float64
// BestTotal is the whole-image distance of BestGuess against the redaction
// (0 = pixel-perfect, 1 = worst). Unlike BestScore — which is a per-character
// marginal score that a correct prefix or a coincidental match can drive to
// ~0 — BestTotal measures how well the full guess explains the entire
// redaction, so it is comparable across separate runs. That makes it the
// right signal for choosing between candidate fonts or styles: the run with
// the lowest BestTotal recovered the redaction most faithfully.
BestTotal float64
// Confidence is 1 − TopN[0].Score, giving a value in [0, 1] where 1
// represents a pixel-perfect match. It is 0 when TopN is empty.
Confidence float64
// Ambiguity is TopN[1].Score − TopN[0].Score: the score gap between the
// best and second-best candidates. A larger gap means the best guess is
// more clearly distinguished from alternatives. It is 0 when len(TopN) < 2.
Ambiguity float64
// BlurSigma is the Gaussian-blur standard deviation (in pixels) used to
// produce this result. It is set by RecoverBlurred and zero for all other
// recovery paths (block-mosaic, manual Pixelator, etc.).
BlurSigma float64
// BelowThreshold is true when BestGuess was promoted from the best-seen
// sub-threshold candidate because no candidate actually passed the
// acceptance gate. When false (the normal case), BestGuess/TopN/Confidence
// are computed entirely from candidates that passed the gate and are
// byte-identical to previous behaviour.
//
// Per-offset edge case: when the global winner is above-threshold
// (BelowThreshold=false), a non-winning offset's per-offset TopN may still
// contain a sub-threshold best-seen candidate. Callers iterating all
// per-offset results should not treat every per-offset TopN entry as
// having passed the acceptance gate; check the per-offset BelowThreshold
// field individually.
BelowThreshold bool
// Normalized is true when RecoverBlurred applied input normalisation
// (via WithNormalize) before the σ-search. It is always false for other
// recovery paths (Recover, mosaic, etc.) and when WithNormalize was not
// passed. Use it to confirm the normalisation step was active.
Normalized bool
// L0Deblurred is true when RecoverBlurred applied L0-regularised text
// deblurring (via WithL0Deblur) as a preprocessing step before the σ-search.
// Always false for the mosaic path and when WithL0Deblur was not passed.
L0Deblurred bool
}
Result is the final output produced by Engine.Run for one surviving grid offset. One Result is sent per offset on the results channel returned by Run.
func Recover ¶ added in v0.3.0
Recover is the one-call entry point: it runs the full search on the redacted image and returns the single best Result across all grid offsets. It builds a Config from opts, auto-detects what it can (e.g. the block size), wires the default components (when the defaults package is imported), runs the search, and drains the channels for the caller.
The common usage is a side-effect import of the defaults package:
import _ "github.com/oioio-space/unpixel/defaults" res, err := unpixel.Recover(ctx, img) fmt.Println(res.BestGuess)
Recover returns ErrNilImage for a nil image and ErrNoComponents when a component is missing and no defaults are wired. A search that finds nothing returns the zero Result and a nil error.
func RecoverBlurred ¶ added in v0.8.0
RecoverBlurred recovers text from a Gaussian-blurred redaction without being told the blur standard deviation σ. It is the zero-config counterpart of Recover with a manual WithPixelator(GaussianBlur(σ)) + WithBlockSize(1).
Default search strategy: beam search ¶
RecoverBlurred defaults to beam search (BeamStrategy) rather than the guided DFS used by Recover. Behind blur the per-character image signal is weak: the correct character's score often beats the wrong one by only a small margin, and guided DFS expands every passing branch depth-first — producing O(|charset|^length) evaluations for longer words, which makes it impractical for ≥5-character targets. Beam search bounds work to O(length × BeamWidth) evaluations, making even 7-character recoveries finish in milliseconds.
The effective BeamWidth for blur recovery is 32 (set by defaults.DefaultBlurStrategy); DefaultBeamWidth = 16 is only the generic BeamStrategy fallback. Either value is wider than the typical blur charset, giving full per-level coverage for small alphabets. Combine with WithLanguageModel (e.g. WithLanguageModel(lang.PriorFor(lang.English))) for disambiguation when the image signal alone does not separate candidates.
Callers that need full guided-DFS recall can override with WithStrategy(defaults.GuidedStrategy()), which also disables the beam default.
Algorithm (adaptive σ-search) ¶
Gaussian blur is a known, deterministic forward operator B_σ. The generate-and-test attack (render → blur → compare) inverts it: render a candidate, blur with the same σ, measure image distance — the true text will have the lowest distance.
RecoverBlurred uses an adaptive strategy that minimises the number of full Recover calls to the common case of ONE:
- Estimate σ₀ = InferBlurSigma(img). The estimator is accurate to within ~15% on typical text images (validated over the fixture set).
- Run ONE full Recover at σ₀ with exact GaussianBlur.
- If Result.BestGuess is non-empty and Result.BestTotal < blurAcceptThreshold the early-accept gate fires: σ₀ is close enough and the candidate is convincing — return immediately (the common case, ≈1× single Recover).
- Otherwise, expand to a bounded fallback sweep: build a coarse grid of ±2 steps around σ₀ (4 extra σ candidates at multipliers {0.7, 0.85, 1.18, 1.4}×σ₀, or a fixed wide grid when σ₀=0), run them in parallel, then fine-refine (±0.25, 5 steps, sequential) around the best coarse winner. This fallback adds ≤9 extra Recover calls — preserving robustness for the minority of images where σ₀ is off by more than ~15%.
Accept threshold (blurAcceptThreshold) ¶
BestTotal is the whole-image pixel distance (in [0,1]) of the best guess against the redaction. For a correct recovery at near-exact σ, BestTotal is typically 0.01–0.04 (pixel-perfect near-match). An incorrect recovery or a σ mismatch produces BestTotal ≫ 0.08. The threshold 0.07 sits comfortably above the correct-recovery floor and below the wrong-σ ceiling, giving a robust early-exit signal without a recall risk.
Concurrency model ¶
The initial single-σ search uses full Workers parallelism (same as a plain Recover call). The fallback sweep uses the same bounded-pool strategy as the old implementation: each σ gets 1 inner worker; up to NumCPU run at once.
All caller-supplied opts (WithCharset, WithMaxLength, WithStyle, WithLanguageModel, WithWorkers, WithStrategy, …) are forwarded to every inner Recover call; WithBlockSize and WithPixelator are set internally and override any value the caller passes.
Ctx cancellation is respected; a cancelled sweep returns the best result found so far.
func RecoverBlurredFile ¶ added in v0.8.2
RecoverBlurredFile opens the image at path and calls RecoverBlurredReader. Pass "-" handling at the call site if stdin support is needed; RecoverBlurredFile always opens a file.
func RecoverBlurredReader ¶ added in v0.8.2
RecoverBlurredReader decodes an image (PNG is registered; register other formats by importing their image/<fmt> package) from r and calls RecoverBlurred.
func RecoverBytes ¶ added in v0.21.0
RecoverBytes decodes an image from in-memory data and calls Recover. It is the []byte counterpart of RecoverReader/RecoverFile — convenient when the image already lives in memory (an HTTP body, an embedded asset) with no file or io.Reader to hand.
Example ¶
ExampleRecoverBytes recovers redacted text from an image already in memory (an HTTP body, an embedded asset), constraining the search to digits for a numeric secret such as a PIN — the narrowest charset gives the fastest, most reliable search.
package main
import (
"context"
"fmt"
"github.com/oioio-space/unpixel"
_ "github.com/oioio-space/unpixel/defaults"
)
func main() {
var pngData []byte // the mosaic image bytes
res, err := unpixel.RecoverBytes(context.Background(), pngData,
unpixel.WithCharset(unpixel.CharsetDigits),
unpixel.WithBlockSize(8),
)
if err != nil {
fmt.Println("recover:", err)
return
}
fmt.Println(res.BestGuess)
}
Output:
func RecoverFile ¶ added in v0.3.0
RecoverFile opens the image at path and calls RecoverReader. Pass "-" handling at the call site if stdin support is needed; RecoverFile always opens a file.
func RecoverReader ¶ added in v0.3.0
RecoverReader decodes an image (PNG is registered; register other formats by importing their image/<fmt> package) from r and calls Recover.
func (Result) Fidelity ¶ added in v0.5.0
Fidelity reports how well BestGuess reproduces the whole redaction, in [0, 1] (1 = pixel-perfect), as 1 − BestTotal. It is the honest confidence signal: unlike Confidence (derived from the marginal score, which a prefix or fluke drives to ~1), Fidelity reflects the whole-image match, so a low value means "this recovery is probably wrong / unrecoverable". It is 0 for an empty guess.
type SkewInfo ¶ added in v0.6.0
type SkewInfo struct {
// Detected is true when the image appeared to have a non-axis-aligned mosaic
// grid (InferBlockGrid confidence was low on the raw image).
Detected bool
// Applied is true when a deskew rotation was actually applied to the image
// inside New — meaning the block-homogeneity gain exceeded deskewHomogMinGain
// and the post-rotation score exceeded deskewHomogMinScore.
Applied bool
// AngleDeg is the rotation angle (in degrees, counter-clockwise) that best
// corrected the skew. It is 0 when no skew was detected or applied.
AngleDeg float64
// BaselineConfidence is the InferBlockGrid confidence of the raw (unrotated)
// image. Values below deskewGridMinConfidence trigger the search.
BaselineConfidence float64
// BestConfidence is the InferBlockGrid confidence after applying AngleDeg.
// It is populated only when Applied is true.
BestConfidence float64
}
SkewInfo carries the outcome of the automatic skew detection performed by New. It is available via Engine.SkewInfo for introspection and CLI warnings.
type Strategy ¶
type Strategy interface {
Search(ctx context.Context, redacted *image.RGBA, cfg Config, out chan<- Progress, results chan<- Result)
}
Strategy runs the full character-by-character search over the candidate space and streams progress and results on the provided channels. Implementations may use different algorithms (guided DFS, beam search, etc.). Search must close neither channel; Engine.Run owns their lifecycle.
type Style ¶
type Style struct {
// FontSize is the font size in points. Defaults to 32.
FontSize float64
// Bold selects the bold font variant when true.
Bold bool
// PaddingTop is the top padding applied before the text, in pixels. Defaults to 8.
PaddingTop int
// PaddingLeft is the left padding applied before the text, in pixels. Defaults to 8.
PaddingLeft int
// LetterSpacing is extra horizontal space, in pixels, inserted after each
// glyph — the equivalent of the CSS letter-spacing property. It may be
// negative to tighten text (e.g. -0.2 to match a Consolas redaction). The
// default 0 leaves glyph advances untouched and preserves kerning; a
// non-zero value renders glyph-by-glyph without kerning.
LetterSpacing float64
// XScale is a horizontal stretch factor applied to the rendered text raster
// after glyph drawing and before pixelation. A value of 1.06 stretches
// the text 6% wider, matching screenshots produced by anisotropic scaling
// (e.g. GIMP layer scale where x and y zoom differ). The zero value and
// exactly 1.0 both mean no stretch: the renderer takes the identical code
// path as without XScale, producing byte-identical output.
XScale float64
}
Style describes the text rendering parameters that must match the typography of the original, pre-pixelated screenshot.
type Verdict ¶ added in v0.18.0
type Verdict struct {
// Text is the candidate string that was scored.
Text string
// Distance is the faithful whole-image distance in [0,1] (≈0 means exact match).
Distance float64
// Match reports whether Distance is below VerifyMatchThreshold.
Match bool
}
Verdict is the result of verifying one candidate string against a pixelated image using the engine's faithful forward model.
func Verify ¶ added in v0.18.0
func Verify(ctx context.Context, img image.Image, candidates []string, opts ...Option) ([]Verdict, error)
Verify scores each candidate against img using the engine's faithful forward model (same render→operator→metric pipeline as Recover), evaluated at the candidate's best grid offset. opts mirror Recover's options (WithCharset/WithBlockSize/WithStyle/WithAuto…); auto-fingerprinting is applied by default when no Pixelator is set. Candidates beyond maxVerifyCandidates are ignored. Returns one Verdict per accepted candidate, in input order.
Verify returns ErrNilImage for a nil image and ErrNoComponents when a required component is missing and no defaults are wired.
Verify uses the mosaic forward model; it does NOT perform the blur sigma-sweep that RecoverBlurred does. For Gaussian-blurred redactions, pass an explicit blur operator via WithPixelator (e.g. defaults.GaussianBlur(sigma)) to get a single-sigma faithful score — otherwise distances may be high for every candidate and nothing will Match.
func VerifyBytes ¶ added in v0.21.0
func VerifyBytes(ctx context.Context, data []byte, candidates []string, opts ...Option) ([]Verdict, error)
VerifyBytes decodes an image from in-memory data and calls Verify — the []byte counterpart of Verify (HTTP bodies, embedded assets).
Example ¶
ExampleVerifyBytes confirms proposed candidate strings against a redaction using the faithful forward model — the propose-and-verify path. WithVerifyThreshold tunes how close a physical fit must be to count as a Match.
package main
import (
"context"
"fmt"
"github.com/oioio-space/unpixel"
_ "github.com/oioio-space/unpixel/defaults"
)
func main() {
var redaction []byte // the mosaic image bytes
verdicts, err := unpixel.VerifyBytes(context.Background(), redaction,
[]string{"hunter2", "swordfish"},
unpixel.WithVerifyThreshold(0.05),
)
if err != nil {
fmt.Println("verify:", err)
return
}
for _, v := range verdicts {
if v.Match {
fmt.Printf("%s confirmed (distance %.4f)\n", v.Text, v.Distance)
}
}
}
Output:
func VerifyFile ¶ added in v0.21.0
func VerifyFile(ctx context.Context, path string, candidates []string, opts ...Option) ([]Verdict, error)
VerifyFile opens the image at path and calls VerifyReader. Use "-"-to-stdin handling at the call site if needed; VerifyFile always opens a file.
func VerifyReader ¶ added in v0.21.0
func VerifyReader(ctx context.Context, r io.Reader, candidates []string, opts ...Option) ([]Verdict, error)
VerifyReader decodes an image from r (PNG is registered; import the format's image/<fmt> package for others) and calls Verify. It is the io.Reader counterpart of Verify, for callers holding a stream rather than a decoded image.Image.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package blind provides a zero-config API for blind recovery of mosaic-redacted text without knowing the font, block size, or grid offset in advance.
|
Package blind provides a zero-config API for blind recovery of mosaic-redacted text without knowing the font, block size, or grid offset in advance. |
|
cmd
|
|
|
unpixel
command
Command unpixel reconstructs text hidden behind pixelation.
|
Command unpixel reconstructs text hidden behind pixelation. |
|
unpixel-mcp
command
Command unpixel-mcp runs the UnPixel MCP server on the stdio transport.
|
Command unpixel-mcp runs the UnPixel MCP server on the stdio transport. |
|
Package defaults wires the standard internal components into an unpixel.Config.
|
Package defaults wires the standard internal components into an unpixel.Config. |
|
Package fontprior ranks the bundled fonts by how well each explains a mosaic redaction, blind — without any known plaintext — so the multi-font sweep can try the likeliest font first (reordering, result-preserving) or prune to the top-K (faster, opt-in).
|
Package fontprior ranks the bundled fonts by how well each explains a mosaic redaction, blind — without any known plaintext — so the multi-font sweep can try the likeliest font first (reordering, result-preserving) or prune to the top-K (faster, opt-in). |
|
Package fonts bundles a small set of redistributable typefaces so UnPixel can recover a redaction zero-config — without the caller supplying any font file — by sweeping these candidates and keeping the best fit (see github.com/oioio-space/unpixel.RecoverMultiFont).
|
Package fonts bundles a small set of redistributable typefaces so UnPixel can recover a redaction zero-config — without the caller supplying any font file — by sweeping these candidates and keeping the best fit (see github.com/oioio-space/unpixel.RecoverMultiFont). |
|
internal
|
|
|
blinddecode
Package blinddecode recovers individual words from a mosaic-pixelated redaction band by combining the forward image model (render → re-pixelate → image distance) with a language prior (dictionary membership + infini-gram).
|
Package blinddecode recovers individual words from a mosaic-pixelated redaction band by combining the forward image model (render → re-pixelate → image distance) with a language prior (dictionary membership + infini-gram). |
|
capacity
Package capacity measures the information-theoretic recoverability of a pixelated-text image for a given rendering geometry (font size, block size, grid phase).
|
Package capacity measures the information-theoretic recoverability of a pixelated-text image for a given rendering geometry (font size, block size, grid phase). |
|
deblur
Package deblur (l0text.go) implements non-blind L0-regularised text deblurring following Pan, Hu, Su, Yang — "Deblurring Text Images via L0-Regularized Intensity and Gradient Prior", CVPR 2014.
|
Package deblur (l0text.go) implements non-blind L0-regularised text deblurring following Pan, Hu, Su, Yang — "Deblurring Text Images via L0-Regularized Intensity and Gradient Prior", CVPR 2014. |
|
did
Package did implements Document Image Decoding (DID) for mosaic-pixelated text.
|
Package did implements Document Image Decoding (DID) for mosaic-pixelated text. |
|
fixture
Package fixture generates synthetic pixelated-text reference images for the recovery test matrix.
|
Package fixture generates synthetic pixelated-text reference images for the recovery test matrix. |
|
fixture/blurfixture
Package blurfixture generates and describes synthetic Gaussian-blurred text images used by the blur-recovery matrix test.
|
Package blurfixture generates and describes synthetic Gaussian-blurred text images used by the blur-recovery matrix test. |
|
fixture/gen
command
Command gen renders the fixture.Matrix reference images to an output directory, alongside a manifest.json that records each image's filename and its original generation parameters (the image ↔ parameters link).
|
Command gen renders the fixture.Matrix reference images to an output directory, alongside a manifest.json that records each image's filename and its original generation parameters (the image ↔ parameters link). |
|
fixture/gencontext
command
Command gencontext renders the context-corpus reference images to an output directory alongside a manifest.json.
|
Command gencontext renders the context-corpus reference images to an output directory alongside a manifest.json. |
|
fixture/gengeometry
command
Command gengeometry renders the geometry-calibration corpus to an output directory alongside a manifest.json.
|
Command gengeometry renders the geometry-calibration corpus to an output directory alongside a manifest.json. |
|
fixture/genlb
command
Command genlb renders the large-block fixture corpus to an output directory alongside a manifest.json.
|
Command genlb renders the large-block fixture corpus to an output directory alongside a manifest.json. |
|
fixture/genmultiframe
command
Command genmultiframe generates multi-frame test fixtures from a SHARP source: it renders text once, then pixelates that sharp image at N distinct grid phases, producing phase-diverse mosaics that genuinely reveal different sub-block information.
|
Command genmultiframe generates multi-frame test fixtures from a SHARP source: it renders text once, then pixelates that sharp image at N distinct grid phases, producing phase-diverse mosaics that genuinely reveal different sub-block information. |
|
fixture/genperspective
command
Command genperspective renders perspective-distorted redaction fixtures: each is a normal pixelated text redaction (via fixture.Redact) warped into a tilted quadrilateral on a mid-gray photo canvas (so the patch is distinguishable for rectify.DetectQuad), simulating a redaction photographed at an angle.
|
Command genperspective renders perspective-distorted redaction fixtures: each is a normal pixelated text redaction (via fixture.Redact) warped into a tilted quadrilateral on a mid-gray photo canvas (so the patch is distinguishable for rectify.DetectQuad), simulating a redaction photographed at an angle. |
|
fixture/gensick
command
Command gensick renders the paper-parity (Hill-2016) sick-corpus reference images to an output directory alongside a manifest.json that records each image's filename, ground-truth text, charset, font, block size, kind ("sick" or "digits"), and a short annotation note.
|
Command gensick renders the paper-parity (Hill-2016) sick-corpus reference images to an output directory alongside a manifest.json that records each image's filename, ground-truth text, charset, font, block size, kind ("sick" or "digits"), and a short annotation note. |
|
fontrank
Package fontrank ranks candidate fonts by how well their glyph exemplars visually match a mosaic-pixelated redaction image.
|
Package fontrank ranks candidate fonts by how well their glyph exemplars visually match a mosaic-pixelated redaction image. |
|
forensics
Package forensics identifies the forward (redaction) operator applied to a redacted image region: mosaic vs.
|
Package forensics identifies the forward (redaction) operator applied to a redacted image region: mosaic vs. |
|
imutil
Package imutil provides image manipulation helpers used by the unpixel pipeline.
|
Package imutil provides image manipulation helpers used by the unpixel pipeline. |
|
infoleak
Package infoleak quantifies how much exploitable information a block-average mosaic leaks under anti-aliased rendering and JPEG compression.
|
Package infoleak quantifies how much exploitable information a block-average mosaic leaks under anti-aliased rendering and JPEG compression. |
|
lang
Package lang provides a tiny, pure-Go character bigram language model used as a prior over candidate strings.
|
Package lang provides a tiny, pure-Go character bigram language model used as a prior over candidate strings. |
|
leak
Package leak provides a file-level pre-pass that recovers original content from metadata and format leaks — EXIF embedded thumbnails, PDF text under rectangles, Office (OOXML) body text, and visible-text-assisted partial redactions — before any pixel solving.
|
Package leak provides a file-level pre-pass that recovers original content from metadata and format leaks — EXIF embedded thumbnails, PDF text under rectangles, Office (OOXML) body text, and visible-text-assisted partial redactions — before any pixel solving. |
|
locate
Package locate provides mosaic-aware region detection for the unpixel pipeline.
|
Package locate provides mosaic-aware region detection for the unpixel pipeline. |
|
metric
Package metric provides image distance metrics for the unpixel pipeline.
|
Package metric provides image distance metrics for the unpixel pipeline. |
|
multiframe
Package multiframe implements multi-frame sub-pixel fusion for mosaic-pixelated images.
|
Package multiframe implements multi-frame sub-pixel fusion for mosaic-pixelated images. |
|
pixelate
Package pixelate (blur.go) adds a Gaussian-blur redaction operator alongside the block-average pixelator.
|
Package pixelate (blur.go) adds a Gaussian-blur redaction operator alongside the block-average pixelator. |
|
rectify
Package rectify provides the planar-homography primitives UnPixel uses to decode redactions photographed under perspective.
|
Package rectify provides the planar-homography primitives UnPixel uses to decode redactions photographed under perspective. |
|
refmatch
Package refmatch implements Depix-style reference-matching decoding for mosaic-pixelated text.
|
Package refmatch implements Depix-style reference-matching decoding for mosaic-pixelated text. |
|
render
Package render provides the XImage text renderer for the unpixel pipeline.
|
Package render provides the XImage text renderer for the unpixel pipeline. |
|
search
Package search (beam.go) adds BeamDFS, a beam-search variant of GuidedDFS that bounds the branching factor by retaining only the best cfg.BeamWidth candidates per depth level, and BeamStrategy, the unpixel.Strategy that drives it.
|
Package search (beam.go) adds BeamDFS, a beam-search variant of GuidedDFS that bounds the branching factor by retaining only the best cfg.BeamWidth candidates per depth level, and BeamStrategy, the unpixel.Strategy that drives it. |
|
secrets
Package secrets scores candidate strings for their resemblance to real secrets and structured tokens (UUIDs, hex tokens, Luhn-valid card numbers, base64 tokens, common passwords).
|
Package secrets scores candidate strings for their resemblance to real secrets and structured tokens (UUIDs, hex tokens, Luhn-valid card numbers, base64 tokens, common passwords). |
|
segment
Package segment partitions a mosaic/redaction image into text lines and words.
|
Package segment partitions a mosaic/redaction image into text lines and words. |
|
varfont
Package varfont provides a variable-font renderer and a coordinate-descent axis fitter for the unpixel pipeline.
|
Package varfont provides a variable-font renderer and a coordinate-descent axis fitter for the unpixel pipeline. |
|
varfont/embed
Package embed exposes the bundled variable fonts for use by the varfont calibrate path.
|
Package embed exposes the bundled variable fonts for use by the varfont calibrate path. |
|
windowhmm
Package windowhmm provides the block-grid types, window-vector extraction, and the trained-HMM primitives (KMeans, Model, Viterbi, Concatenate) used by the sliding-window decoders in mosaictext.
|
Package windowhmm provides the block-grid types, window-vector extraction, and the trained-HMM primitives (KMeans, Model, Viterbi, Concatenate) used by the sliding-window decoders in mosaictext. |
|
Package mcpserver wires UnPixel's decode and analysis capabilities as a Model Context Protocol server.
|
Package mcpserver wires UnPixel's decode and analysis capabilities as a Model Context Protocol server. |
|
Package mosaictext recovers monospace text from a mosaic-pixelated redaction with zero configuration: given only the image, it locates the redaction, detects the block grid, calibrates the typography (font, size, tracking) from the image itself, and reconstructs the most plausible text.
|
Package mosaictext recovers monospace text from a mosaic-pixelated redaction with zero configuration: given only the image, it locates the redaction, detects the block grid, calibrates the typography (font, size, tracking) from the image itself, and reconstructs the most plausible text. |
|
Package rerank re-orders decode candidates that have already been scored physically (by unpixel.Verify), by blending each candidate's image distance with a language score.
|
Package rerank re-orders decode candidates that have already been scored physically (by unpixel.Verify), by blending each candidate's image distance with a language score. |