deskew — 2D geometry op

• Datenarten: image → image

• Aufruf: fullseye.apply(img, "deskew", a=0.5, b=0.5) (das 2-D-Modell ist ein Bild plus zwei skalare Regler a,b∈[0,1])

deskew: input → output

*Die Abbildung ist die tatsächliche Ausgabe auf einer synthetischen 128×128-Eingabe. Links Eingabe, rechts Ausgabe. Punktwolken als Draufsicht-Streudiagramm (Helligkeit = z), 1-D-Reihen als Linie, Volumen als Maximum-Projektion entlang z, Videos als mittleres Bild, komplexe Bilder als Betrag; Rückgabewerte, die kein Bild ergeben, werden als Werte gezeigt.*

Regler a durchfahren (0,1 / 0,5 / 0,9, der andere Regler auf Standard):

▸ deskew: Regler a durchfahren (Doku-Website)

Regler b durchfahren (0,1 / 0,5 / 0,9, der andere Regler auf Standard):

▸ deskew: Regler b durchfahren (Doku-Website)

Stufen (die vorangehenden Ops → dieser Op, von links nach rechts):

▸ deskew: Stufen (Doku-Website)

Auf anderen Bildern (synthetische Szene / Foto / Münzen. Obere Reihe: Eingaben, untere Reihe: deren Ausgaben. Regler auf Standard):

▸ deskew: andere Eingaben (Doku-Website)

*Keine Farb-Eingabe (H,W,3) gezeigt: dieser Op behandelt den Farbkanal als dritte Raumachse (vermischt Kanäle). Pro Kanal aufrufen.*

Verwendung

Misst die Schräglage und richtet sie auf (deskew). Der Winkel wird nicht als Regler vorgegeben, sondern aus dem Bild geschätzt.

a variiert den Suchbereich ±(2 + 43a)° (±2° bei a=0, ±45° bei a=1). b variiert die Verfeinerungsschrittweite 1/(1 + round(9b))° (1°-Schritte bei b=0, 0.1°-Schritte bei b=1; je feiner, desto langsamer ― hier liegt der Zielkonflikt).

Das Kriterium ist die Summe der quadrierten Differenzen des horizontalen Projektionsprofils. Wenn sich die Zeilen bei Drehung um einen bestimmten Winkel ausrichten, steigt und fällt die in Zeilenrichtung zusammengefasste Intensitätskurve am stärksten. Grob wird in 1°-Schritten gesucht, und das beste ±1° mit der Schrittweite von b verfeinert. Bei Gleichstand wird der kleinere Winkel genommen, daher fallen strukturlose Bilder und leere Frames auf 0° (= die Eingabe wird unverändert zurückgegeben).

• Die Suche läuft auf einer auf 256 Pixel an der langen Seite ausgedünnten Kopie (die Ausdünnung ändert den Winkel nicht). Nur die letzte 1 Drehung erfolgt in Originalgröße. Selbst die weiteste Suche auf 512x512 dauerte gemessen 121 ms.

• Die Bewertung wird nur auf dem zentralen Quadrat nach der Drehung erhoben (Seitenlänge = min(H,W)/sqrt(2)) ― ein Bereich, der bei jedem Winkel im Rahmen bleibt, sodass die Art der Eckenfüllung nicht in die Bewertung einfließt.

• Außerhalb des Rahmens wird mit dem Median des Randes gefüllt (mode="constant"). Das vorhandene rotate_image füllt durch Spiegelung, daher erscheinen beim Aufrichten eines Formulars Spiegelschriftzeichen in den vier Ecken (dessen docstring räumt selbst ein, es sei "ungeeignet, wenn außerhalb des Rahmens mit der Hintergrundfarbe gefüllt werden soll"). Dass sich das Aufgerichtete unverändert an OCR oder Zuschnitt weitergeben lässt, ist der Mehrwert dieses Ops.

