Re: Filtre graphique
Publié : mer. 27/avr./2022 13:54
filtre roberts
c'est un filtre détection de contours,ce n'est pas le plus efficace,mais l'un des plus rapides
il est preferable d'utiliser un filtre de floutage avant (boxblur) puis le filtre threshodl après ( Black&white)
Programme de test
c'est un filtre détection de contours,ce n'est pas le plus efficace,mais l'un des plus rapides
il est preferable d'utiliser un filtre de floutage avant (boxblur) puis le filtre threshodl après ( Black&white)
Code : Tout sélectionner
;*******************************************************************************
;Titre : Filter_Roberts
;Date : 27/04/2022
;Version PB : PureBasic 5.70 LTS
; x64 seulement
; Windows
; linux - non testé
; ios - non testé
;
;Info : ne fonctionne qu'avec des images 32bits ( source , cible et masque )
; "la fonction "load_image" convertis les images 24bits en 32bits"
;
; : "Global Dim param(256)" est a declarer dans le programme principal
;*******************************************************************************
; valeur min = 0
; valeur 'mediane' = 128
; valeur max = 255
;Filter_Roberts( source , cible , option )
;Filter_Roberts( source , cible , option , mask )
Procedure Filter_Roberts_thread(i)
Protected start,stop,p,s
p = @param()
start = ( param(4) / param(5) ) * i
stop = ( param(4) / param(5) ) * (i + 1)
If i = (param(5) - 1) ; ndt
If stop < param(4) : stop = param(4) - 1 : EndIf
EndIf
If stop > param(4)-1 : stop = param(4)-1 : EndIf
Protected Dim Reg_memory.q(13*8+ 6*16 ) ; (6 registes 64bits) + (4 registes 128bits)
s=@reg_memory() ; sauvegarde des registes
!mov rax,[p.v_s]
!mov [rax+000],rbx
!mov [rax+008],rcx
!mov [rax+016],rdx
!mov [rax+024],rdi
!mov [rax+032],rsi
!mov [rax+040],r8
!mov [rax+048],r9
!mov [rax+054],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
!mov rcx,[p.v_p]
!pxor xmm0,xmm0
!mov eax,[rcx+6*8] ; opt
!imul eax,$10101
!movd xmm5,eax
!punpcklbw xmm5,xmm0
!mov eax,[ecx+3*8] ; lg
!mov r10,rax
!dec r10 ; r10 = lg-1
!mov eax,[p.v_stop];[ecx+4*8] ; ht
!mov r11,rax
!mov r9,[p.v_start] ; ht
!mov eax,[ecx+3*8] ; lg
!mul r9
!shl rax,2
!mov r9,rax
!mov eax,[ecx+3*8] ; lg
!shl eax,2
!mov rsi,[rcx+00] ; source
!add rsi,r9
!mov rdi,rsi
!add rdi,rax
!mov rdx,[rcx+1*8] ; cible
!add rdx,r9
!mov r9,[p.v_start] ; ht
!robert_boucle_y:
!movd xmm1,[rsi]
!movd xmm3,[rdi]
!punpcklbw xmm1,xmm0
!punpcklbw xmm3,xmm0
!xor r8,r8
!robert_boucle_x:
!movd xmm2,[rsi+r8*4+4]
!movd xmm4,[rdi+r8*4+4]
!punpcklbw xmm2,xmm0
!punpcklbw xmm4,xmm0
!movq xmm10,xmm1 ; r=(Abs(Abs(rx)+Abs(ry))*Filter_Roberts_opt)
!psubsw xmm10,xmm4
!pabsw xmm10,xmm10 ; abs
!movq xmm11,xmm2 ;
!psubsw xmm11,xmm3
!pabsw xmm11,xmm11 ; abs
!paddsw xmm10,xmm11 ; x=((rx+ry)*opt)/128
!pmullw xmm10,xmm5
!psrlw xmm10,7
!packsswb xmm10,xmm0
!movd [rdx+r8*4],xmm10
!movq xmm1,xmm2 ;r1=r2
!movq xmm3,xmm4
!inc r8
!cmp r8,r10 ; cmp (lg-1)
!jb robert_boucle_x
!mov eax,[ecx+3*8] ; lg
!shl eax,2
!add rdx,rax
!add rsi,rax
!add rdi,rax
!inc r9
!cmp r9,r11 ; cmp (ht-1)
!jb robert_boucle_y
!mov rax,[p.v_s] ; restaurtion des registres
!mov rbx,[rax+000]
!mov rcx,[rax+008]
!mov rdx,[rax+016]
!mov rdi,[rax+024]
!mov rsi,[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]
FreeArray(Reg_memory())
EndProcedure
Procedure Filter_Roberts_mask_thread(i)
Protected start,stop,p,s
p = @param()
start = ( param(4) / param(5) ) * i
stop = ( param(4) / param(5) ) * (i + 1)
If i = (param(5) - 1) ; ndt
If stop < param(4) : stop = param(4) - 1 : EndIf
EndIf
If stop > param(4)-1 : stop = param(4)-1 : EndIf
Protected Dim Reg_memory.q(13*8+ 6*16 ) ; (6 registes 64bits) + (4 registes 128bits)
s=@reg_memory() ; sauvegarde des registes
!mov rax,[p.v_s]
!mov [rax+000],rbx
!mov [rax+008],rcx
!mov [rax+016],rdx
!mov [rax+024],rdi
!mov [rax+032],rsi
!mov [rax+040],r8
!mov [rax+048],r9
!mov [rax+054],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
!mov rcx,[p.v_p]
!pxor xmm0,xmm0
!mov eax,[rcx+6*8] ; opt
!imul eax,$10101
!movd xmm5,eax
!punpcklbw xmm5,xmm0
!mov eax,[ecx+3*8] ; lg
!mov r10,rax
!dec r10 ; r10 = lg-1
!mov r9,[p.v_start] ; ht
!mov eax,[ecx+3*8] ; lg
!mul r9
!shl rax,2
!mov r9,rax
!mov eax,[ecx+3*8] ; lg
!shl eax,2
!mov rsi,[rcx+00] ; source
!add rsi,r9
!mov rdi,rsi
!add rdi,rax
!mov rdx,[rcx+1*8] ; cible
!add rdx,r9
!mov r11,[rcx+2*8] ; mask
!add r11,r9
!mov r9,[p.v_start] ; ht
!robert_boucle_y2:
!movd xmm1,[rsi]
!movd xmm3,[rdi]
!punpcklbw xmm1,xmm0
!punpcklbw xmm3,xmm0
!xor r8,r8
!robert_boucle_x2:
!movd xmm2,[rsi+r8*4+4]
!movd xmm4,[rdi+r8*4+4]
!punpcklbw xmm2,xmm0
!punpcklbw xmm4,xmm0
!movq xmm10,xmm1 ; r=(Abs(Abs(rx)+Abs(ry))*Filter_Roberts_opt)
!psubsw xmm10,xmm4
!pabsw xmm10,xmm10 ; abs
!movq xmm11,xmm2 ;
!psubsw xmm11,xmm3
!pabsw xmm11,xmm11 ; abs
!paddsw xmm10,xmm11 ; x=((rx+ry)*opt)/128
!pmullw xmm10,xmm5
!psrlw xmm10,7
!packsswb xmm10,xmm0
!movd r13d,xmm10 ; calcul du mask
!mov r12d,[r11+r8*4] ; mask
!and r13d,r12d ; modification dans le mask
!xor r12d,$ffffffff
!mov r14d,[rsi+r8*4] ; source
!and r14d,r12d
!or r14d,r13d ; ajout de la partie hors du mask
!mov [rdx+r8*4],r14d
!movq xmm1,xmm2 ;r1=r2
!movq xmm3,xmm4
!inc r8
!cmp r8,r10 ; cmp (lg-1)
!jb robert_boucle_x2
!mov eax,[ecx+3*8] ; lg
!shl eax,2
!add rdx,rax
!add rsi,rax
!add rdi,rax
!add r11,rax
!mov rax,[p.v_stop]
;!dec rax
!inc r9
!cmp r9,rax ; cmp (ht-1)
!jb robert_boucle_y2
!mov rax,[p.v_s] ; restaurtion des registres
!mov rbx,[rax+000]
!mov rcx,[rax+008]
!mov rdx,[rax+016]
!mov rdi,[rax+024]
!mov rsi,[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]
FreeArray(Reg_memory())
EndProcedure
Procedure Filter_Roberts(Filter_Roberts_source,Filter_Roberts_cible,Filter_Roberts_opt=128,Filter_Roberts_mask=0)
If Filter_Roberts_cible = 0 Or Filter_Roberts_source = 0 : ProcedureReturn : EndIf
Protected thread , Psource , Pcible , Pmask , lg , ht , i
thread=CountCPUs(#PB_System_CPUs)
If thread<2:thread=1:EndIf
Protected Dim tr.q(thread)
StartDrawing(ImageOutput(Filter_Roberts_source))
Psource = DrawingBuffer()
lg = ImageWidth(Filter_Roberts_source)
ht = ImageHeight(Filter_Roberts_source)
StopDrawing()
StartDrawing(ImageOutput(Filter_Roberts_cible))
Pcible = DrawingBuffer()
StopDrawing()
If Filter_Roberts_mask <> 0
StartDrawing(ImageOutput(Filter_Roberts_mask))
Pmask = DrawingBuffer()
StopDrawing()
EndIf
param(0)=Psource
param(1)=Pcible
param(2)=Pmask
param(3)=lg
param(4)=ht
param(5)=thread
param(6)= Filter_Roberts_opt
For i=0 To thread-1 : tr(i)=0 : Next
For i=0 To thread-1
While tr(i)=0
If Filter_Roberts_mask = 0
tr(i)=CreateThread(@Filter_Roberts_thread(),i)
Else
tr(i)=CreateThread(@Filter_Roberts_mask_thread(),i)
EndIf
Wend
Next
For i=0 To thread-1
If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf
Next
FreeArray(tr())
EndProcedure
Code : Tout sélectionner
;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
Global Dim param(256)
;-- include files
IncludeFile "filtres\roberts.pbi"
; 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, "roberts", #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")
MenuTitle("mask")
MenuItem(6,"new mask")
TrackBarGadget(10, 10, 0, 512, 20, 0, 255 )
SetGadgetState(10, 128)
Repeat
update = 0
Event = WindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case 10
r = GetGadgetState(10)
update = 1
Case 11
g= GetGadgetState(11)
update = 1
Case 12
b = GetGadgetState(12)
update = 1
Case 13
r = GetGadgetState(13)
g=r : b=r
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,30) : EndIf
StopDrawing()
r = GetGadgetState(10)
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
Case 6
If source <> 0
StartDrawing(ImageOutput(source))
Psource = DrawingBuffer()
lg = ImageWidth(source)
ht = ImageHeight(source)
StopDrawing()
If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
mask = 4
CreateImage(mask,lg,ht,32)
StartDrawing(ImageOutput(mask))
Circle(lg/2,ht/2,ht/4,$ffffff)
Box(lg/8,ht/8,lg/6,ht/6,$ffffff)
StopDrawing()
r = GetGadgetState(10)
update = 1
EndIf
EndSelect
EndSelect
If update = 1
t=ElapsedMilliseconds()
Filter_Roberts(source,cible,r,mask)
t=ElapsedMilliseconds() - t
StartDrawing(WindowOutput(0))
If IsImage(cible)
DrawImage(ImageID(cible),0,30)
DrawText(750,5,Str(t)+" ")
EndIf
StopDrawing()
EndIf
Until Event = #PB_Event_CloseWindow Or quit=1
CloseWindow(0)
EndIf