FloodFill étendu non récursif
bonjour
j'ai besoin d'un FloodFill un peu étendu par rapport à celui du GDI de Windaube
il faudrait notamment que je puisse paramètrer la fonction de comparaison des pixels, un test d'égalité stricte des couleurs n'étant pas suffisant, et sans utiliser une couleur de bordure (la limite de zone est marquée par un changement de couleur important, pas par une bordure au sens propre du mot)
c'est pour faire des trucs genre "magic wand" ...
je vois à peu près comment le faire en récursif en testant à chaque fois les 8 voisins de mon germe, mais sur des gros bitmaps avec de larges zones de couleurs semblables je risquerai certainement un débordement de pile, et le temps d'exécution risque d'être grand (?)
j'utilise Delphi
merci de votre aide
jlf
Re: FloodFill étendu non récursif
Citation:
Envoyé par jlf
j'ai besoin d'un FloodFill un peu étendu par rapport à celui du GDI de Windaube
Change d'OS si celui-ci ne te plaît pas. Quand c'est pas des critiques parceque c'est "trop assisté", c'est des critiques parceque ce n'est "pas assez assisté"... Jamais contents...
Citation:
Envoyé par jlf
il faudrait notamment que je puisse paramètrer la fonction de comparaison des pixels, un test d'égalité stricte des couleurs n'étant pas suffisant, et sans utiliser une couleur de bordure (la limite de zone est marquée par un changement de couleur important, pas par une bordure au sens propre du mot)
Effectue ton flood fill sur ton image, mais en comparant avec les pixels d'une dérivée de l'image, obtenue par application d'un filtre de gradient (ex : Sobel). C'est un détecteur de contours, la valeur des pixels obtenue correspond à la "force" de la transition de couleur. Il te suffit de calculer cette dérivée sur un bitmap caché (=en mémoire), car il n'est pas nécessaire de l'afficher. Ce n'est même pas nécessaire d'avoir un vrai bitmap, d'ailleurs : tu peux te contenter d'aller récupérer les pixels dans la propriété Scanline de ton TBitmap.
Citation:
Envoyé par jlf
je vois à peu près comment le faire en récursif en testant à chaque fois les 8 voisins de mon germe, mais sur des gros bitmaps avec de larges zones de couleurs semblables je risquerai certainement un débordement de pile, et le temps d'exécution risque d'être grand (?)
La méthode du germe, bien que "parfaite" d'un point de vue algo, est très lente. Et à 8 voisins, "fermer" la zone devient très difficile, étant donné que l'algo va pouvoir passer "au travers" d'une ligne à 45°... On n'utilise que 4 voisins, habituellement.
Perso, j'utilise plutôt un remplissage type raster :
1) Prendre un point d'origine.
2) Tracer au maximum à gauche jusqu'à la condition d'arrêt (quelle que soit cette condition d'arrêt).
3) Arrivé à l'arrêt, mémoriser la position du pixel.
4) Refaire la même manip à droite. Arrivé à la condition d'arrêt, tracer la ligne directement.
5) Propager le tracé en haut, puis en bas de l'origine.
6) Lorsque la propagation verticale s'arrête, continuer à droite et à gauche pour trouver les "trous" => tu vas obtenir deux lignes à tracer et non plus une seule, puis 3, 4, etc...
Tu saisis le principe ? Ca demande beaucoup, BEAUCOUP moins de mémoire que le floodfill classique, et c'est plus rapide à tracer.
Accessoirement, c'est l'algo de tracé du GDI, à l'opération de comparaison près... :twisted:
Bien sûr, il faut penser à chaque "butée" à propager dans les 4 directions, sinon les formes très concaves ne peuvent être remplies.
Une autre solution, assez élégante, consisterai à :
1) Dériver l'image.
2) Seuiller cette dérivée pour obtenir des zones "à remplir" (= sous un certain seuil, noir) et des zones "à éliminer" (=au dessus d'un certain seuil, blanc). Tu obtiens donc une image à 2 couleurs.
3) "Fermer" cette zone, avec un FloodFill GDI et une troisième couleur (ex : rouge) : tu vas donc avoir 3 couleurs :
- Rouge : Pixels sous le seuil, connexes avec l'origine du remplissage.
- Blanc : Pixels au dessus du seuil, à éliminer.
- Noir : Pixels sous le seuil, mais non-connexes, à éliminer aussi.
4) Tu convertis l'image en N&B de nouveau : rouge => noir, noir => blanc, blanc => blanc.
5) Tu obtiens un masque binaire, correspondant à ta "magic wand", à appliquer à ton image d'origine : une opération de copie de bitmap fera alors le reste, suivant ce que tu veux faire.
Cette méthode est normalement très rapide, car elle peut profiter d'un maximum d'accélération matérielle (FloodFill et copie/transferts de bitmaps).