filtre détection de contour méthode prewitt

Pour discuter de l'assembleur
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

filtre détection de contour méthode prewitt

Message par manababel »

Code : Tout sélectionner

EnableExplicit

Global Dim Reg_memory.q(4*344)

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected source_p , cible_p , s.q
  Protected lg.q , ht.q , taille.q , depth.q
  
  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
    
  StartDrawing(ImageOutput(nom))
  source_p = DrawingBuffer()
  ht = ImageHeight(nom)
  lg = ImageWidth(nom)
  Depth=OutputDepth()
  StopDrawing()
  
  If Depth=24
    taille=lg*ht
    cible_p=AllocateMemory(taille*4)
    Dim save.q(4)
    s=@save()
    EnableASM
      !mov rax,[p.v_s]
      !mov [rax],rcx
      !mov [rax+8],rdx
      !mov [rax+16],r8
      !mov rcx,[p.v_source_p]
      !mov rdx,[p.v_cible_p]
      !mov r8,[p.v_taille]
      !sub r8,1 ; <---------------- ????
      !copy_boucle24:
        !mov eax,[rcx]     
        !mov [rdx],eax
        !add rcx,3
        !add rdx,4
        !dec r8
       !jnz copy_boucle24
      !mov rax,[p.v_s] 
      !mov rcx,[rax]
      !mov rdx, [rax+8]
      !mov r8,[rax+16]
    DisableASM
    FreeArray(save())
    
    FreeImage(nom) ; supprime l'image 24bits
    CreateImage(nom,lg,ht,32) 
    StartDrawing(ImageOutput(nom))
    source_p = DrawingBuffer()
    StopDrawing()
    CopyMemory( cible_p , source_p , taille*4 )
    FreeMemory(cible_p)
  EndIf
  
  ProcedureReturn 1
EndProcedure




; partie du programme à modifier pour adapter se programme au votre
; convertie les "IDs" des images en pointer d'adresse
; test si les images sont en 32bits et de la meme taille
;-------------------------------------------------------------------

Macro sp(source,cible)
  Protected Depth.q , lg.q , ht.q , lg1.q , ht1.q , taille.q
  Protected cible_p.q , source_p.q
  
  StartDrawing(ImageOutput(cible))
  cible_p = DrawingBuffer()
  ht1 = ImageHeight(cible)
  lg1 = ImageWidth(cible)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
  
  StartDrawing(ImageOutput(source))
  source_p = DrawingBuffer()
  ht = ImageHeight(source)
  lg = ImageWidth(source)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
  
  If lg<>lg1 Or ht<>ht1 : ProcedureReturn : EndIf
  
  taille = lg * ht
EndMacro

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(pixel,r,g,b)
    r=(pixel & $ff0000)>>16
    g=(pixel & $ff00)>>8
    b=(pixel & $ff)
  EndMacro

;-------------------------------------------------------------------
; sauvegarde de registres
Macro Save_Reg()
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx ;
  !mov [rax+016],rdx ;
  !mov [rax+024],rsi
  !mov [rax+032],rdi
  !mov [rax+040],r8 ;
  !mov [rax+048],r9 ;
  !mov [rax+056],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15

  !movdqu [rax+104],xmm0 ;
  !movdqu [rax+120],xmm1 ;
  !movdqu [rax+136],xmm2 ;
  !movdqu [rax+152],xmm3 ;
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  DisableASM
EndMacro

Macro Rest_Reg()
; restore les registres
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rsi,[rax+024]
  !mov rdi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]

  !movdqu xmm0,[rax+104] ;
  !movdqu xmm1,[rax+120] ;
  !movdqu xmm2,[rax+136] ;
  !movdqu xmm3,[rax+152] ;
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  DisableASM

EndMacro
;-------------------------------------------------------------------

