Bildverarbeitung · Python · Prüfmethodik
OpenCV mit Python: Otsu, adaptive und feste Schwellwerte richtig vergleichen
Welcher Schwellwert passt zur Prüfaufgabe? Ein fester Grenzwert, Otsu und adaptive Schwellwertbildung lösen nicht dasselbe Problem. Dieser Leitfaden zeigt einen nachvollziehbaren Vergleich mit Python und OpenCV: vom Bildausschnitt über eine binäre Maske bis zu den Fragen, die vor einem industriellen Einsatz beantwortet sein müssen.
Das Beispiel ist ein Lern- und Vergleichsprototyp für dunkle Merkmale auf hellem Hintergrund. Es enthält keine Kundenbilder, Produktionskennzahlen oder Freigabeaussage. Die Auswahl- und Testempfehlungen sind eine technische Vorgehensweise, keine universellen Grenzwerte.
Fester Schwellwert, Otsu oder adaptiv?
Ein fester Schwellwert verwendet überall denselben vorgegebenen Wert. Otsu ermittelt einen globalen Wert aus dem Histogramm; gut getrennte Helligkeitsgruppen sind dafür ein günstiger Ausgangspunkt. Adaptive Verfahren berechnen dagegen lokale Grenzwerte. Die Grundlagen beschreibt das OpenCV-Tutorial [1].
| Ausgangslage | Erster Kandidat | Kritische Gegenprobe |
|---|---|---|
| Kontrast bleibt über den Prüfbereich stabil | Fester Schwellwert | Hält derselbe Wert auch bei zulässiger Helligkeitsänderung? |
| Zwei Helligkeitsgruppen im gewählten Ausschnitt | Otsu | Bleibt das Ergebnis bei anderem Objektanteil im Bild brauchbar? |
| Hintergrundhelligkeit variiert räumlich | Adaptiv | Werden Flächen vollständig erfasst oder nur ihre Ränder? |
Meine Empfehlung: zunächst alle drei Kandidaten auf denselben repräsentativen Aufnahmen vergleichen. Ein aufwendigeres Verfahren gewinnt nicht automatisch. Wenn eine einfache Methode die vorher festgelegten Anforderungen erfüllt, ist eine zusätzliche Parameterebene zunächst eine weitere mögliche Fehlerquelle.
Den Prüfbereich (ROI, region of interest) vorab fachlich festlegen. Ein wechselnder Ausschnitt ist eine andere Eingabe und muss als solche dokumentiert werden. Wer einen Algorithmus auf einem engen Ausschnitt einstellt und später das gesamte Kamerabild verarbeitet, vergleicht keine identischen Bedingungen.
Python-Beispiel: drei Masken mit identischer Vorverarbeitung
Benötigt werden Python, NumPy und OpenCV; die API-Referenz dieses Beitrags ist Version 4.12. Das Skript erwartet eine eigene Datei inspection.png: ein einkanaliges 8-Bit-Bild, mindestens 31 × 31 Pixel groß. Farbbilder und höher aufgelöste Intensitätswerte werden ausdrücklich abgewiesen. IMREAD_UNCHANGED vermeidet hier eine stillschweigende Umwandlung beim Einlesen. Siehe Datei-API [5].
import cv2 as cv
import numpy as np
def compare_thresholds(gray):
if gray is None or not isinstance(gray, np.ndarray):
raise ValueError("Provide a readable image.")
if gray.ndim != 2 or gray.dtype != np.uint8:
raise ValueError("Expected single-channel uint8.")
if min(gray.shape) < 31:
raise ValueError("Example requires at least 31 x 31 pixels.")
smooth = cv.GaussianBlur(gray, (3, 3), 0)
_, fixed = cv.threshold(
smooth, 120, 255, cv.THRESH_BINARY_INV
)
otsu_value, otsu = cv.threshold(
smooth, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU
)
adaptive = cv.adaptiveThreshold(
smooth, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
cv.THRESH_BINARY_INV, 31, 7
)
return otsu_value, {
"fixed": fixed, "otsu": otsu, "adaptive": adaptive
}
if __name__ == "__main__":
gray = cv.imread("inspection.png", cv.IMREAD_UNCHANGED)
threshold, masks = compare_thresholds(gray)
print("OpenCV:", cv.__version__)
print("Otsu threshold:", threshold)
for name, mask in masks.items():
print(name, mask.shape, mask.dtype)
Die Masken bleiben im Arbeitsspeicher; Eingabedateien werden nicht überschrieben. Alle Varianten erhalten dieselbe geglättete Eingabe. Mit THRESH_BINARY_INV werden Werte bis einschließlich des jeweiligen Grenzwerts weiß. Damit ist im Beispiel das dunkle Prüfmerkmal der weiße Vordergrund. Der ausgegebene Otsu-Wert ist ein Intensitätsgrenzwert, kein Vertrauenswert und kein Qualitätsmaß. API-Details [2].
Die Zahlen 120, 31 und 7 sind Startwerte für den Vergleich, keine industriellen Empfehlungen. Eine synthetische Funktionsprüfung kann zeigen, dass Formate und Aufrufe funktionieren; sie ersetzt keine Auswertung echter Prüfaufnahmen. Für eine Reproduktion gehören die tatsächlich installierten Bibliotheksversionen ins Testprotokoll.
Parameter gezielt variieren – nicht gleichzeitig erraten
Fenstergröße und Offset
adaptiveThreshold() benötigt ein einkanaliges 8-Bit-Bild und eine ungerade Fenstergröße größer als eins. Beim Gauß-Verfahren wird der lokal gewichtete Mittelwert um C vermindert. OpenCV-Referenz [2].
Ein anschaulicher Grenzfall folgt direkt daraus: Liegt das Fenster vollständig in einer gleichmäßig dunklen Fläche und ist C positiv, liegt deren Pixelwert über „lokaler Mittelwert minus C“. Die invertierte Maske wird dort schwarz. Die Fläche kann deshalb innen verschwinden, obwohl ihre Ränder erkannt werden. Adaptive Schwellwertbildung ist somit nicht gleichbedeutend mit vollständiger Objektsegmentierung.
Eine sinnvolle Gegenprobe ist, dieselbe Merkmalsgröße in mehreren Bildpositionen und bei mehreren Fenstergrößen zu testen. Dabei bleibt alles andere zunächst konstant. Ändert sich die Bildauflösung, darf eine unveränderte Fenstergröße in Pixeln nicht ungeprüft als derselbe fachliche Maßstab gelten.
Glättung und Morphologie
Gauß-Glättung reduziert hochfrequente Bildanteile, kann aber auch Kanten verbreitern. Deshalb ist die 3 × 3-Glättung im Beispiel nur eine Vergleichsbedingung. Ein zusätzlicher Test ohne Glättung zeigt, ob kleine relevante Details verloren gehen. OpenCV zu Filtern [3].
Opening besteht aus Erosion und anschließender Dilatation, Closing aus der umgekehrten Reihenfolge. Damit lassen sich kleine Vordergrundstrukturen entfernen beziehungsweise kleine Löcher schließen. OpenCV zu Morphologie [4]. Genau diese Strukturen könnten jedoch das gesuchte Fehlerbild sein. Deshalb ist im Beispiel bewusst keine automatische „Bereinigung“ eingebaut.
Vor einer Nachbearbeitung die Frage festhalten: Was gilt fachlich als Störung, was als Defekt? Wird ein dunkler Kratzer als weißes Merkmal dargestellt, darf eine Reinigung ihn nicht bloß deshalb löschen, weil er klein ist. Rohmaske und bearbeitete Maske sollten im Test nebeneinander erhalten bleiben.
Prüfplan statt schöner Einzelbilder
Für einen belastbaren Vergleich empfehle ich folgende Reihenfolge. Sie ist unabhängig davon, welcher der drei Kandidaten auf dem ersten Bild am besten aussieht:
- Entscheidung definieren: Soll ein Bauteil gefunden, ein Fehler erkannt oder eine Fläche gemessen werden? Eine ähnliche Maske ist noch keine richtige Prüfentscheidung.
- Referenzen festlegen: Originalbild, erwartetes Ergebnis und Begründung zusammenhalten. Unklare Fälle getrennt kennzeichnen, statt sie nachträglich passend zu etikettieren.
- Einstell- und Prüfdaten trennen: Parameter an einem Teil der Aufnahmen festlegen und an bislang unbenutzten Bildern prüfen. Nahezu identische Bilder desselben Teils nicht als unabhängige Bestätigung behandeln.
- Randfälle bewusst aufnehmen: Zulässige Lage-, Material- und Helligkeitsvarianten, leere Bilder, Grenzfälle sowie fehlerfreie und fehlerhafte Teile berücksichtigen. Welche Varianten zulässig sind, kommt aus der Anwendung.
- Fehler getrennt zählen: Übersehene Defekte und fälschlich verworfene Gutteile separat dokumentieren. Bei einer Messaufgabe zusätzlich gegen eine geeignete Referenz messen; die Pixelmaske allein genügt nicht.
- Änderungen nachvollziehbar halten: Datensatz, ROI, Filter, Schwellwertverfahren, Parameter und Softwareversion gemeinsam versionieren. Laufzeit auf dem vorgesehenen Zielsystem mit der gesamten Verarbeitungskette prüfen.
Eine mögliche Dokumentationszeile lautet: Bild-ID → Referenzentscheidung → Konfiguration → Ergebnis → Abweichung → offene Frage. Dieser Vorschlag liefert noch keine Akzeptanzgrenzen. Diese müssen vor der abschließenden Bewertung aus den Risiken und Anforderungen der konkreten Aufgabe abgeleitet werden.
Für geometrische Messungen ist außerdem die Abbildungsgeometrie relevant: Der Leitfaden zur Kamerakalibrierung mit OpenCV behandelt diesen separaten Baustein. Wie Konfigurationen und Nachweise verknüpft werden können, erläutert der Beitrag über Knowledge Graphs in der Bildverarbeitung.
Häufige Fragen
Warum liefert Otsu nicht automatisch die richtige Maske?
Otsu kennt die Bedeutung eines Defekts nicht. Ein Histogramm enthält Helligkeitshäufigkeiten, aber keine fachliche Beschriftung „gut“ oder „schlecht“. Das berechnete Ergebnis muss deshalb gegen die gewünschte Prüfentscheidung geprüft werden.
Sollte ein 16-Bit-Kamerabild einfach in uint8 umgewandelt werden?
Nicht stillschweigend. Der Beispielcode bricht dafür absichtlich ab. Eine nötige Skalierung gehört mit Eingabebereich und Informationsverlust in die dokumentierte Verarbeitungskette; nach einer Änderung müssen die Parameter erneut geprüft werden.
Wann ist ein anderer Ansatz nötig?
Wenn sich die relevanten Fälle innerhalb der zulässigen Betriebsbedingungen nicht zuverlässig trennen lassen, sollte die Aufgabe neu bewertet werden: Aufnahmebedingungen, geeignete Merkmale oder ein anderes Segmentierungsverfahren. Ein weiterer Parameter allein ist kein Nachweis, dass die Ursache behoben wurde.
Verwendete Primärquellen
- OpenCV 4.12: Image Thresholding
- OpenCV 4.12: threshold / adaptiveThreshold API
- OpenCV 4.12: Smoothing Images
- OpenCV 4.12: Morphological Transformations
- OpenCV 4.12: Image File Reading and Writing
Dokumentationsstand: OpenCV 4.12; Quellen geprüft am 11. September 2026. Der Code ist ein eigenständiges Vergleichsbeispiel. Die Prüfstrategie und die Interpretation des gleichmäßigen Flächeninneren sind daraus abgeleitete technische Empfehlungen.
