Bildverarbeitung in Java multi-threaded

vorhergehende Artikel in: Java Komponenten Numerik
13.08.2020

Ich habe vor einiger Zeit darüber berichtet, dass ich eine alte Bibliothek zur Bildverarbeitung von C++ nach Java portiert habe. Ich habe sie inzwischen poliert und um neue Features ergänzt...

Um zunächst auf die naheliegendste Kritik einzugehen: Ich weiß, dass es solche Bibliotheken bereits gibt und ich wusste es damals, als ich die ursprüngliche Version in C++ implementierte ebenfalls. Alle bestehenden Bibliotheken hatten damals aber einen für mich wichtigen Fehler: Sie haben Bilder als Bilder angesehen. Ich erkläre mal diese etwas seltsam anmutende Äußerung:

Zum Zeitpunkt der Entstehung der ursprünglichen Variante beschäftigte ich mich an der Universität mit Feature-Extraktion aus Bildern zum Einsatz in autonomen Systemen - unter anderem für die Navigation und Hindernisvermeidung. Es war (damals) wichtig, die Bilder einer Vorverarbeitung zu unterziehen um die wichtigen Features robust und deutlich daraus gewinnen zu können.

Diese Vorverarbeitung geschah in mehreren aufeinander aufbauenden Operationen oder Schritten. Nun werden Bilder (zumindest damals hatten wir noch kein HDR) pro Band (Grauwert, Rot, Grün, Blau,...) in 256 Stufen diskretisiert. Wenn das Ergebnis jeder Operation jeweils wieder ein Bild ist, gehen unter Umständen wichtige Informationen verloren - es wäre besser, wenn die Operationen den vollen Dynamikumfang und damit die Genauigkeit des Datentyps Double oder wenigstens Float hätten und erst am Ende der Verarbeitungspipeline wieder in ein Bild mit maximal 256 diskreten Abstufungen diskretisiert würden.

Daher war das zentrale Konzept meiner Bildverarbeitungsbibliothek eine Struktur, die beliebig viele Bänder enthalten konnte und die Werte für jedes einzelne Pixel darin waren kontinuierliche Werte in einem beliebig wählbaren Dynamikbereich.

Diese Argumentation trifft unverändert auch auf die Java-Variante zu.

In den letzten Wochen habe ich diverse Tests für die Java-Variante implementiert und die Bibliothek mit Hilfe des Internets um eine Implementierung der diskreten Fourier Transformation für Bilder erweitert.

Dabei fiel mir auf, dass ich bisher noch keine Performance-Optimierung durch Multithreading in der Bibliothek eingebaut hatte (wie gesagt - die C++ Variante ist bereits sehr alt...). Daher habe ich im Zuge der Tests eine Operation exemplarisch parallelisiert.

Diese Parallelisierung fand zum einen mittels Verlagerung der Berechnung auf die GPU statt, worüber ich bereits berichtet habe.

Die Parallelisierung mittels mehrerer Threads zeigte einen deutlichen und unmittelbaren Gewinn - allerdings erst ab einer bestimmten Bildgröße. Ich gebe hier die Ergebnisse für unterschiedliche Bildgrößen an:

Für ein Bild mit 512*512 Pixeln Auflösung und drei Bändern war zu sehen, dass die Streuung der Messung dafür sorgte, dass langsame Durchläufe des parallelen Algorithmus tatsächlich länger dauern konnten als schnelle Durchläufe des sequentiellen Algorithmus - die Streuung lag für die sequentielle Variante zwischen 31 und 60 Millisekunden, bei der parallelen waren es zwischen 17 und 63 Millisekunden.

Für ein Bild mit 1608*1608 Pixeln Auflösung war die parallele Variante deutlich überlegen - die Streuung lag für die sequentielle Variante zwischen 210 und 237 Millisekunden, bei der parallelen waren es zwischen 119 und 148 Millisekunden.

Alle Artikel rss Wochenübersicht Monatsübersicht Github Repositories Gitlab Repositories Mastodon Über mich home xmpp


Vor 5 Jahren hier im Blog

  • Fährnisse des Buildprozesses unter Windows

    17.07.2019

    Nachdem ich begonnen hatte, mich mit der Beschleunigung der Berechnung des Mandelbrot-Fraktals unter Zuhilfenahme der Shadereinheiten in Graphikkarten zu beschäftigen und erste Erfolge feiern konnte, wollte ich das mal auf einer richtigen Graphikkarte ausprobieren...

    Weiterlesen...

Neueste Artikel

  • Datenvalidierung UTF8 mit BiDi-Steuerzeichen (TrojanSource 2.0)

    Ich bin heute nochmal inspiriert worden, weiter über die Trojan Source Vulnerability nachzudenken. Meiner Meinung nach bestehen hier noch Probleme - speziell bei Nutzereingaben oder Daten, die über externe Schnittstellen ampfangen werden.

    Weiterlesen...
  • OpenStreetMap Navi als Docker-Container

    Ich habe die auf OpenStreetMap basierende OpenSource Navigationslösung Graphhopper in einen Docker-Container gepackt und als neuestes Mitglied in meinem Docker-Zoo willkommen geheißen.

    Weiterlesen...
  • SQL-Aggregatfunktionen in SQLite als BeanShell-Scripts

    Ich habe neulich über eine Möglichkeit berichtet, SQLite mittels der sQLshell und Beanshell-Skripten um SQL-Funktionen zu erweitern. In diesem Artikel versprach ich auch, über eine solche Möglichkeit für Aggregatfunktionen zu berichten.

    Weiterlesen...

Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.

Wer daran teilhaben und eventuell sogar davon profitieren möchte, muß damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.

Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...

PS: Meine öffentlichen GitHub-Repositories findet man hier - meine öffentlichen GitLab-Repositories finden sich dagegen hier.