Procedure Filter_Prewitt_pb(source.q,cible.q,mul.l=1)
  Protected p , rgb 
  Protected r , g , b , r1,g1,b1 , r2,g2,b2 , r3,g3,b3 , r4,g4,b4 , r5,g5,b5 , r6,g6,b6 , r7,g7,b7 , r8,g8,b8 , r9,g9,b9
  Protected x , y , ry,gy,by , rx,gx,bx
  
  sp(source,cible)
  
  For y=1 To ht-2
    x=0
          p=source_p+((y-1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r1,g1,b1)
          p=source_p+((y-1)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r2,g2,b2)
          p=source_p+((y-0)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r4,g4,b4)     
          p=source_p+((y-0)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r5,g5,b5)
          p=source_p+((y+1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r7,g7,b7)
          p=source_p+((y+1)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r8,g8,b8)
          
        For x=2 To lg-2
         
          p=source_p+((y-1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r3,g3,b3)          
          p=source_p+((y-0)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r6,g6,b6)         
          p=source_p+((y+1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r9,g9,b9)         
          
          ry=(r1 + r2 + r3) -( r7 + r8 + r9)
          gy=(g1 + g2 + g3) -( g7 + g8 + g9)
          by=(b1 + b2 + b3) -( b7 + b8 + b9)
          
          rx=(r3 + r6 + r9)-(r1 + r4 + r7)
          gx=(g3 + g6 + g9)-(g1 + g4 + g7)
          bx=(b3 + b6 + b9)-(b1 + b4 + b7)
          
          r=((Abs(rx)+Abs(ry))*mul)
          g=((Abs(gx)+Abs(gy))*mul)
          b=((Abs(bx)+Abs(by))*mul)
          ClampRGB(r,g,b)
          rgb=r<<16+g<<8+b
          
          PokeL(cible_p+(lg*y+x)<<2,rgb)

          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

;-------------------------------------------------------------------


Procedure Filter_Prewitt_asm(source.q,cible.q,mul.l=1)
  Protected s.q
 
  sp(source,cible) 
  
  Save_Reg()
  EnableASM
  !mov r12,[p.v_source_p]
  !mov r11,[p.v_cible_p]
  !add r11,4
  !mov r15,[p.v_lg]
  !shl r15,2
  
  !pxor xmm0,xmm0
  
  !mov eax,[p.v_mul]
  !imul eax,$10101
  !movd xmm15,eax
  !punpcklbw xmm15,xmm0
  
  !xor rax,rax
  !mov eax,[p.v_ht]
  !mov r13,rax
  !sub r13,3
  !prewitt_boucle_y :
  
    !mov rsi,r12
    !mov rdi,r11
    !add r12,r15
    !add r11,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[p.v_lg]
    !mov r14,rax
    !sub r14,2

    !prewitt_boucle_x:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry1 = |r1|g1|b1|
      !paddsw xmm10,xmm2  ; ry1 = |r1+r2|g1+r2|b1+r2|
      !paddsw xmm10,xmm3  ; ry1 = |r1+r2+r3|g1+g2+g3|b1+b2+b3| 
      !movups xmm11,xmm7 ; ry2 = |r7|g7|b7|
      !paddsw xmm11,xmm8  ; ry2 = |r7+r8|g7+r8|b7+r8|
      !paddsw xmm11,xmm9  ; ry2 = |r7+r8+r9|g7+g8+g9|b7+b8+b9| 
      !psubsw xmm10,xmm11 ; ry = ry1 - ry2
      !pabsw xmm10,xmm10 ; ry = abs(ry)
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !paddsw xmm12,xmm6
      !paddsw xmm12,xmm9
      !movups xmm13,xmm1
      !paddsw xmm13,xmm4
      !paddsw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry)*mul)
      !pmullw xmm10,xmm15
      
      !packuswb xmm10,xmm0
      !movd [rdi],xmm10
      
      !add rdi,4
      !add rsi,4
  
      !movaps xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movaps xmm2,xmm3
      !movaps xmm4,xmm5
      !movaps xmm5,xmm6
      !movaps xmm7,xmm8
      !movaps xmm8,xmm9
      
      !sub r14,1
      !jnz prewitt_boucle_x
    !sub r13,1
    !jnz prewitt_boucle_y    
    DisableASM
  Rest_Reg()

  
EndProcedure
;-------------------------------------------------------------------

UseJPEGImageDecoder()
UsePNGImageDecoder()
Global imgx=1200
Global imgy=800


If OpenWindow(0, 0, 0, imgx, imgy, "Prewitt", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source.q , cible.q , t.q , file$ , i
  
   file$ = OpenFileRequester("Image","","",0)
   source=10
   cible=20
   
   If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
     MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
     End
   EndIf
   
   ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
   
   CreateImage(cible,imgx,imgy,32) ; l'image doit entre en mode 32bits
   
   t=ElapsedMilliseconds()
     Filter_Prewitt_asm(source,cible)  ; <= ramplacer par "Filter_Roberts_asm(source,cible)"
   t=ElapsedMilliseconds()-t
   
   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,0)
   DrawText(5,5,Str(t))
   StopDrawing()
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 EndIf
Dernière modification par manababel le dim. 17/janv./2021 17:51, modifié 1 fois.
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: filtre détection de contour méthode prewitt

Message par kernadec »

bsr manababel
Merci pour le partage de tous ces codes géométriques
Les filtres sont top sur certaines images avec des personnages cela donne
de jolis panneaux sculptés

juste une petite remarque peut être garder la largeur hauteur de l'image importée
et aussi ajouter a ces codes filtres un SaveFileRequester()

Image

filtre Prewitt

Image

filtre Roberts

Image

Cordialement
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre détection de contour méthode prewitt

Message par manababel »

J'essaie de faire des programmes simples à utiliser , et fonctionnelle sur la plupart des Pc ( au moins sous Windows 64 bits en ASM).
donc n'hésitez pas à le(s) modifier et à l'améliorer à votre convenance.

vous pouvez obtenir d'autres effets en mixant les filtres.
ex :
1_ flouter l'image
2-la passée en niveau de gris
3_detection de contour
4_faire un negatif
5_Aditionné l'image avec cette d'origine
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre détection de contour méthode prewitt

Message par manababel »

modification de la multiplication int('mul') en float('mul')
ajout du multi-thread en PB

Code : Tout sélectionner

EnableExplicit

CompilerIf #PB_Compiler_Thread = #False
   CompilerError "Enable Thread Safe mode!"
 CompilerEndIf
 
Global ndt_max=CountCPUs(#PB_System_ProcessCPUs )
Global ndt=ndt_max -1
If ndt < 1 : ndt = 1 :EndIf
Global Dim Thread(ndt_max+1)
Structure var
  source.q
  cible.q
  mul.f
  start.q
  stop.q
EndStructure
Global Dim param.var((ndt_max)*2+1)

Global Dim Reg_memory.q(4*344)

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected source_p , cible_p , s.q
  Protected lg.q , ht.q , taille.q , depth.q
  
  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
    
  StartDrawing(ImageOutput(nom))
  source_p = DrawingBuffer()
  ht = ImageHeight(nom)
  lg = ImageWidth(nom)
  Depth=OutputDepth()
  StopDrawing()
  
  If Depth=24
    taille=lg*ht
    cible_p=AllocateMemory(taille*4)
    Dim save.q(4)
    s=@save()
    EnableASM
      !mov rax,[p.v_s]
      !mov [rax],rcx
      !mov [rax+8],rdx
      !mov [rax+16],r8
      !mov rcx,[p.v_source_p]
      !mov rdx,[p.v_cible_p]
      !mov r8,[p.v_taille]
      !sub r8,1 ; <---------------- ????
      !copy_boucle24:
        !mov eax,[rcx]     
        !mov [rdx],eax
        !add rcx,3
        !add rdx,4
        !dec r8
       !jnz copy_boucle24
      !mov rax,[p.v_s] 
      !mov rcx,[rax]
      !mov rdx, [rax+8]
      !mov r8,[rax+16]
    DisableASM
    FreeArray(save())
    
    FreeImage(nom) ; supprime l'image 24bits
    CreateImage(nom,lg,ht,32) 
    StartDrawing(ImageOutput(nom))
    source_p = DrawingBuffer()
    StopDrawing()
    CopyMemory( cible_p , source_p , taille*4 )
    FreeMemory(cible_p)
  EndIf
  
  ProcedureReturn 1
EndProcedure




; partie du programme à modifier pour adapter se programme au votre
; convertie les "IDs" des images en pointer d'adresse
; test si les images sont en 32bits et de la meme taille
;-------------------------------------------------------------------

Macro sp(source,cible)
  Protected Depth.q , lg.q , ht.q , lg1.q , ht1.q , taille.q
  Protected cible_p.q , source_p.q
  
  StartDrawing(ImageOutput(cible))
  cible_p = DrawingBuffer()
  ht1 = ImageHeight(cible)
  lg1 = ImageWidth(cible)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
  
  StartDrawing(ImageOutput(source))
  source_p = DrawingBuffer()
  ht = ImageHeight(source)
  lg = ImageWidth(source)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
  
  If lg<>lg1 Or ht<>ht1 : ProcedureReturn : EndIf
  
  taille = lg * ht
EndMacro

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(pixel,r,g,b)
    r=(pixel & $ff0000)>>16
    g=(pixel & $ff00)>>8
    b=(pixel & $ff)
  EndMacro

;-------------------------------------------------------------------
; sauvegarde de registres
Macro Save_Reg()
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx ;
  !mov [rax+016],rdx ;
  !mov [rax+024],rsi
  !mov [rax+032],rdi
  !mov [rax+040],r8 ;
  !mov [rax+048],r9 ;
  !mov [rax+056],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15

  !movdqu [rax+104],xmm0 ;
  !movdqu [rax+120],xmm1 ;
  !movdqu [rax+136],xmm2 ;
  !movdqu [rax+152],xmm3 ;
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  DisableASM
EndMacro

Macro Rest_Reg()
; restore les registres
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rsi,[rax+024]
  !mov rdi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]

  !movdqu xmm0,[rax+104] ;
  !movdqu xmm1,[rax+120] ;
  !movdqu xmm2,[rax+136] ;
  !movdqu xmm3,[rax+152] ;
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  DisableASM

EndMacro
;-------------------------------------------------------------------

Procedure Filter_Prewitt_sp(i)

  Protected p , rgb 
  Protected r , g , b , r1,g1,b1 , r2,g2,b2 , r3,g3,b3 , r4,g4,b4 , r5,g5,b5 , r6,g6,b6 , r7,g7,b7 , r8,g8,b8 , r9,g9,b9
  Protected x , y , ry,gy,by , rx,gx,bx
  Protected source , cible, mul.f , start , stop
  
  source=param(i)\source
  cible=param(i)\cible
  mul=param(i)\mul
  start=param(i)\start
  stop=param(i)\stop
  
  sp(source,cible)
  
  If start = 0 : start =1 : EndIf
  If stop >=(ht-1) : stop= ht-2:EndIf
  For y=start To stop
    x=0
          p=source_p+((y-1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r1,g1,b1)
          p=source_p+((y-1)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r2,g2,b2)
          p=source_p+((y-0)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r4,g4,b4)     
          p=source_p+((y-0)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r5,g5,b5)
          p=source_p+((y+1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r7,g7,b7)
          p=source_p+((y+1)*lg+(x+1))<<2
          rgb=PeekL(p)
          returnRGB(rgb,r8,g8,b8)
          
        For x=2 To lg-2
         
          p=source_p+((y-1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r3,g3,b3)          
          p=source_p+((y-0)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r6,g6,b6)         
          p=source_p+((y+1)*lg+x)<<2
          rgb=PeekL(p)
          returnRGB(rgb,r9,g9,b9)         
          
          ry=(r1 + r2 + r3) -( r7 + r8 + r9)
          gy=(g1 + g2 + g3) -( g7 + g8 + g9)
          by=(b1 + b2 + b3) -( b7 + b8 + b9)
          
          rx=(r3 + r6 + r9)-(r1 + r4 + r7)
          gx=(g3 + g6 + g9)-(g1 + g4 + g7)
          bx=(b3 + b6 + b9)-(b1 + b4 + b7)
          
          r=((Abs(rx)+Abs(ry))*mul)
          g=((Abs(gx)+Abs(gy))*mul)
          b=((Abs(bx)+Abs(by))*mul)
          ClampRGB(r,g,b)
          rgb=r<<16+g<<8+b
          
          PokeL(cible_p+(lg*y+x)<<2,rgb)

          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

Procedure Filter_Prewitt_pb(source.q,cible.q,mul.f=1)
  
  Protected div , i
  
  sp(source,cible)
  div=ht/ndt
 
  For i=0 To ndt-1
    Param(i)\source=source
    Param(i)\cible=cible
    Param(i)\mul=mul
    Param(i)\start=i*div
    Param(i)\stop=(i*div)+div-1
    Thread(i)=CreateThread(@Filter_Prewitt_sp(),i)
  Next
  
  For i=0 To ndt-1
    If Thread(i) : WaitThread(thread(i)):EndIf
  Next
  
EndProcedure

;-------------------------------------------------------------------


Procedure Filter_Prewitt_asm(source.q,cible.q,mul.f=1)
  Protected s.q
 
  sp(source,cible) 
  
  Save_Reg()
  EnableASM
  !mov r12,[p.v_source_p]
  !mov r11,[p.v_cible_p]
  !add r11,4
  !mov r15,[p.v_lg]
  !shl r15,2
  
  !pxor xmm0,xmm0
  
  !VBROADCASTSS xmm15,[p.v_mul]

  !xor rax,rax
  !mov eax,[p.v_ht]
  !mov r13,rax
  !sub r13,3
  !prewitt_boucle_y :
  
    !mov rsi,r12
    !mov rdi,r11
    !add r12,r15
    !add r11,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[p.v_lg]
    !mov r14,rax
    !sub r14,2

    !prewitt_boucle_x:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry1 = |r1|g1|b1|
      !paddsw xmm10,xmm2  ; ry1 = |r1+r2|g1+r2|b1+r2|
      !paddsw xmm10,xmm3  ; ry1 = |r1+r2+r3|g1+g2+g3|b1+b2+b3| 
      !movups xmm11,xmm7 ; ry2 = |r7|g7|b7|
      !paddsw xmm11,xmm8  ; ry2 = |r7+r8|g7+r8|b7+r8|
      !paddsw xmm11,xmm9  ; ry2 = |r7+r8+r9|g7+g8+g9|b7+b8+b9| 
      !psubsw xmm10,xmm11 ; ry = ry1 - ry2
      !pabsw xmm10,xmm10 ; ry = abs(ry)
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !paddsw xmm12,xmm6
      !paddsw xmm12,xmm9
      !movups xmm13,xmm1
      !paddsw xmm13,xmm4
      !paddsw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry))
      
      !punpcklwd xmm10,xmm0 ; 16=>32bits
      !CVTDQ2PS xmm10,xmm10 ; float(x)
      !mulps xmm10,xmm15 ; 
      !CVTPS2DQ xmm10,xmm10 ; int(x)
      !packusdw xmm10,xmm0 ; 32=>16bits
      
      !packuswb xmm10,xmm0 ; 16=>8bits
      !movd [rdi],xmm10 ; pokel(xmm10)
      
      !add rdi,4
      !add rsi,4
  
      !movaps xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movaps xmm2,xmm3
      !movaps xmm4,xmm5
      !movaps xmm5,xmm6
      !movaps xmm7,xmm8
      !movaps xmm8,xmm9
      
      !sub r14,1
      !jnz prewitt_boucle_x
    !sub r13,1
    !jnz prewitt_boucle_y    
    DisableASM
  Rest_Reg()

  
EndProcedure
;-------------------------------------------------------------------

UseJPEGImageDecoder()
UsePNGImageDecoder()
Global imgx=1200
Global imgy=800

If OpenWindow(0, 0, 0, imgx, imgy, "Prewitt", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source.q , cible.q , t.q , file$ , i
  
   file$ = OpenFileRequester("Image","","",0)
   source=10
   cible=20
   
   If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
     MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
     End
   EndIf
   
   ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
   
   CreateImage(cible,imgx,imgy,32) ; l'image doit entre en mode 32bits
   
   t=ElapsedMilliseconds()
     Filter_Prewitt_pb(source,cible,1)  ; <= ramplacer par "Filter_Roberts_asm(source,cible)"
   t=ElapsedMilliseconds()-t
   
   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,0)
   DrawText(5,5,Str(t))
   StopDrawing()
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 EndIf
Dernière modification par manababel le dim. 17/janv./2021 17:51, modifié 1 fois.
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: filtre détection de contour méthode prewitt

Message par venom »

Bonjour manababel,

Bravo et merci pour le partage. Fonctionne bien chez moi.






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre