Filtre de convolution3x3

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

Filtre de convolution3x3

Message par manababel »

bonjour
voici un filtre de convolution de noyau 3x3
il est multi-thread et utilise des nombres flottants
les pixels du bord de l'image ne sont pas traités

Code : Tout sélectionner

;-------------------------------------------------------------------
Global Dim Filter_convolution3x3_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_convolution3x3_set(v1,v2.f)
  If v1<0 Or v1>10 : ProcedureReturn : EndIf
  Filter_convolution3x3_tab(v1) = v2
EndProcedure

; programme principal
Procedure Filter_convolution3x3_thread(i)
  
  Protected x.l , y.l , pixel.l
  Protected r.f , r1.f , r2.f , r3.f , r4.f , r5.f , r6.f , r7.f , r8.f , r9.f
  Protected g.f , g1.f , g2.f , g3.f , g4.f , g5.f , g6.f , g7.f , g8.f , g9.f
  Protected b.f , b1.f , b2.f , b3.f , b4.f , b5.f , b6.f , b7.f , b8.f , b9.f
  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) - 2 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-2 : EndIf
  If start < 1 : start = 1 : EndIf  
  
  dif.f = 1 / Filter_convolution3x3_tab(9)
  For y=start To stop
    returnRGB(((y-1)*lg4) , 1)
    returnRGB(((y-1)*lg4)+4,2)
    returnRGB(((y-0)*lg4) , 4)   
    returnRGB(((y-0)*lg4)+4,5) 
    returnRGB(((y+1)*lg4) , 7)          
    returnRGB(((y+1)*lg4)+4,8)          
    For x=2 To lg-1
      returnRGB(((((y-1)*lg)+x)*4) , 3) 
      returnRGB(((((y-0)*lg)+x)*4) , 6)      
      returnRGB(((((y+1)*lg)+x)*4) , 9)
      ri=(r1*Filter_convolution3x3_tab(0)+r2*Filter_convolution3x3_tab(1)+r3*Filter_convolution3x3_tab(2)+r4*Filter_convolution3x3_tab(3)+r5*Filter_convolution3x3_tab(4)+r6*Filter_convolution3x3_tab(5)+r7*Filter_convolution3x3_tab(6)+r8*Filter_convolution3x3_tab(7)+r9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
      gi=(g1*Filter_convolution3x3_tab(0)+g2*Filter_convolution3x3_tab(1)+g3*Filter_convolution3x3_tab(2)+g4*Filter_convolution3x3_tab(3)+g5*Filter_convolution3x3_tab(4)+g6*Filter_convolution3x3_tab(5)+g7*Filter_convolution3x3_tab(6)+g8*Filter_convolution3x3_tab(7)+g9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
      bi=(b1*Filter_convolution3x3_tab(0)+b2*Filter_convolution3x3_tab(1)+b3*Filter_convolution3x3_tab(2)+b4*Filter_convolution3x3_tab(3)+b5*Filter_convolution3x3_tab(4)+b6*Filter_convolution3x3_tab(5)+b7*Filter_convolution3x3_tab(6)+b8*Filter_convolution3x3_tab(7)+b9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
      ClampRGB(ri,gi,bi)
      PokeL(cible_p+(y*lg*4)+(x-1)*4,(ri<<16+gi<<8+bi))
      r1=r2:r2=r3:r4=r5:r5=r6:r7=r8:r8=r9
      g1=g2:g2=g3:g4=g5:g5=g6:g7=g8:g8=g9
      b1=b2:b2=b3:b4=b5:b5=b6:b7=b8:b8=b9
    Next
  Next
 
EndProcedure

;-------------------------------------------------------------------  
;gestion des threads
Procedure Filter_convolution3x3(Filter_convolution3x3_source,Filter_convolution3x3_cible)
  
  If Filter_convolution3x3_cible = 0 Or Filter_convolution3x3_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_convolution3x3_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_convolution3x3_source)
  ht = ImageHeight(Filter_convolution3x3_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_convolution3x3_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_convolution3x3_tab(9) = 0 : Filter_convolution3x3_tab(9) = 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_convolution3x3_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 2
      For x = 0 To 2
        pos = 10+y*3+x
        StringGadget(pos , x*40,y*20,39,19,"")
        Read.f a.f
        SetGadgetText(pos,Str(a))
      Next
    Next
    StringGadget(19 , 130,10,39,19,"")
    Read.f a.f : SetGadgetText(19,Str(a))
    StringGadget(20 , 130,30,39,19,"")
    Read.f a.f : SetGadgetText(20,Str(a))

  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10 To 20
            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,80) : 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 10
          t$=GetGadgetText(i+10)
          b.f = ValD(t$)
          Filter_convolution3x3_set(i,b)
        Next
        
        t=ElapsedMilliseconds()
        Filter_convolution3x3(source,cible)

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

  CloseWindow(0)

EndIf

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

Re: Filtre de convolution3x3

Message par threedslider »

Merci de ton code cela marche bien !
Répondre