Filtre de convolution5x5

Programmation d'applications complexes
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Filtre de convolution5x5

Message par manababel »

voici un filtre de convolution de noyau 5x5
il est multi-thread et utilise des nombres flottants
les pixels du bord de l'image ne sont pas traités
utilisez des images de petites taille , cette version demande beaucoup de ressources au processeur ( ex: 512x512 max)

Code : Tout sélectionner

;-------------------------------------------------------------------
Global Dim Filter_convolution5x5_tab.f(11)
Global Dim param.i(6)
;-------------------------------------------------------------------


Macro clampRGB(r,g,b)
  If r<0:r=0:EndIf
  If g<0:g=0:EndIf
  If b<0:b=0:EndIf
  If r>255:r=255:EndIf
  If g>255:g=255:EndIf
  If b>255:b=255:EndIf
EndMacro

Macro returnRGB(p,var)
  pixel=PeekL(source_p + p)
  ri = (pixel & $ff0000)>>16
  gi = (pixel & $ff00)>>8
  bi = (pixel & $ff)
  r(var)=(ri)
  g(var)=(gi)
  b(var)=(bi)
EndMacro


Procedure Filter_convolution5x5_set(v1,v2.f)
  If v1<0 Or v1>26 : ProcedureReturn : EndIf
  Filter_convolution5x5_tab(v1) = v2
EndProcedure



; programme principal
Procedure Filter_convolution5x5_thread(i)
  
  Protected Dim r.f(25)
  Protected Dim g.f(25)
  Protected Dim b.f(25)
  Protected x.l , y.l , pixel.l
  Protected dif.f
  Protected ri.l , gi.l , bi.l
  Protected start.l,stop.l
  Protected source_p.i , cible_p.i , lg.l , ht.l , lg4.l
  
  source_p = param(0)
  cible_p = param(1)
  lg = param(3)
  ht = param(4)
  lg4= lg<<2
  
  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1) +2
  If i = (param(5) - 1) ; ndt
    If stop <= param(4) : stop = param(4) - 3 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-3 : EndIf
  If start < 2 : start = 2 : EndIf  
  
  dif.f = 1 / Filter_convolution5x5_tab(25)
  For y=start To stop
    
    For i=1 To 4
      returnRGB(((y-2)*lg4)+i*4 , i)
      returnRGB(((y-1)*lg4)+i*4 , i+6)
      returnRGB(((y-0)*lg4)+i*4 , i+11)
      returnRGB(((y+1)*lg4)+i*4 , i+16) 
      returnRGB(((y+2)*lg4)+i*4 , i+21)
    Next
    
    For x=4 To lg-1
      returnRGB(((((y-2)*lg)+x)*4) , 5) 
      returnRGB(((((y-1)*lg)+x)*4) , 10)      
      returnRGB(((((y+0)*lg)+x)*4) , 15)
      returnRGB(((((y+1)*lg)+x)*4) , 20)
      returnRGB(((((y+2)*lg)+x)*4) , 25)
      
      ri = 0 : gi = 0 : bi = 0
      For i=1 To 25
        ri = ri + r(i) * Filter_convolution5x5_tab(i-1)
        gi = gi + g(i) * Filter_convolution5x5_tab(i-1)
        bi = bi + b(i) * Filter_convolution5x5_tab(i-1)
        r(i) = r(i+1)
        g(i) = g(i+1)
        b(i) = b(i+1)
      Next
      ri = ri * dif + Filter_convolution5x5_tab(26)
      gi = gi * dif + Filter_convolution5x5_tab(26)
      bi = bi * dif + Filter_convolution5x5_tab(26)
      
      ClampRGB(ri,gi,bi)
      PokeL(cible_p+(y*lg*4)+(x-2)*4,(ri<<16+gi<<8+bi))

    Next
  Next
 
EndProcedure

