Recherche des contours d'une image

Partagez votre expérience de PureBasic avec les autres utilisateurs.
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Recherche des contours d'une image

Message par ATHOW »

Voila un algo pour rechercher les contours d'une image, utilisant quelques notions mathématiques.

(EDIT (nouvelle version) : les nombreux 'startDrawing()' ralentissaient beaucoup trop...)

Code : Tout sélectionner

; (c) 2007 - Guillaume HUSSON
; Recherche des contours d'une image par la mèthode du filtre de Roberts

UsePNGImageDecoder()
UsePNGImageEncoder()
UseJPEGImageDecoder()

; Le filtre de Roberts :
Global Dim roberts.b(2,2)


; l'image à traiter :
#IMAGE = 0
nom_fichier$ = OpenFileRequester("Choisissez une image","","Image|*.BMP;*.bmp;*.png;*PNG;*.jpeg;*.jpg;*.JPEG;*.JPG",0)

If Not nom_fichier$
  End
EndIf

LoadImage(#IMAGE,nom_fichier$)
Global width.l = ImageWidth(#IMAGE)
Global height.l = ImageHeight(#IMAGE)
Global Dim image_in.l(width,height)
StartDrawing(ImageOutput(#IMAGE))
For i.l=0 To width-1
  For j.l=0 To height-1
    image_in(i,j)=Point(i,j)
  Next j
Next i
StopDrawing()

; l'image résultat :
Global Dim image_out.l(width,height)

MessageRequester("Début de la procédure de recherche de contours", "Cliquez sur OK puis patientez jusqu'à la fin de la recherche de contour.", #MB_OK|#MB_ICONINFORMATION)

Procedure.d convolution(i.l,j.l)
  r.w = 0
  g.w = 0
  b.w = 0
  For k.b = 0 To 2
    For l.b = 0 To 2
      If (i+k-1 < width And j+l-1 < height And i+k-1>=0 And j+l-1>=0)
        c.l = image_in(i+k-1,j+l-1)
        r + Red(c)*roberts(k,l)
        g + Green(c)*roberts(k,l)
        b + Blue(c)*roberts(k,l)
      EndIf
    Next l
  Next k
  r = Abs(r)
  g = Abs(g)
  b = Abs(b)
  If(r>255)
    r=255
  EndIf
  If(g>255)
    g=255
  EndIf
  If(b>255)
    b=255
  EndIf
  ProcedureReturn RGB(r,g,b)
EndProcedure


For i.l=0 To width-1
  For j.l=0 To height-1
    ; initialisation : recherche des contours horizontaux, en premier lieu
    roberts(0,0) = 0
    roberts(0,1) = -1
    roberts(1,0) = 1
    roberts(1,1) = 0 
    convH.l = convolution(i,j)
    ; recherche des contours verticaux, en second
    roberts(0,0) = -1
    roberts(0,1) = 0
    roberts(1,0) = 0
    roberts(1,1) = 1 
    convV.l = convolution(i,j)
    
    rH.w = Red(convH)
    gH.w = Green(convH)
    bH.w = Blue(convH)
    
    rV.w = Red(convV)
    gV.w = Green(convV)
    bV.w = Blue(convV)
    
    r.w = Int(Sqr(rH*rH+rV*rV))
    g.w = Int(Sqr(gH*gH+gV*gV))
    b.w = Int(Sqr(bH*bH+bV*bV))
    
    If(r>255)
      r=255
    EndIf
    If(g>255)
      g=255
    EndIf
    If(b>255)
      b=255
    EndIf
    
    image_out(i,j) = RGB(255,255,255)-RGB(r,g,b)
    
  Next j
Next i

MessageRequester("Fin de la procédure de recherche de contours", "Vous pouvez maintenant sauvegarder votre nouvelle image ne contenant que les contours.", #MB_OK|#MB_ICONINFORMATION)

StartDrawing(ImageOutput(#IMAGE))
For i.l=0 To width-1
  For j.l=0 To height-1
    Plot(i,j,image_out(i,j))
  Next j
Next i
StopDrawing()

nom_fichier$ = SaveFileRequester("Sauvegardez votre image","","Image PNG|*.png;*PNG",0)
If(nom_fichier$)
  SaveImage(#IMAGE,nom_fichier$+".png",#PB_ImagePlugin_PNG)
EndIf

Voila, c'est une méthode parmi d'autres, ça a peut-être été déjà posté, mais si ça peut aider quelqu'un, ben tant mieux !

Un aperçu du résultat :

Avant :

Image

Après :

Image

EDIT : Un exemple plus parlant (quoique) et en couleur :

Avant :

Image

Après :

Image
Dernière modification par ATHOW le lun. 02/avr./2007 22:59, modifié 1 fois.
minirop
Messages : 321
Inscription : mer. 02/août/2006 21:06

Message par minirop »

j'ai pas trop mater le code, mais si j'ai bien compris, çà supprime les pixels qui sont de la même couleurs que ceux qui l'entoure.
11111
10001
10X01
10001
11111

le X à été supprimé.

pas mal.

edit : en effet c'est très long (en 10 sec j'en étais à (0,50) sur (799,599) )
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message par ATHOW »

minirop a écrit :j'ai pas trop mater le code, mais si j'ai bien compris, çà supprime les pixels qui sont de la même couleurs que ceux qui l'entoure.
11111
10001
10X01
10001
11111

le X à été supprimé.

pas mal.

edit : en effet c'est très long (en 10 sec j'en étais à (0,50) sur (799,599) )
C'est pas exactement ça, il y a quand même un lissage des traits pour obtenir des contours continus...
J'ai édité le premier post pour la version plus rapide.
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

Malin, cela peut servir quand les programmes graphiques normaux patinent :)
Dernière modification par Frenchy Pilou le mar. 03/avr./2007 12:00, modifié 1 fois.
Est beau ce qui plaît sans concept :)
Speedy Galerie
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

c'est peut être pas là que tu ton programme perd le plus de temps mais tu pourrais remplacer la commande point() part un pointeur...ça devrait déjà améliorer les choses.... :P
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

en tout cas ce listing est conservé sur mon Forum :D
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message par ATHOW »

Je me suis amusé à coder une mini appli (utilisant la recherche de contour) qui fait un effet crayonné sur les images.

http://kothsoftware.free.fr/effet_crayonne.zip
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

tu veux pas mettre le source ici ? :D
ThoT
Messages : 33
Inscription : mar. 20/mars/2007 17:51

Message par ThoT »

minirop a écrit :j'ai pas trop mater le code,
...par contre l'image d'exemple!!!.... 8)
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message par ATHOW »

Dobro a écrit :tu veux pas mettre le source ici ? :D
Bah, en fait j'ai codé un million de procédures (seuillage, baisse de l'opacité...) pour me rendre compte que le meilleur résultat était tout simplement une recherche de contour + un passage en niveau de gris.

Pour le passage en niveau de gris, j'ai utilisé la composante Y de chaque pixel : on récupère le r,g et b du pixel puis on calcule :

Code : Tout sélectionner

y.c = Int(0,299*r + 0,587*g + 0,114*b)
La couleur correspondant au pixel sera donc :

Code : Tout sélectionner

RGB(y,y,y)
Je pourrais mettre le code qu'une fois chez moi, vendredi normalement.
Coolman
Messages : 432
Inscription : sam. 01/janv./2005 16:07

Message par Coolman »

Impressionant, merci de partager le code :)
Pascal Vernie
Messages : 127
Inscription : mar. 15/mars/2005 16:37

Message par Pascal Vernie »

Félicitations résultat trés joli.
Pascal
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

Il serait plus judicieux d'incrémenter le nom des fichiers, car évidemment j'ai détourner ce prog en reprenant à chaque fois le résultat crayonné :lol:
Le problème c'est qu'on obtient un nom à rallonge impressionnant :)
Evidemment je pourrais changer le nom à chaque fois, mais bon c'est pas trop commode :)
Alors que si c'est incrémenté automatiquement c'est plus cool :D

Au bout de 6 ou 7 fois on obtient un truc qui ressemble aux "Turmites" :lol:

Image
Est beau ce qui plaît sans concept :)
Speedy Galerie
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message par ATHOW »

En fait il s'agit d'un projet en Java que je fais pour un cours de traitement d'image.
Je compte le porter en PureBasic au fur et à mesure, mais comme c'est pas ce qui me donnera une bonne note, je me focalise plus sur le Java en ce moment.

Avec un peu de patience, vous aurez une vraie appli en Pure, avec des menus et tout (et le code, bien sûr).
Mon but : arriver à un effet "encre de Chine" avec des hachures pour les zones d'ombre... ca va être chaud...
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

Si tu pouvais aller jusque là, cela serait super top! 8O
http://visgraph.cse.ust.hk/MoXi/

A l'impossible nul n'est tenu :)
Bon courage! 8)
Est beau ce qui plaît sans concept :)
Speedy Galerie
Répondre