Squelettiser une image en AS3
Le mardi 12 août 2008 à 01:40 :: Flash-AS3 :: #47 :: rss :: 3049 lectures
ça fait quelques mois que je m'intéresse aux opérateurs morphomathématiques.
en actionscript on en trouve pas tant, peut être parce que les temps de traitement sont trop longs pour faire ce à quoi ils servent d'habitude genre de la reconnaissance de motifs (visage, lettrages etc.), du component labelling (isoler des plages de couleur, tracker des trucs), recréer des structures en imagerie médicale j'en passe (beaucoup).
pas de head tracking ni de reconnaissance faciale dans ce post, parcontre un petit algo de skeletonization qui rend de bien jolies images.
le mieux c'est de mater ça :
http://homepages.inf.ed.ac.uk/rbf/HIPR2/morops.htm
bon, HIPR2 est une librairie en java, et java c'ets bien pour flash d'autant qu'ils expliquent tout bien et qu'il y a des exemples.
je me suis intéressé à la skeletonization car je voulais faire un distance Transform en fait.
un DT c'est, en partant de ça:

tu obtiens ça:

sexy hein?!
avec une skeletonization tu obtien(dras) ça:

bon le fonctionnement vite fait:
en gros on effectue X passes sur une image en lourdant les pixels qui ne font pas partie de la structure jusqu'à ce qu'on puisse plus rien virer.
pour savoir si c'est la structure ou merde, on utilise plusieurs kernels (des petites matrices de 3*3) qu'on rotate / compare à l'image existante pour savoir si on dégage le pixel ou si on le garde.
du coup je suis parti sur leur algo... mauvaise pioche!
basé sur du hitMiss il est trèèèès gourmand.
je l'ai optimisé tant que faire se pouvait. j'ai remplacé le traitement à même le bitmapData par un traitement sur un tableau 2D, puis linéaire avant de faire le traitement cash bourrin sur une String.
ça allait beaucoup mieux ( -70% de temps de traitement ) mais je me suis demandé si ça irait pas plus vite d'indexer des int dans untableau sachant que des int ne sont au fond que des 0 et des 1. donc j'ai posé la question sur MB : http://flash.mediabox.fr/index.php?showtopic=87210
suivant les conseils d'hubeert, je me suis collé à une version int de l'algo, j'ai flingué mon samedi dernier pour gagner 20% de perfs ce qui est nul.
demo

l'image vient de : http://www.flickr.com/photos/legohaulic/
très bon ^^
quand je dis perfs, vla le log pour l'image de ci dessus :
image: w 500 h 375
passe n° 1 : 3035 ms
passe n° 2 : 2769 ms
...
passe n° 25 : 931 ms
...
passe n° 55 : 291 ms
total: 61850 ms 55 passes
54 passes en 60 secondes : c'est pas rien.
et le résultat:
le travail est soigné, on obtiens exactement l'image du squelette, mais bon, c'est juste pas exploitable quoi.
pour les furieux qui veulent le voir en vrai, ici une version 'allégée' avec un bitmap rescalé à 20% de la taille d'affichage: lien
tibibi parle quant à lui d'un algo que j'avais trouvé dans un bouquin que je recommande à tout le monde sans pouvoir l'appliquer parce que je suis trop mauvais: hilditch
donc là on n'a qu'une passe à 2 kernels ( contre 8 passes à un kernel pour l'autre ) par itération.
parcontre (tout à un prix) certains patterns disparaissent et pas des moindres : les diagonales de 2 pixels et les carrés (cf. bas de page).
je suis pas sûr de l'avoir bien porté car on est vraiment censés conserver des lignes continues. ce sont les ocnditions A(p2)!= 1 et A(p4)!= 1 qui merdent.
pour le gain de perfs, c'est presque rigolo.
vla le log pour la même image avec l'algo de Hilditch:
image: w 500 h 375
passe n°: 0 : 108 ms
passe n°: 1 : 49 ms
...
passe n°: 55 : 24 ms
total: 4940 55 passes
5 secondes: ça calme hein?! 
ok c'est cracra mais c'est exploitable (un peu)
tout dépend de ce qu'on veut en faire bien sûr mais tel quel pour un output graphique, c'est parfait ^^
du coup on peut même foutre une démo en live avec en prime le gradient morphologique :D (clickes sur youpi en haut à gauche)
sources les 2 premières marchent ensemble
après il aime pas trop les grandes régions (comme ci dessus). il préfère plein de petites. ça paraît logique mais l'algo 1 n'aimait personne.
bon et qu'est ce qu'on fait avec ce script prodigieux ?
perso j'ai ma petite idée mais en gros on obtient des points clé de l'image ; la structure, ça peut servir.
1 - par exemple pour faire un squelette, vous n'êtes pas sans savoir que la V10 du player amènera un petit outil sympa appelé bones. on peut contrôler au runtime ceux qu'on a posé sur la scène.
et alors que se passe t'il si en plus on est cap' de savoir où les poser à partir de n'importe quelle image chargée au runtime ?
ben on s'apprête à envoyer du pâté humide sur pas mal de réseaux sociaux à base d'avatars customisés du slip aux moustaches.
2 - cette petite saloperie supporte très bien les redimensionnements. donc on peut calculer le squelette sur une image 10* plus petite et en normalisant les coordonnées, on retombe pile poil sur les points clés de l'original (pour peu qu'on n'aie pas trop altéré les éléments structurants de l'image).
3 - ça sert également à dénombrer les éléments d'une image. en filtrant intelligemment une image, en réduisant le bruit puis en seuillant, on peut isoler des objets: la technique
dans ce cas on aura plutôt besoin de celui d'au dessus que de hilditch mais gardez le rescaling en tête ;).
pour le reste je laisse libre cours à votre imagination.
copains
Commentaires
1. Le mercredi 20 août 2008 à 10:14, par jeanjean
Ajouter un commentaire