How to optimize this code?
Posted: Fri Jul 21, 2023 7:51 pm
Hello,
I am currently checking out how different binarization algorithms work (and it's amazing, what you can do with a little afford). Currently I only implemented different greyscaling algorithms and a threshold given as absolute or relative (in percent) value. Next will be including histograms and some filters.
However, I initially planned to use a CustomFilterCallback, but this isn't possible, because I can't add more variables to the function (I need them to tell which algorithm to use). I could use a global variable, but then it won't be threadsafe.
So here's my question: Has anyone maybe an idea how to pass this additional variables to the callback function? Is this even better than including the code in the main function like I do now?
Code for reference (use a compiled version when testing the live function; may not work as expected with enabled desktop scaling):
Also, when I'm done, is there any interest to have it put Tips&Tricks? As I told before I am working for a company that processes PCBs and I am programming the machines that test them after printing and again after soldering. Binarization is the main key to find out whether the board is fine or not. This caught my interest and I'm trying to recreate the algorithms the software uses.
I am currently checking out how different binarization algorithms work (and it's amazing, what you can do with a little afford). Currently I only implemented different greyscaling algorithms and a threshold given as absolute or relative (in percent) value. Next will be including histograms and some filters.
However, I initially planned to use a CustomFilterCallback, but this isn't possible, because I can't add more variables to the function (I need them to tell which algorithm to use). I could use a global variable, but then it won't be threadsafe.
So here's my question: Has anyone maybe an idea how to pass this additional variables to the callback function? Is this even better than including the code in the main function like I do now?
Code for reference (use a compiled version when testing the live function; may not work as expected with enabled desktop scaling):
Code: Select all
Enumeration Binarization
#Bin_Alg_Relative
#Bin_Alg_Absolute
EndEnumeration
Enumeration PreBinarization
#Bin_Pre_BT709
#Bin_Pre_Equal
#Bin_Pre_REC601
#Bin_Pre_BT2100
#Bin_Pre_RedChannel
#Bin_Pre_GreenChannel
#Bin_Pre_BlueChannel
EndEnumeration
Procedure Binarize(Image.i,Border.a=50,Algorithm.a=#Bin_Alg_Relative,PreProcessing.a=#Bin_Pre_BT709)
Protected Result.i,x.l,y.l,Pixel.l,r.a,g.a,b.a,Res.a,Color.l
If IsImage(Image)
Result=CopyImage(Image,#PB_Any)
If Result
StartDrawing(ImageOutput(Result))
For x=0 To ImageWidth(Result)-1
For y=0 To ImageHeight(Result)-1
Pixel=Point(x,y)
r=Red(Pixel)
g=Green(Pixel)
b=Blue(Pixel)
Select PreProcessing
Case #Bin_Pre_BT709
Res=0.2126*r+0.7152*g+0.0722*b
Case #Bin_Pre_Equal
Res=(r+g+b)/3
Case #Bin_Pre_REC601
Res=0.299*r+0.587*g+0.114*b
Case #Bin_Pre_BT2100
Res=0.2627*r+0.678*g+0.0593*b
Case #Bin_Pre_RedChannel
Res=r
Case #Bin_Pre_GreenChannel
Res=g
Case #Bin_Pre_BlueChannel
Res=b
EndSelect
Select Algorithm
Case #Bin_Alg_Absolute
If Res>Border
Color=#White
Else
Color=#Black
EndIf
Case #Bin_Alg_Relative
If Res>Border*2.55
Color=#White
Else
Color=#Black
EndIf
EndSelect
Plot(x,y,Color)
Next
Next
StopDrawing()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Procedure LiveEvents()
If GetGadgetState(7)
If Bin And IsImage(Bin):FreeImage(Bin):EndIf
Bin=Binarize(0,Val(GetGadgetText(4)),GetGadgetState(2),GetGadgetState(1))
SetGadgetState(0,ImageID(Bin))
EndIf
EndProcedure
UseJPEGImageDecoder()
LoadImage(0,OpenFileRequester("Load file","","*.jpg",0))
If IsImage(0)
OpenWindow(0,0,0,ImageWidth(Bin)+200,ImageHeight(Bin)+20,"Binarization Test",#PB_Window_SystemMenu)
ImageGadget(0,10,10,WindowWidth(0),WindowHeight(0),ImageID(0))
ComboBoxGadget(1,GadgetWidth(0)+20,10,170,25)
ComboBoxGadget(2,GadgetWidth(0)+20,45,170,25)
TextGadget(3,GadgetWidth(0)+20,85,100,20,"Border:")
StringGadget(4,GadgetWidth(0)+120,80,70,25,"50",#PB_String_Numeric)
SetGadgetState(4,50)
SetGadgetText(4,"50")
ButtonGadget(5,GadgetWidth(0)+20,115,170,25,"Let's go!")
ButtonGadget(6,GadgetWidth(0)+20,150,170,25,"Original")
ButtonGadget(7,GadgetWidth(0)+20,185,170,25,"Go live!",#PB_Button_Toggle)
AddGadgetItem(1,-1,"BT709")
AddGadgetItem(1,-1,"Equal")
AddGadgetItem(1,-1,"REC601")
AddGadgetItem(1,-1,"BT2100")
AddGadgetItem(1,-1,"Red Channel")
AddGadgetItem(1,-1,"Green Channel")
AddGadgetItem(1,-1,"Blue Channel")
SetGadgetState(1,0)
AddGadgetItem(2,-1,"Relative")
AddGadgetItem(2,-1,"Absolute")
SetGadgetState(2,0)
BindGadgetEvent(1,@LiveEvents(),#PB_EventType_Change)
BindGadgetEvent(2,@LiveEvents(),#PB_EventType_Change)
BindGadgetEvent(4,@LiveEvents(),#PB_EventType_Change)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case 5;Do binarization
If Bin And IsImage(Bin):FreeImage(Bin):EndIf
Bin=Binarize(0,Val(GetGadgetText(4)),GetGadgetState(2),GetGadgetState(1))
SetGadgetState(0,ImageID(Bin))
Case 6;Revert to original image
SetGadgetState(0,ImageID(0))
Case 7;Live view
If GetGadgetState(7)
DisableGadget(5,#True)
If Bin And IsImage(Bin):FreeImage(Bin):EndIf
Bin=Binarize(0,Val(GetGadgetText(4)),GetGadgetState(2),GetGadgetState(1))
SetGadgetState(0,ImageID(Bin))
Else
DisableGadget(5,#False)
EndIf
EndSelect
EndSelect
ForEver
Else
MessageRequester("Error","Image could not be loaded!",#PB_MessageRequester_Error)
EndIf
CompilerEndIf