Gemessene Genauigkeit und Grenzen (synthetische Seite mit 14 Pixel Zeilenabstand und 384 Pixel Breite): Mit b=1 (0.1°-Schritte) ergeben 1 / 2 / 3.7 / 5 / 12 / 20° allesamt einen Fehler von 0.00°. Allerdings liefern Neigungen unter 0.6° 0 ― selbst über die volle Seitenbreite erreicht der Zeilenversatz kein 1 Pixel, und die Schärfe der Projektion geht in der Abrundung durch die Interpolation unter. Für feinere Messungen die Eingabe vergrößern (das Kriterium ist proportional zur Breite).

Vorarbeiten: Die Neigung mit Projektionsprofilen zu messen ist klassisch; Postl (1986) nutzte die Varianz, Baird (1987) die Quadratsumme + eine grob-zu-fein-Winkelsuche als Kriterium. Dieses Op steht in Bairds Tradition; neu ist nicht die Methode, sondern die Behandlung des Randes (siehe unten).

★Früher lag das Differenzkriterium um +3.0 Grad daneben. Die Ursache ist nun geklärt. Bei der Vorabmessung vom 2026-09-17 hatte das Varianzkriterium bei Ground Truths von −7/−3/+3/+7 Grad einen Fehler von 0.0 Grad, das Differenzkriterium lag bei allen 4 um +3.0 Grad daneben, und als Ursache wurden vermutlich die Randartefakte von ndimage.rotate notiert, wobei "ob mode="constant" sie beseitigt, unverifiziert" sei. Ursache war nicht die Art der Füllung, sondern der betrachtete Bereich - wird die Bewertung nur auf dem einbeschriebenen Quadrat nach der Drehung erhoben, ergibt auch das Differenzkriterium bei allen 1/2/3.7/5/12/20 Grad einen Fehler von 0.00 Grad (gemessen).

Der Wertebereich bleibt der der Eingabe (weder lineare Interpolation noch der Randmedian erweitern ihn). ★Leere Frames (Wertebereich unter 1e-9) und Eingaben unter 8 Pixel werden unverändert zurückgegeben. ★Es darf nicht in Kacheln aufgeteilt werden ― der Winkel ist ein aus dem ganzen Bild bestimmter 1 Wert; pro Kachel gemessen würde jede Kachel um einen anderen Winkel gedreht (mit Begründung in scale.py registriert).

Ausführlicher Anwendungsleitfaden

• Leitfaden zur Familie gallery2d_geometry

Referenzen (Beispieldaten, Literatur)

• Katalog der Beispieldaten (Download-URLs / Lizenzen) — 2-D nutzt skimage.data (BSD/Public Domain) plus synthetische Bilder, 3-D nennt Download-URLs echter Datenquellen (Stanford, PDS, …).

• Herkunft und Literatur der Operatoren — die Quellen der Forschung/Verfahren, auf denen diese Operatorfamilie beruht.

• Der kanonische Algorithmus (Autor, Jahr) und seine Anwendungen stehen im Familienleitfaden oben.

In Studio ausprobieren

Das Programm unten ist nachweislich lauffähig (gleiche Eingabe wie die Abbildung). In der Studio-Hilfe wird dieser Block zu Schaltflächen, die es sofort laden und ausführen.

rotate_img 0.58 0.50
deskew 0.50 0.50

▸ Diese Pipeline laden  ·  Laden & ausführen

Ausführbare Beispiele (verifizierte Samples, die diesen Operator wirklich aufrufen)

• gallery2d_geometry — py -3.11 examples/gallery2d_geometry.py

Typkompatible Folge-Operatoren (nehmen image als Eingabe)

identity · gaussian · mean_box · bilateral · unsharp · median · min_filter · max_filter

Gleiche Kategorie (geometry)

rotate_img · rescale_img · affine_warp · sk_swirl · mirror_image · transpose_region · rotate_image · zoom_image_factor


*Provenance: ops.py — 2D Operator-Registry. Diese Notiz wird von tools/opdocs.py md erzeugt (nicht von Hand bearbeiten).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.