Skwik/README.md
Samuel Prevost cb576b603f
Some checks failed
Deploy to GitHub Pages / build (push) Has been cancelled
Deploy to GitHub Pages / deploy (push) Has been cancelled
docs: refresh README with current pipeline + accurate license
The "How it works" steps now match the five-stage Upload → EXIF →
Datums → Deskew → Measure flow (the old README still described a
four-step pipeline ending at "Run correction"). The algorithm section
is rewritten to describe what the solver actually does today: primary-
gauge selection, the alternating-minimization loop around findHomography,
the per-type correspondence builders (rectangle/line/ellipse),
confidence-as-replication weighting, oscillation detection, output
bounds clamp, and per-datum residual reporting.

Adds the three example tiles from the upload page, fixes the presets
list to mention circles, and corrects the license to match the GPLv3
LICENSE file already in the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 12:49:09 +02:00

6.0 KiB
Raw Permalink Blame History

Skwik

Client-side image deskewing tool. Upload a photo taken at an angle, place reference measurements on known objects, and get a perspective-corrected output with real-world scale.

Everything runs in the browser -- no server, no uploads.

Example

Before — angled photograph with a paper sheet as a known-size reference
Before — angled shot
After — perspective-corrected top-down view
After — corrected perspective
Measured — the corrected image with measurement annotations baked in
Measured — annotations baked in

How it works

  1. Upload a JPG or HEIC image (HEIC is converted automatically). Past uploads are cached and reopen straight into Measure with their datums and annotations restored.
  2. Review EXIF data -- camera, lens, focal length.
  3. Place datums on the image -- rectangles, lines, or ellipses (circles) with known real-world dimensions. Each datum carries a 1--5 confidence score. One datum can be flagged as the world-axis reference to fix the output orientation.
  4. Deskew -- OpenCV.js computes a perspective transform and produces a corrected image at a configurable px/mm scale, with per-datum residuals and a global RMS error reported.
  5. Measure -- annotate the corrected image with lines, rectangles, ellipses, circles, and angles in real-world units. Export the bare PNG, or the image with measurements baked in (full resolution or current viewport).

The algorithm

The pipeline picks a primary datum that fixes the output gauge (orientation, position, scale): any datum the user explicitly flagged as the world-axis reference, otherwise the highest-confidence rectangle, then ellipse, then line. The primary's known dimensions are mapped onto an axis-aligned output frame via cv.getPerspectiveTransform -- that's the warm-start homography.

That homography is then refined by an alternating-minimization loop around cv.findHomography (which internally runs DLT + Levenberg-Marquardt). On every outer pass, each datum is turned into output-space point correspondences using its shape constraint:

  • Rectangle -- Procrustes-fit an ideal w × h rectangle to the current projection of the user-marked corners.
  • Line -- preserve the projected midpoint and direction, rescale to the expected length.
  • Ellipse -- sample 12 points along the user ellipse, project them, then radially snap to a circle of the expected diameter centred on the projected user-marked centre. Forces circles to stay circular under perspective.

Confidence scores (1--5) are realised as integer replication of correspondences -- cv.findHomography has no native weighting. The primary additionally gets a ×3 gauge boost so its anchors don't drift while secondary datums are being satisfied. The loop runs until the homography stops moving (max-entry relative delta below 1e-6) or 30 iterations, with period-2 oscillation detection logging a warning if the alternating minimization fails to converge.

A single cv.warpPerspective with Lanczos resampling produces the corrected image at the requested px/mm scale; output bounds are derived by projecting the source image corners through the final homography and clamped to a 12288 px maximum dimension to keep WASM heap usage bounded.

Per-datum residuals are reported alongside the result: edge length error and corner perpendicularity for rectangles, length error for lines, and isotropy / skew / equivalent-diameter error from the projected conic for ellipses, plus a global RMS percentage across all of them.

Quick start

pnpm install
pnpm dev

Open http://localhost:5173.

Build

pnpm build      # type-check + production build
pnpm preview    # serve the build locally

Lint & format

pnpm lint       # eslint (strict TS + Vue)
pnpm lint:fix   # auto-fix
pnpm format     # prettier
pnpm type-check # vue-tsc

Stack

Layer Tech
Framework Vue 3 + TypeScript (strict)
Build Vite
Components shadcn-vue + Tailwind CSS v4
Canvas Konva.js + vue-konva
CV OpenCV.js 4.12 (WASM)
HEIC heic-to
EXIF exifr
State Pinia

Datum presets

Rectangles: A3, A4, A5, A6, 15×10 cm. Circles: €1, €2, US 25¢, UK 1p, CD. Custom dimensions supported on every type; lines accept any length.

How Skwik compares

There are plenty of tools that do part of what Skwik does, but none that combine everything:

Tool Client-side Multi-datum weighting Real-world mm scale Measurement tools Scale bar export
Skwik
MYOG Perspective Correction
PerspectiveFix
PicFix.pro
ImageOnline Perspective
Toolschimp Image Measure
Aspose Deskew

Most deskew tools just pull 4 corners to a rectangle without any real-world dimensions -- the output has no scale. Most measurement tools calibrate against a single reference and don't correct perspective. Skwik uses multiple weighted datums (rectangles, lines, and ellipses, each with a confidence score) to solve both problems in one pass, and lets you measure distances or export with a scale bar on the corrected image.

License

GNU General Public License v3.0