;-------------------------------------------------------------------  
;gestion des threads
Procedure Filter_convolution5x5(Filter_convolution5x5_source,Filter_convolution5x5_cible)
  
  If Filter_convolution5x5_cible = 0 Or Filter_convolution5x5_source = 0 : ProcedureReturn : EndIf
  Protected thread.i , Psource.i , Pcible.i , Pmask , lg , ht , i 
  
  thread=CountCPUs(#PB_System_CPUs)
  If thread<2:thread=1:EndIf

  Protected Dim tr.i(thread)
  
  StartDrawing(ImageOutput(Filter_convolution5x5_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_convolution5x5_source)
  ht = ImageHeight(Filter_convolution5x5_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_convolution5x5_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_convolution5x5_tab(25) = 0 : Filter_convolution5x5_tab(25) = 0.0000001 :EndIf  ; pour eviter une division par 0

  param(0)=Psource
  param(1)=Pcible
  param(3)=lg
  param(4)=ht
  param(5)=thread
  
  For i=0 To thread-1 : tr(i)=0 : Next
  For i=0 To thread-1
    While tr(i)=0   
      tr(i)=CreateThread(@Filter_convolution5x5_thread(),i)
    Wend
  Next
  
  For i=0 To thread-1
    If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf 
  Next
  
  FreeArray(tr())
  
EndProcedure


;------------------------------------------------------------------
;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()


; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
  Protected lg.l , ht.l , depth.l , temps.i  , dif.l , dif1.l

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    CopyImage(nom,temps)
    FreeImage(nom)
    StartDrawing(ImageOutput(temps))
    temps_p = DrawingBuffer()
    lg = ImageWidth(temps)
    ht = ImageHeight(temps)
    dif = DrawingBufferPitch() - (lg*3)
    StopDrawing()
    
  
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    nom_p = DrawingBuffer()
    StopDrawing()
    
    For y=0 To ht-1
      For x=0 To lg-1
        i = ((y*lg)+x)*3
        r=PeekA(temps_p + i + 2 + dif1)
        g=PeekA(temps_p + i + 1 + dif1)
        b=PeekA(temps_p + i + 0 + dif1)
        PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
      Next
      dif1 = dif1 + dif
    Next
    
    FreeImage(temps) ; supprime l'image 24bits
    
  EndIf

  ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------

;-- programme test
If OpenWindow(0, 0, 0, 800, 800, "convolution3x3", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CreateMenu(0, WindowID(0))
    MenuTitle("Load")
    MenuItem( 1, "Load Image")
   MenuTitle("Save")   
    MenuItem( 2, "Save BMP")
    ;MenuItem( 3, "Save JPG")
    MenuItem( 4, "Save Clipboard")
  MenuTitle("Quit")
    MenuItem( 5, "Quit")
    
    Restore donnees
    For y = 0 To 4
      For x = 0 To 4
        pos = 10+y*5+x
        StringGadget(pos , x*40,y*20,39,19,"")
        Read.f a.f
        SetGadgetText(pos,Str(a))
      Next
    Next
    StringGadget(35 , 210,10,39,19,"")
    Read.f a.f : SetGadgetText(35,Str(a))
    StringGadget(36 , 210,30,39,19,"")
    Read.f a.f : SetGadgetText(36,Str(a))

  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10 To 36
            update = 1

        EndSelect
                
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            source = 2
            If IsImage(source) : FreeImage(source) : EndIf
            If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
            If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
            file$ = OpenFileRequester("Image","","",0)
            If Not Load_Image(source,file$)
              source = 0
              MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
            Else
              cible = 3
              If IsImage(cible) : FreeImage(cible) : EndIf
              CopyImage(source,cible)
              StartDrawing(WindowOutput(0))
              If IsImage(cible) : DrawImage(ImageID(cible),0,100) : EndIf
              StopDrawing()
              update = 1
           EndIf
          
          Case 2
            nom$ = SaveFileRequester("Save BMP", "", "", 0)
            If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf

          Case 4
            SetClipboardImage(cible)
            
          Case 5
            quit = 1
        
        EndSelect
      EndSelect
      
      If update = 1   
        Restore donnees
        For i=0 To 26
          t$=GetGadgetText(i+10)
          b.f = ValD(t$)
          Filter_convolution5x5_set(i,b)
        Next
        
        t=ElapsedMilliseconds()
        Filter_convolution5x5(source,cible)

        t=ElapsedMilliseconds() - t
        
        StartDrawing(WindowOutput(0))
        If IsImage(cible)
          DrawImage(ImageID(cible),0,100)
          ;DrawText(750,5,Str(t)+"     ")
        EndIf
        StopDrawing()
      EndIf
      
      
  Until Event = #PB_Event_CloseWindow Or quit=1

  CloseWindow(0)

EndIf

DataSection
  donnees:
  Data.f -2,-2,-2,-2,-2
  Data.f -2,-1,-1,-1, 2
  Data.f -2,-1, 5, 1, 2
  Data.f -2, 1, 1, 1, 2
  Data.f -2, 2, 2, 2, 2
  Data.f 1,0
EndDataSection
Avatar de l’utilisateur
threedslider
Messages : 455
Inscription : dim. 01/juil./2018 22:38

Re: Filtre de convolution5x5

Message par threedslider »

Merci encore pour le partage du code ;)
Ekim
Messages : 215
Inscription : dim. 24/juin/2018 1:20

Re: Filtre de convolution5x5

Message par Ekim »

Bonsoirs à tous)

l'impie que je suis me pousse à vous poser 2 questions, la 1ere, concerne le filtre dit "convolution", est ce un nom officiel et que cela représente?

la 2eme, concernant le traitement d'une image, afin de gagner du temps ainsi que de la ressource processeur, est il préférable de multi-threader son appli ou faut il plutôt créer des sous-applis pour répartir des différentes tâches ?

Merci)
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Filtre de convolution5x5

Message par Ar-S »

La 1ère je n'en sais rien du tout..
Et pour la seconde, j'ai envie de dire qu'il faut tester. Mais logiquement le multithread est justement fait pour éviter qu'il y ai à appeler des sous applis.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Ekim
Messages : 215
Inscription : dim. 24/juin/2018 1:20

Re: Filtre de convolution5x5

Message par Ekim »

Merci @Ar-S pour ton point de vue :D
Répondre