Derzeit durchlaufe ich in einer Android-Anwendung, die ich entwickle, die Pixel eines Bildes, um es zu verwischen. Dies dauert bei einem 640 x 480-Bild etwa 30 Sekunden.
Beim Durchsuchen von Apps im Android Market bin ich auf eine gestoßen, die eine Unschärfefunktion enthält und deren Unschärfe sehr schnell ist (z. B. 5 Sekunden), sodass sie eine andere Methode zum Verwischen verwenden müssen.
Kennt jemand einen schnelleren Weg als das Durchlaufen der Pixel?
Antworten:
Dies ist eine Aufnahme im Dunkeln, aber Sie können versuchen, das Bild zu verkleinern und dann erneut zu vergrößern. Dies kann mit gemacht werden
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
. Stellen Sie sicher und setzen Sie den Filterparameter auf true. Es wird in nativem Code ausgeführt, sodass es möglicherweise schneller ist.quelle
Für zukünftige Googler ist hier ein Algorithmus, den ich von Quasimondo portiert habe. Es ist eine Art Mischung zwischen einer Box-Unschärfe und einer Gaußschen Unschärfe, es ist sehr hübsch und auch ziemlich schnell.
Das Update für Personen, bei denen das ArrayIndexOutOfBoundsException-Problem auftritt: @anthonycr in den Kommentaren enthält folgende Informationen:
quelle
for
Schleife unmittelbar vor dem schlechten dereferenzieren, entweder die Berechnung derrbs
variablen oder die Berechnung dergsum
,rsum
oderbsum
Variablen wird nicht richtig gemacht. Ich habe festgestellt, dass durch ErsetzenMath.abs
durchStrictMath.abs
oder eine andereabs
Implementierung der Absturz nicht auftritt. Da sichStrictMath.abs
selbst delegiertMath.abs
, scheint es eine schlechte Optimierung zu sein.Android Blur Guide 2016
mit Showcase / Benchmark App und Source auf Github . Schauen Sie sich auch das Blur-Framework an, an dem ich gerade arbeite: Dali .
Nachdem ich viel experimentiert habe, kann ich Ihnen jetzt sicher einige solide Empfehlungen geben, die Ihnen das Leben in Android erleichtern, wenn Sie das Android Framework verwenden.
Laden und Verwenden einer verkleinerten Bitmap (für sehr verschwommene Bilder)
Verwenden Sie niemals eine Bitmap in voller Größe. Je größer das Bild ist, desto mehr muss verwischt werden und desto höher muss der Unschärferadius sein. Je länger der Unschärferadius ist, desto länger dauert der Algorithmus.
Dadurch wird die Bitmap mit
inSampleSize
8 geladen , also nur 1/64 des Originalbilds. Testen Sie, wasinSampleSize
Ihren Anforderungen entspricht, behalten Sie es jedoch bei 2 ^ n (2,4,8, ...), um eine Qualitätsminderung aufgrund von Skalierung zu vermeiden. Weitere Informationen finden Sie in Google DocEin weiterer großer Vorteil ist, dass das Laden von Bitmaps sehr schnell erfolgt. Bei meinen frühen Unschärfetests stellte ich fest, dass die längste Zeit während des gesamten Unschärfeprozesses das Laden von Bildern war. Um ein 1920x1080-Image von der Festplatte zu laden, benötigte mein Nexus 5 500 ms, während die Unschärfe nur noch etwa 250 ms dauerte.
Verwenden Sie Renderscript
Renderscript bietet
ScriptIntrinsicBlur
einen Gaußschen Unschärfefilter. Es hat eine gute visuelle Qualität und ist nur die schnellste, die Sie realistisch auf Android bekommen. Google behauptet, "normalerweise 2-3x schneller als eine Multithread-C-Implementierung und oft 10x + schneller als eine Java-Implementierung zu sein" . Renderscript ist sehr ausgefeilt (unter Verwendung des schnellsten Verarbeitungsgeräts (GPU, ISP usw.) usw.) und es gibt auch die v8-Unterstützungsbibliothek, die es bis auf 2.2 kompatibel macht. Nun, zumindest theoretisch scheint es durch meine eigenen Tests und Berichte von anderen Entwicklern nicht möglich zu sein, Renderscript blind zu verwenden, da die Hardware- / Treiberfragmentierung bei einigen Geräten Probleme zu verursachen scheint, selbst bei höheren SDK-Levels (z. B. bei mir) Probleme mit dem 4.1 Nexus S) Seien Sie also vorsichtig und testen Sie auf vielen Geräten. Hier ist ein einfaches Beispiel, mit dem Sie beginnen können:Wenn Sie die v8-Unterstützung mit Gradle verwenden, die von Google ausdrücklich empfohlen wird, "weil sie die neuesten Verbesserungen enthält" , müssen Sie Ihrem Build-Skript nur zwei Zeilen hinzufügen und
android.support.v8.renderscript
mit den aktuellen Build-Tools verwenden ( aktualisierte Syntax für das Android Gradle-Plugin v14 + ).Einfacher Benchmark auf einem Nexus 5 - Vergleich von RenderScript mit verschiedenen anderen Java- und Renderscript-Implementierungen:
Die durchschnittliche Laufzeit pro Unschärfe bei verschiedenen Bildgrößen
Megapixel pro Sekunde, die unscharf werden können
Jeder Wert ist der Durchschnitt von 250 Runden.
RS_GAUSS_FAST
istScriptIntrinsicBlur
(und fast immer die schnellste), andere, die damit beginnen,RS_
sind meistens Convolve-Implementierungen mit einfachen Kerneln. Die Details der Algorithmen finden Sie hier . Dies ist keine reine Unschärfe, da ein guter Teil die gemessene Speicherbereinigung ist. Dies ist hier zu sehen (ScriptIntrinsicBlur
auf einem 100x100-Bild mit ca. 500 Runden)Die Spikes sind gc.
Sie können selbst überprüfen, ob die Benchmark-App im Playstore verfügbar ist: BlurBenchmark
Verwendet Bitmap wo immer möglich (wenn prio: Leistung> Speicherbedarf)
Wenn Sie mehrere Unschärfen für eine Live-Unschärfe oder ähnliches benötigen und Ihr Speicher dies zulässt, wird die Bitmap nicht mehrmals aus Drawables geladen, sondern in einer Elementvariablen "zwischengespeichert". Versuchen Sie in diesem Fall immer, dieselben Variablen zu verwenden, um die Speicherbereinigung auf ein Minimum zu beschränken.
Überprüfen Sie auch die neue
inBitmap
Option beim Laden aus einer Datei oder einem Drawable, die den Bitmap-Speicher wiederverwendet und Zeit für die Speicherbereinigung spart.Zum Mischen von scharf bis verschwommen
Die einfache und naive Methode besteht darin, nur 2
ImageViews
, eine unscharfe und Alpha-Fade zu verwenden. Wenn Sie jedoch einen raffinierteren Look wünschen, der sanft von scharf zu verschwommen übergeht, lesen Sie den Beitrag von Roman Nurik in seiner Muzei-App .Grundsätzlich erklärt er, dass er einige Frames mit unterschiedlichen Unschärfebereichen vorab verwischt und sie als Keyframes in einer Animation verwendet, die wirklich flüssig aussieht.
quelle
renderscriptSupportModeEnabled true
oder es wird nicht gebaut! Ich habe immer gesucht!EDIT (April 2014): Dies ist eine Frage- / Antwortseite, die anscheinend immer noch viele Treffer erhält. Ich weiß, dass ich für diesen Beitrag immer positive Stimmen bekomme. Wenn Sie dies lesen, müssen Sie jedoch feststellen, dass die hier veröffentlichten Antworten (sowohl meine als auch die akzeptierte Antwort) veraltet sind. Wenn Sie heute eine effiziente Unschärfe implementieren möchten , sollten Sie RenderScript anstelle von NDK oder Java verwenden. RenderScript läuft unter Android 2.2+ (unter Verwendung der Android Support Library ), daher gibt es keinen Grund, es nicht zu verwenden.
Die alte Antwort folgt, aber Vorsicht, sie ist veraltet.
Für zukünftige²-Googler ist hier ein Algorithmus, den ich von Yahels Port von Quasimondos Algorithmus portiert habe, aber mit dem NDK. Es basiert natürlich auf Yahels Antwort. Da hier jedoch nativer C-Code ausgeführt wird, ist er schneller. Viel schneller. Wie 40 mal schneller.
Ich finde , dass das NDK verwendet , ist wie alle Bildmanipulation sollte auf Android getan werden ... es etwas ärgerlich ist zunächst zu implementieren (ein großes Tutorial lesen JNI über die Verwendung und die NDK hier ), aber viel besser, und nahezu in Echtzeit für eine viele Dinge.
Als Referenz dauerte es mit der Java-Funktion von Yahel 10 Sekunden, um mein Bild mit 480 x 532 Pixel und einem Unschärferadius von 10 zu verwischen. Mit der nativen C-Version dauerte es jedoch 250 ms. Und ich bin mir ziemlich sicher, dass es noch weiter optimiert werden kann ... Ich habe gerade eine dumme Konvertierung des Java-Codes durchgeführt, es gibt wahrscheinlich einige Manipulationen, die verkürzt werden können, ich wollte nicht zu viel Zeit damit verbringen, das Ganze umzugestalten.
Verwenden Sie es dann folgendermaßen (unter Berücksichtigung einer Klasse namens com.insert.your.package.ClassName und einer nativen Funktion namens functionToBlur, wie im obigen Code angegeben):
Es wird eine RGB_8888-Bitmap erwartet!
Um eine RGB_565-Bitmap zu verwenden, erstellen Sie entweder eine konvertierte Kopie, bevor Sie den Parameter übergeben (yuck), oder ändern Sie die Funktion, um einen neuen
rgb565
Typ anstelle vonrgba
:Das Problem ist, dass Sie, wenn Sie dies tun, nicht mehr lesen
.red
können.green
und.blue
von dem Pixel das Byte richtig lesen müssen, duh. Als ich das vorher brauchte, tat ich Folgendes:Aber es gibt wahrscheinlich einen weniger dummen Weg, dies zu tun. Ich fürchte, ich bin kein großer C-Codierer.
quelle
r[wh]
,g[wh]
undb[wh]
zuuint8_t
.pastebin.com
Dieser Code ist perfekt für mich
quelle
Sie können jetzt ScriptIntrinsicBlur aus der RenderScript-Bibliothek verwenden, um schnell zu verwischen. Hier erfahren Sie, wie Sie auf die RenderScript-API zugreifen. Das Folgende ist eine Klasse, die ich erstellt habe, um Ansichten und Bitmaps zu verwischen:
quelle
Für mich hat das gut funktioniert: So verwischen Sie Bilder effizient mit RenderScript von Android
quelle
Verwenden Sie das hier erwähnte Render-Skript http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android/
quelle
Dies ist für alle Personen, die den Radius von vergrößern müssen
ScriptIntrinsicBlur
, um eine härtere Gaußsche Unschärfe zu erzielen.Anstatt den Radius auf mehr als 25 zu setzen, können Sie das Bild verkleinern und das gleiche Ergebnis erzielen. Ich habe eine Klasse namens geschrieben
GaussianBlur
. Unten sehen Sie die Verwendung und die gesamte Klassenimplementierung.Verwendung:
Klasse:
quelle
Danke @Yahel für den Code. Das Posten der gleichen Methode mit Unterstützung für das Verwischen von Alphakanälen, für die ich einige Zeit gebraucht habe, damit sie ordnungsgemäß funktioniert, sodass möglicherweise Zeit gespart wird:
quelle
Ich habe das schon mal benutzt ..
quelle
Für zukünftige Googler, die sich für den NDK-Ansatz entscheiden, finde ich den verlässlich genannten Stackblur-Algorithmus. Ich habe hier eine C ++ - Implementierung gefunden, die nicht auf SSE basiert - http://www.antigrain.com/__code/include/agg_blur.h.html#stack_blur_rgba32, die einige Optimierungen unter Verwendung statischer Tabellen enthält, wie:
Ich habe den Stackblur-Algorithmus für Multi-Core-Systeme modifiziert - hier finden Sie http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ Da immer mehr Geräte 4 Kerne haben - Optimierungen ergeben 4x Geschwindigkeitsvorteil.
quelle
Nicolas POMEPUY Rat. Ich denke, dieser Link wird hilfreich sein: Unschärfeeffekt für Android-Design
Beispielprojekt bei github
quelle
Wir haben versucht, RenderScript-Unschärfe wie oben erwähnt in verschiedenen Antworten zu implementieren. Wir konnten nur die v8-RenderScript-Version verwenden, was uns große Probleme bereitete.
Ich möchte unsere schmutzige Nur-Java-Version teilen, die langsam ist und in einem separaten Thread und, wenn möglich, vor der Verwendung ausgeführt werden sollte und daher fortbesteht.
Diese Lösung ist alles andere als perfekt, erzeugt jedoch einen vernünftigen Unschärfeeffekt, der auf der Tatsache beruht, dass eine hochtransparente Version desselben Bildes auf eine kaum transparente "scharfe" Version gezeichnet wird. Das Alpha hängt von der Entfernung zum Ursprung ab.
Sie können einige "magische Zahlen" an Ihre Bedürfnisse anpassen. Ich wollte diese "Lösung" nur für alle freigeben, die Probleme mit der v8-Supportversion von RenderScript haben.
quelle
Wenn Sie weiterhin Probleme mit der Renderscript-Unterstützungsbibliothek auf x86-Chipsätzen haben, lesen Sie bitte diesen Beitrag des Erstellers der Bibliothek. Es sieht so aus, als hätte das von ihm vorbereitete Update es nicht irgendwie in die Build Tools v20.0.0 geschafft, daher stellt er die Dateien zur Verfügung, um es manuell zu reparieren, und eine kurze Erklärung, wie es geht.
https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=71347
quelle
vom Mario Viviani Blog kann man diese Lösung von 17 Android Version verwenden:
https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz
oder
https://gist.github.com/Mariuxtheone/903c35b4927c0df18cf8
quelle
Hier ist eine Echtzeit-Unschärfe-Überlagerung mit RenderScript, die schnell genug zu sein scheint.
https://github.com/mmin18/RealtimeBlurView
quelle
Ich fand heraus, dass ein wenig abnehmender Kontrast, Helligkeit und Sättigung unscharfe Bilder hübscher machen. Deshalb kombinierte ich verschiedene Methoden aus dem Stapelüberlauf und erstellte diese Unschärfeklasse, die sich mit unscharfen Bildern, sich ändernder Helligkeit, Sättigung, Kontrast und Größe der unscharfen Bilder befasst. Es kann auch Bilder von zeichnbar in Bitmap konvertieren und umgekehrt.
quelle
Am i / o 2019 wurde folgende Lösung vorgestellt:
quelle