002
21.02.2017, 13:35 Uhr
ao
(Operator)
|
Nochmal in Ruhe nachgedacht:
Willst du die Bearbeitung EINES Bildes auf mehrere Kerne verteilen? Das setzt voraus, dass der Algorithmus parallelisierbar ist. Das trifft vielleicht auf manche Bildverarbeitungs-Algorithmen zu, aber sicher nicht auf alle, oder?
Oder willst du yip mehrfach parallel aufrufen und jedes Mal ein anderes Bild verarbeiten lassen? In dem Fall kannst du die Parallelisierung nicht innerhalb von yip lösen, sondern musst es auf der Skript-Ebene machen. Also nicht in C++.
Außerdem solltest du mal kritisch auf deinen Algorithmus gucken, ich beziehe mich auf den Code in dem Floyd-Steinberg-Thread von vor ein paar Tagen:
1. du rufst coldist zu oft auf. Du solltest das bisher gefundene Minimum speichern und nicht bei jedem Schleifendurchlauf neu berechnen. Solange die Palette nur zwei Farben (schwarz und weiß) enthält, ist das noch nicht tragisch, aber ich schätze, du willst auch mal mit größeren Paletten dithern.
2. die anschließende Fortpflanzung des Dither-Fehlers auf die Nachbarpixel ist eine Orgie von Int-Float-Konversionen: Die Multiplikation konvertiert implizit nach float, das Zurückspeichern im Pixel macht wieder int draus (bzw. short).
Zitat: |
Ich habe erst die Klasse "pixel" vollständig von unsigned char nach short umgestellt;
|
Dadurch hast du beim Draufaddieren keine Über- und Unterläufe mehr, das war wahrscheinlich die Ursache für die Artefakte, die du anfangs hattest. Das hat die Ergebnisse schon mal wesentlich verbessert.
Was du aber nach wie vor hast: Du rechnest in float und speicherst in Ganzzahl, d.h. vor jeder Rechnung konvertierst du von short nach float und nach jeder Rechnung wieder zurück. Dadurch hast du jedesmal einen mehr oder weniger kleinen Rundungsfehler (je dunkler das Pixel, desto größer, relativ gesehen), der sich fortpflanzen und das Bild verfälschen kann. Obendrein ist diese Konvertiererei Zeitverschwendung, denn im nächsten Schleifendurchlauf wird sie ja wieder rückgängig gemacht.
Es ist zumindest mal den Versuch wert, ein Pixel aus drei float-Komponenten zu definieren, die Bilddaten beim Laden aus der Datei umzurechnen, alle Manipulationen in Fließkomma zu machen und erst am Ende zum Wegspeichern wieder Ganzzahldaten draus zu machen - wahrscheinlich wird das schneller, und das Ergebnis wird zumindest nicht schlechter.
3. Wenn du die Daten für t1 bis t4 schon hast, dann verwende sie doch und hol sie nicht nochmal ab:
C++: |
if (t1.red > -1) { img[r].at(c+1).get_all(triple); // überflüssig, die Daten sind schon in t1 newred = triple.red + dist.red*0.4375; // triple ist überflüssig, benutz t1 newgreen = triple.green + dist.green*0.4375; // dito newblue = triple.blue + dist.blue*0.4375; // dito img[r].at(c+1).set_all(mround(newred), mround(newgreen), mround(newblue)); } // für t2 bis t4 dasselbe.
|
Dieser Post wurde am 21.02.2017 um 13:39 Uhr von ao editiert. |