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