Actuellement, dans une application Android que je développe, je parcourt les pixels d'une image pour la brouiller. Cela prend environ 30 secondes sur une image 640x480.
En parcourant des applications sur l'Android Market, j'en suis tombé sur une qui inclut une fonction de flou et leur flou est très rapide (comme 5 secondes), ils doivent donc utiliser une méthode différente de flou.
Quelqu'un connaît-il un moyen plus rapide autre que de parcourir les pixels?
Réponses:
Il s'agit d'une photo dans le noir, mais vous pouvez essayer de réduire l'image, puis de l'agrandir à nouveau. Cela peut être fait avec
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
. Assurez-vous et définissez le paramètre de filtre sur true. Il fonctionnera en code natif, donc ce sera peut-être plus rapide.la source
Pour les futurs Googleurs, voici un algorithme que j'ai porté depuis Quasimondo. C'est une sorte de mélange entre un flou de boîte et un flou gaussien, c'est très joli et assez rapide aussi.
Mise à jour pour les personnes rencontrant le problème ArrayIndexOutOfBoundsException: @anthonycr dans les commentaires fournit ces informations:
la source
for
boucle immédiatement avant la mauvaise déréférencement, soit le calcul de larbs
variable ou le calcul desgsum
,rsum
ou lesbsum
variables ne sont pas faites à droite. J'ai trouvé qu'en remplaçantMath.abs
parStrictMath.abs
ou une autreabs
implémentation, le crash ne se produit pas. Puisqu'ilStrictMath.abs
délègue àMath.abs
, il semble que ce soit une mauvaise optimisation.Guide Android Blur 2016
avec Showcase / Benchmark App et Source sur Github . Consultez également le framework Blur sur lequel je travaille actuellement: Dali .
Après avoir beaucoup expérimenté, je peux maintenant vous donner en toute sécurité des recommandations solides qui vous faciliteront la vie sous Android lorsque vous utilisez le Framework Android.
Charger et utiliser une image bitmap réduite (pour les images très floues)
N'utilisez jamais la taille d'un Bitmap. Plus l'image est grande, plus elle doit être floue et plus le rayon de flou doit être élevé et, généralement, plus le rayon de flou est élevé, plus l'algorithme prend du temps.
Cela chargera le bitmap avec
inSampleSize
8, donc seulement 1/64 de l'image d'origine. Testez ce quiinSampleSize
correspond à vos besoins, mais gardez-le 2 ^ n (2,4,8, ...) pour éviter de dégrader la qualité en raison de la mise à l'échelle. Voir la documentation Google pour en savoir plusUn autre très gros avantage est que le chargement des bitmaps sera très rapide. Lors de mes premiers tests de flou, j'ai pensé que le temps le plus long de tout le processus de flou était le chargement de l'image. Donc, pour charger une image 1920 x 1080 à partir du disque, mon Nexus 5 avait besoin de 500 ms, tandis que le flou ne prenait que 250 ms environ.
Utiliser Renderscript
Renderscript fournit
ScriptIntrinsicBlur
un filtre de flou gaussien. Il a une bonne qualité visuelle et est juste le plus rapide que vous obtenez de manière réaliste sur Android. Google prétend être "généralement 2-3 fois plus rapide qu'une implémentation C multithread et souvent 10x + plus rapide qu'une implémentation Java" . Renderscript est vraiment sophistiqué (utilisant le périphérique de traitement le plus rapide (GPU, FAI, etc.), etc.) et il existe également la bibliothèque de support v8 qui le rend compatible jusqu'à 2,2 . Eh bien au moins en théorie, grâce à mes propres tests et rapports d'autres développeurs, il semble qu'il n'est pas possible d'utiliser Renderscript à l'aveuglette, car la fragmentation du matériel / pilote semble causer des problèmes avec certains périphériques, même avec un sdk lvl plus élevé (par exemple, j'avais problèmes avec le Nexus S 4.1) alors soyez prudent et testez sur de nombreux appareils. Voici un exemple simple qui vous aidera à démarrer:Lorsque vous utilisez le support v8 avec Gradle, qui est spécifiquement recommandé par Google "car ils incluent les dernières améliorations" , il vous suffit d'ajouter 2 lignes à votre script de build et de l'utiliser
android.support.v8.renderscript
avec les outils de build actuels ( syntaxe mise à jour pour le plugin Android Gradle v14 + )Benchmark simple sur un Nexus 5 - comparaison de RenderScript avec différentes autres implémentations java et Renderscript:
Le temps d'exécution moyen par flou sur différentes tailles de photo
Mégapixels par seconde qui peuvent être flous
Chaque valeur est la moyenne de 250 tours.
RS_GAUSS_FAST
estScriptIntrinsicBlur
(et presque toujours le plus rapide), les autres qui commencent parRS_
sont pour la plupart des implémentations convolves avec des noyaux simples. Les détails des algorithmes peuvent être trouvés ici . Ce n'est pas purement flou, car une bonne partie est le ramassage des ordures qui est mesuré. Cela peut être vu ici (ScriptIntrinsicBlur
sur une image 100x100 avec environ 500 tours)Les pointes sont gc.
Vous pouvez vérifier par vous-même, l'application de référence est dans le Playstore: BlurBenchmark
Réutilise Bitmap dans la mesure du possible (si prio: performances> empreinte mémoire)
Si vous avez besoin de plusieurs flous pour un flou en direct ou similaire et que votre mémoire le permet, ne chargez pas le bitmap à partir de drawables plusieurs fois, mais gardez-le "mis en cache" dans une variable membre. Dans ce cas, essayez toujours d'utiliser les mêmes variables, pour réduire au minimum la récupération de place.
Découvrez également la nouvelle
inBitmap
option lors du chargement partir d'un fichier ou d'un dessin qui réutilisera la mémoire bitmap et économisera le temps de récupération de place.Pour mélanger du net au flou
La méthode simple et naïve consiste simplement à utiliser 2
ImageViews
, un flou et un fondu alpha. Mais si vous voulez un look plus sophistiqué qui passe en douceur de net à flou, consultez l'article de Roman Nurik sur la façon de le faire comme dans son application Muzei. .Fondamentalement, il explique qu'il pré-floute certaines images avec différentes étendues de flou et les utilise comme images clés dans une animation qui semble vraiment fluide.
la source
renderscriptSupportModeEnabled true
ou il ne sera pas construit! J'ai cherché pour toujours!EDIT (avril 2014): Il s'agit d'une page de questions / réponses qui reçoit encore beaucoup de hits, semble-t-il. Je sais que je reçois toujours des votes pour ce message. Mais si vous lisez ceci, vous devez vous rendre compte que les réponses publiées ici (la mienne et la réponse acceptée) sont obsolètes. Si vous souhaitez implémenter un flou efficace aujourd'hui , vous devez utiliser RenderScript au lieu du NDK ou de Java. RenderScript fonctionne sur Android 2.2+ (en utilisant la bibliothèque de support Android ), il n'y a donc aucune raison de ne pas l'utiliser.
La vieille réponse suit, mais méfiez-vous car elle est obsolète.
Pour les futurs Googleurs, voici un algorithme que j'ai porté depuis le port de Yahel de l'algorithme de Quasimondo, mais en utilisant le NDK. C'est basé sur la réponse de Yahel, bien sûr. Mais cela exécute du code C natif, donc c'est plus rapide. Plus vite. Genre, 40 fois plus rapide.
Je trouve que l'utilisation du NDK est la façon dont toute la manipulation d'image doit être effectuée sur Android ... c'est un peu ennuyeux à mettre en œuvre au début (lisez un excellent tutoriel sur l'utilisation de JNI et du NDK ici ), mais bien mieux, et presque en temps réel pour un beaucoup de choses.
Pour référence, en utilisant la fonction Java de Yahel, il a fallu 10 secondes pour brouiller mon image de 480x532 pixels avec un rayon de flou de 10. Mais cela a pris 250ms en utilisant la version native C. Et je suis à peu près sûr que cela peut encore être optimisé ... Je viens de faire une conversion stupide du code java, il y a probablement des manipulations qui peuvent être raccourcies, je ne voulais pas passer trop de temps à refactoriser le tout.
Ensuite, utilisez-le comme ceci (en considérant une classe appelée com.insert.your.package.ClassName et une fonction native appelée functionToBlur, comme l'indique le code ci-dessus):
Il attend un bitmap RGB_8888!
Pour utiliser un bitmap RGB_565, créez une copie convertie avant de passer le paramètre (beurk), ou modifiez la fonction pour utiliser un nouveau
rgb565
type au lieu dergba
:Le problème est que si vous faites cela, vous ne pouvez plus lire
.red
,.green
et.blue
du pixel plus, vous devez lire l'octet correctement, duh. Quand j'en avais besoin avant, j'ai fait ceci:Mais il y a probablement une manière moins stupide de le faire. Je ne suis pas vraiment un codeur C de bas niveau, j'en ai peur.
la source
r[wh]
,g[wh]
etb[wh]
àuint8_t
.pastebin.com
Ce code fonctionne parfaitement pour moi
la source
Vous pouvez maintenant utiliser ScriptIntrinsicBlur de la bibliothèque RenderScript pour flouter rapidement. Voici comment accéder à l'API RenderScript. Voici une classe que j'ai créée pour brouiller les vues et les bitmaps:
la source
Cela a bien fonctionné pour moi: Comment flouter les images efficacement avec RenderScript d'Android
la source
Utilisez le script de rendu comme mentionné ici http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android/
la source
Ceci est pour toutes les personnes qui ont besoin d'augmenter le rayon de
ScriptIntrinsicBlur
pour obtenir un flou gaussien plus dur.Au lieu de mettre le rayon à plus de 25, vous pouvez réduire l'image et obtenir le même résultat. J'ai écrit une classe appelée
GaussianBlur
. Ci-dessous, vous pouvez voir comment utiliser et toute l'implémentation de la classe.Usage:
Classe:
la source
Merci @Yahel pour le code. Publier la même méthode avec la prise en charge du flou du canal alpha car il m'a fallu un certain temps pour la faire fonctionner correctement, ce qui peut faire gagner du temps à quelqu'un:
la source
J'ai utilisé ça avant ..
la source
Pour les futurs Googleurs qui choisissent l'approche NDK - je trouve un algorithme de stackblur fiable. J'ai trouvé ici une implémentation C ++ qui ne repose pas sur SSE - http://www.antigrain.com/__code/include/agg_blur.h.html#stack_blur_rgba32 qui contient quelques optimisations utilisant des tables statiques comme:
J'ai modifié l'algorithme stackblur pour les systèmes multi-core - il peut être trouvé ici http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ Comme de plus en plus d'appareils ont 4 cœurs - les optimisations donnent Avantage de vitesse 4x.
la source
Conseils de Nicolas POMEPUY. Je pense que ce lien sera utile: effet de flou pour la conception Android
Exemple de projet sur github
la source
Nous avons essayé d'implémenter le flou RenderScript comme mentionné ci-dessus dans différentes réponses. Nous étions limités à utiliser la version v8 RenderScript et cela nous a causé beaucoup de problèmes.
Je veux partager notre version sale de Java uniquement qui est lente et devrait être effectuée sur un thread séparé et, si possible, avant utilisation et donc persistante.
Cette solution est loin d'être parfaite mais crée un effet de flou raisonnable basé sur le fait qu'elle dessine une version hautement transparente de la même image sur une version "nette" à peine transparente. L'alpha dépend de la distance à l'origine.
Vous pouvez ajuster certains «nombres magiques» à vos besoins. Je voulais juste partager cette "solution" pour tous ceux qui ont des problèmes avec la version de support v8 de RenderScript.
la source
Pour ceux qui ont encore des problèmes avec la bibliothèque de support Renderscript sur les chipsets x86, veuillez consulter cet article du créateur de la bibliothèque. Il semble que le correctif qu'il a préparé n'a pas réussi à atteindre les outils de construction v20.0.0, il fournit donc les fichiers pour le corriger manuellement et une brève explication sur la façon de le faire.
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
la source
du blog Mario Viviani, on peut utiliser cette solution à partir de la version 17 Android:
https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz
ou
https://gist.github.com/Mariuxtheone/903c35b4927c0df18cf8
la source
Voici une superposition de flou en temps réel utilisant RenderScript, qui semble être assez rapide.
https://github.com/mmin18/RealtimeBlurView
la source
J'ai trouvé qu'une diminution du contraste, de la luminosité et de la saturation rendait les images floues plus jolies.J'ai donc combiné diverses méthodes de débordement de pile et créé cette classe de flou qui traite des images floues, de la modification de la luminosité, de la saturation, du contraste et de la taille des images floues. Il peut également convertir des images de dessinables en bitmap et vice-versa.
la source
Lors des entrées / sorties 2019, la solution suivante a été présentée:
la source