Kalibrierungsbeispiel Teil 2 – Kalibrierungstool

Teil 1 dieser Serie widmete sich einer robusten Bildauswertung mit wenig Rechenkraft auf Basis vorher bestimmter Kalibrierungswerte. Dieser Teil widmet sich deren Bestimmung. Wie bereits angeführt, ist die Kalibrierung wesentlich aufwendiger und rechenintensiver. Daher wurde sie in diesem Projekt ausgelagert auf einen Desktop-Rechner. Der Komplexität geschuldet widmen sich diesem Part mehrere Teile.

Abbildung 1: Ausschnitt UI Kalibrierungstool

Im ersten Teil wurde die Umsetzung der Lock-in-Phasendetektion mit positionsabhängiger Referenzfrequenz gezeigt. Die lokale Periode P(x)P(x) (Pixel pro mm) ist dabei ortsabhängig und wird berechnet als:

P(x)=P0+dPdx(xx0)+d2Pdx2(xx0)2[pxmm]P(x) = P_0 + \frac{dP}{dx}\,(x – x_0) + \frac{d^2P}{dx^2}\,(x – x_0)^2 \qquad \left[\frac{\text{px}}{\text{mm}}\right]

Daraus ergeben sich die Kalibrierungs-Parameter

  • x0x_0 als Referenzposition
  • P0P_0 als Basisperiode bei x0x_0
  • dP/dxdP/dx als linearer Koeffizient
  • d2P/dx2d^2P/dx^2 als quadratischer Koeffizient

Triviale Schritte wie die Festlegung des ROIs werden bewusst ausgelassen.

Ist der ROI festgelegt, ergibt sich das bekannte Messbild:

Analog der Auswertung im Vermessungsgerät wird zunächst ein 1D-Helligkeitsprofil generiert. Warum dieser Weg, der bereits Bildinformation verliert? Die Antwort ist: da praktische Tests gezeigt haben, auf diesem Weg wird die angestrebte Zielgenauigkeit bereits deutlich übertroffen. Die Striche sind hinreichend senkrecht, so dass hier der Informationsverlust durch Mittelung unbedeutend gegenüber der Relevanz der folgenden Verfahren ausfällt.

Das Bild wird in einem horizontalen ROI-Streifen der Höhe hh ab Zeile y0y_0 vertikal gemittelt. Für jede Spalte xx ergibt sich:

I(x)=1hy=y0y0+h1image(x,y)I(x) = \frac{1}{h} \sum_{y=y_0}^{y_0+h-1} \text{image}(x, y)

Das Helligkeitsprofil wird nun mit einem symmetrischen Box-Filter leicht geglättet:

I~(x)=1|N(x)|kN(x)I(k)\tilde{I}(x) = \frac{1}{|N(x)|} \sum_{k \in N(x)} I(k)

mit N(x)=[max(0,xr),min(W1,x+r)]N(x) = [\max(0, x-r),\; \min(W-1, x+r)] und |N(x)||N(x)| als Anzahl der Summanden (Randbehandlung durch Clamping).

Auf dieser Signalbasis erfolgt die Detektion der Linien. Und hier fällt die Entscheidung klar auf den Ansatz, die Kanten der Linien zu detektieren und nicht die Linie direkt z.B. als Helligkeitsminimum. Das hat mehrere Gründe:

  • Information steckt in der Flanke, nicht im Plateau
    Ein Strich erscheint im gemittelten 1D-Helligkeitsprofil als Mulde mit einem flachen, rauschdominierten Boden, der tiefste Punkt ist statistisch schlecht lokalisiert.
    Die Übergänge hell → dunkel und dunkel → hell hingegen sind die Stellen mit dem größten Gradienten |dI/dx||dI/dx| und damit dem höchsten Signal-zu-Rausch-Verhältnis für eine Ortsbestimmung.
    Die Flanke gibt die Position auf Bruchteile eines Pixels preis, das Plateau nicht.
  • Unempfindlich gegen Helligkeits- und Kontrastverläufe
    Die Beleuchtung über die Bildbreite ist nicht homogen, die Abbildung fällt zu den Rändern hin ab, und die Striche selbst haben nicht überall denselben Schwarzwert.
    Ein Verfahren, das auf absoluten Helligkeitswerten operiert (Schwelle, Minimum), reagiert auf jede dieser Störungen.
    Der Gradient ist dagegen invariant gegen additive Offsets und nahezu invariant gegen langsame multiplikative Verläufe, genau die Fehlerklassen, die in der Praxis auftreten.
  • Trennung von linker und rechter Kante als Plausibilitätsanker
    Da der vorzeichenbehaftete Gradient links und rechts eines Strichs entgegengesetzte Extrema hat, lassen sich die beiden Kanten getrennt detektieren und anschließend zu Paaren zusammenführen.
    Das liefert als Nebenprodukt die Strichbreite, und damit ein hartes Plausibilitätskriterium:
    Paare außerhalb des erwarteten Breitenfensters werden verworfen, bevor sie das Periodenmodell verfälschen.
    Ein Minimum-basiertes Verfahren kann diesen Selbsttest nicht leisten, da es nur einen Punkt pro Strich sieht.

Für die Detektion der Kanten wird aus dem geglätteten Helligkeitsprofil ein 1D Profil gg der signierten Gradienten über diesem mittels zentraler Differenzen gebildet:

g(x)=12(I~(x+1)I~(x1))für x[1,W2]g(0)=0g(W1)=0\begin{aligned} g(x) &= \frac{1}{2} \bigl(\tilde{I}(x+1) – \tilde{I}(x-1)\bigr) \qquad \text{für } x \in [1, W-2] \\ g(0) &= 0\\ g(W-1) &= 0 \end{aligned}

Bei einer linken Strichkante fällt die Intensität (hell → dunkel), daher ist g(x)<0g(x) < 0, an einer rechten Strichkante steigt die Intensität wieder (dunkel → hell), hier ist g(x)>0g(x) > 0.

Das Gradientenprofil ist jedoch rauschbehaftet. Für die Detektierung der Kanten werden in dem Profil Segmente [a,b][a, b] gesucht, in denen zusammenhängend der Gradient g(x)θg(x) \geq \theta (Kandidat für eine rechte Kante, positives Segment) oder g(x)θg(x) \leq -\theta (Kandidat für eine linke Kanten, negatives Segment) ausfällt. θ\theta dient also als Schwellwert. Die Kandidaten der linken und rechten Seite werden nach weiteren Kriterien gefiltert, wie minimaler und maximaler Länge, maximalen Peak etc.

wi=g(i)θ(rechte Seite)wi=g(i)θ(linke Seite)x=i=abwiii=abwi(Subpixel-Position)s=i=abwi(Peakstärke)\begin{aligned} w_i &= g(i) – \theta \qquad & (\text{rechte Seite}) \\ w_i &= -g(i) – \theta \qquad & (\text{linke Seite}) \\ x &= \frac{\sum_{i=a}^{b} w_i \cdot i} {\sum_{i=a}^{b} w_i} &\text{(Subpixel-Position)}\\ s &= \sum_{i=a}^{b} w_i \qquad &\text{(Peakstärke)} \end{aligned}

Der nächste Teil beleuchtet die Filterung der Kandidaten.