The MASM Forum

Projects => Rarely Used Projects => RosAsm => Topic started by: guga on July 30, 2020, 04:42:38 AM

Title: Sobel Function
Post by: guga on July 30, 2020, 04:42:38 AM
new Sobel Function
Code: [Select]
`; Equates used  as flags to the type of fix we want onto the sobel operator.[SOBEL_FIX_TRUNCATE 0] ; Normal result. Only truncated all above the limits of -255 and 255[SOBEL_FIX_SIMPLE 1] ; common adjust of the edges. Much better.; Equates used on the matrix[FloatMatricesInt.M1Dis 0 FloatMatricesInt.M2Dis 4 FloatMatricesInt.M3Dis 8 FloatMatricesInt.M4Dis 12 FloatMatricesInt.M5Dis 16 FloatMatricesInt.M6Dis 20 FloatMatricesInt.M7Dis 24 FloatMatricesInt.M8Dis 28 FloatMatricesInt.M9Dis 32][Size_Of_FloatMatricesInt 36][Float_SobleVarG: R\$ 180.3122292025696187222153123367365]; 255/sqrt(2)) . This is a variable used to speed up the math when computing the G;;    SobelGetGPLusEx        Calculates the Sobel operator for a given amount of pixels stored opn a 3x3 matrix        Parameters:        pMatrix(In):    The Inputed pixels stored on a 3x3 matrix where the Sobel edges are calculated. The input values must be in Real4 format from 0 to 255. (No integer yet. I´ll adapt to handle integers later)                        To make easier understand, the matrix is written using equates and the values must be previously calculated and filled.                        The format of the matrix is:                                                M1 M2 M3                        M4 M5 M6                        M7 M8 M9                                                So, at Point M1, Pixel at pos X0, Y0                               Point M2, Pixel at pos X1, Y0                               Point M3, Pixel at pos X2, Y0                               Point M4, Pixel at pos X0, Y1                               Point M5, Pixel at pos X1, Y1                               Point M6, Pixel at pos X2, Y1                               Point M7, Pixel at pos X0, Y2                               Point M8, Pixel at pos X1, Y2                               Point M9, Pixel at pos X2, Y2        pOutSobelX(out): Pointer to a variable that will Store the SobelX value (Magnitude in X direction. I.e.: Gx).                         The stored value can be negative, positive or zero. All in Real4 format from -1 to 1        pOutSobelY(out): Pointer to a variable that will Store the SobelY value (Magnitude in Y direction. I.e.: Gy).                        The stored value can be negative, positive or zero. All in Real4 format from -1 to 1        pOutSobel(Out): Pointer to a variable that will Store the Sobel value (Total Magnitude of the pixel. I.e.: G).                        The output is a positive Integer value from 0 to 255. The magnitude of Sobel operator is given by:                            G = sqrt(Gx^2+Gy^2)        FixType(In):    A flag able to fix the Sobel operator when it exceeds the limits of -1 to 1 (Normalized)                        It´s common to the Sobel Operator extrapolates the resultant limits (-255 to 255. Or -1 to 1, normalized)                        We can see values (unormalized) in the order of -600, 482, 265, -258, -780 etc etc                                                Currently, in order to fix that 2 Flags can be used:                                                SOBEL_FIX_TRUNCATE (Value = 0). Simply truncates the values of Gx and Gy to -1 (if the result is too dark) or 1 (If the result is too bright)                        SOBEL_FIX_SIMPLE  (Value = 1). Fix the values adjusting the extrapolation to it stays within the limits.                                                       The math envolving is this fix is: FixedValue = OldValue/(255*(floor(|OldValue|/255)+1))                                pDegree(Out/Optional): A Pointer to a variable to store the Angle formed by the pixel. Sobel Operator can be used to calculate the angle (direction) of the Pixel.                               It outputs the angle in Degrees. The format of the output is always in real4 format from 0º to 360º.                               This parameter can be &NULL if you don´t want to exprt the angle.        Return Values:                    The function does not return any value.    Example of usage:    [MyMatrix: F\$ 25, 200, 30                  100, 45, 75                  0, 81, 255]        call SobelGetGPlusEx MyMatrix, MySobelX, MySobelY, MySobel, SOBEL_FIX_SIMPLE, &NULL    ;;Proc SobelGetGPLusEx:    Arguments @pMatrix, @pOutSobelX, @pOutSobelY, @pOutSobel, @FixType, @pDegree    Local @pReturn, @DataCheck, @Divisor, @FractionX, @FractionY, @Floor, @YAxis, @XAxis    Structure @TempAxis 16, @SobelYAxisDis 0, @SobelXAxisDis 8    Uses edi, edx, ecx, eax    finit    mov edi D@pMatrix    ; To calculate Gx^2 later. Therefore Gx = M3+M9 + 2*(M6-M4) - (M7+M1)    fld F\$edi+FloatMatricesInt.M6Dis | fsub F\$edi+FloatMatricesInt.M4Dis | fmul R\$Float_Two    fadd F\$edi+FloatMatricesInt.M3Dis | fadd F\$edi+FloatMatricesInt.M9Dis    fsub F\$edi+FloatMatricesInt.M7Dis | fsub F\$edi+FloatMatricesInt.M1Dis    lea ecx D@DataCheck | fistp F\$ecx    .If D@DataCheck = 0        fldz | fstp F@FractionX    .Else_If D@DataCheck <s 0-255 ; Blacks. Edge too dark.        If D@FixType = SOBEL_FIX_TRUNCATE ;  Truncate the value to -1. The default Sobel behaviour (It truncates to -255 or 255. But, since we are using normalized version we set the limits to -1 and 1)            fld R\$Float_MinusOne | fstp F@FractionX        Else ; SOBEL_FIX_SIMPLE. FixedValue = OldValue/(255*(floor(|OldValue|/255)+1))            xor edx edx | mov ecx 255 | mov eax D@DataCheck | neg eax | div ecx | inc eax | imul eax 255 | mov D@Divisor eax            fild D@DataCheck | fidiv F@Divisor |  fstp F@FractionX        End_If    .Else_If D@DataCheck >s 255 ; Whites. Edge too brigth.        If D@FixType = SOBEL_FIX_TRUNCATE ;  Truncate the value to -1. The default Sobel behaviour (It truncates to -255 or 255. But, since we are using normalized version we set the limits to -1 and 1)            fld1 | fstp F@FractionX        Else ;  SOBEL_FIX_SIMPLE. FixedValue = OldValue/(255*(floor(OldValue/255)+1))            xor edx edx | mov ecx 255 | mov eax D@DataCheck | div ecx | inc eax | imul eax 255 | mov D@Divisor eax            fild D@DataCheck | fidiv F@Divisor |  fstp F@FractionX        End_If    .Else        fild D@DataCheck | fmul R\$Float_One_255 | fstp F@FractionX    .End_If    mov eax D@pOutSobelX | mov ecx D@FractionX | mov D\$eax ecx    ; To calculate Gy^2 later. Therefore Gy = M7+M9 + 2*(M8-M2) - (M3+M1)    fld F\$edi+FloatMatricesInt.M8Dis | fsub F\$edi+FloatMatricesInt.M2Dis | fmul R\$Float_Two    fadd F\$edi+FloatMatricesInt.M7Dis | fadd F\$edi+FloatMatricesInt.M9Dis    fsub F\$edi+FloatMatricesInt.M3Dis | fsub F\$edi+FloatMatricesInt.M1Dis    lea ecx D@DataCheck | fistp F\$ecx    .If D@DataCheck = 0        fldz | fstp F@FractionY    .Else_If D@DataCheck <s 0-255 ; Blacks. Edge too dark. FixedValue = OldValue/(255*(floor(|OldValue|/255)+1))        If D@FixType = SOBEL_FIX_TRUNCATE ;  Truncate the value to -1. The default Sobel behaviour (It truncates to -255 or 255. But, since we are using normalized version we set the limits to -1 and 1)            fld R\$Float_MinusOne | fstp F@FractionY        Else ; SOBEL_FIX_SIMPLE ;  FixedValue = OldValue/(255*(floor(|OldValue|/255)+1))            xor edx edx | mov ecx 255 | mov eax D@DataCheck | neg eax | div ecx | inc eax | imul eax 255 | mov D@Divisor eax            fild D@DataCheck | fidiv F@Divisor |  fstp F@FractionY        End_If    .Else_If D@DataCheck >s 255 ; Whites. Edge too brigth. FixedValue = OldValue/(255*(floor(OldValue/255)+1))        If D@FixType = SOBEL_FIX_TRUNCATE ;  Truncate the value to -1. The default Sobel behaviour (It truncates to -255 or 255. But, since we are using normalized version we set the limits to -1 and 1)            fld1 | fstp F@FractionY        Else ; SOBEL_FIX_SIMPLE;  FixedValue = OldValue/(255*(floor(OldValue/255)+1))            xor edx edx | mov ecx 255 | mov eax D@DataCheck | div ecx | inc eax | imul eax 255 | mov D@Divisor eax            fild D@DataCheck | fidiv F@Divisor |  fstp F@FractionY        End_If    .Else        fild D@DataCheck | fmul R\$Float_One_255 | fstp F@FractionY    .End_If    mov eax D@pOutSobelY | mov ecx D@FractionY | mov D\$eax ecx    ; Output the Angle (in degrees) if needed    If D@pDegree <> 0        lea eax D@SobelYAxisDis | fld F@FractionY | fstp R\$eax        lea edx D@SobelXAxisDis | fld F@FractionX | fstp R\$edx        call atan2 eax, edx, &True        mov eax D@pDegree | fstp F\$eax    End_If    ; And finally create the Sobel G after Gx and Gy are already fixed    ; Soble = sqrt((255*FractionX)^2+(255*FractionY)^2)) = G = sqrt(Gx^2+Gy^2)    ; since FractionX and FractionY can have a maximum of 1 and -1, therefore sobleMax = (255/sqrt(2)) * sqrt(FractionX^2+FractionY^2)    fld F@FractionX | fmul ST0 ST0 | fld F@FractionY | fmul ST0 ST0 | faddp ST1 ST0 | fsqrt | fmul R\$Float_SobleVarG    lea edx D@pReturn    fistp F\$edx    mov eax D@pReturn    If eax > 255        mov eax 255    End_If    mov ecx D@pOutSobel | mov D\$ecx eaxEndP`
Atan function used:
Code: [Select]
`[Float_AtanPiFactor: R\$ (180/3.1415926535897932384626433832795)][Float360: R\$ 360]; Macros used to simulate If/Else/EndIf using Fpu[Fpu_If | fld #3 | fld #1 | fcompp | fstsw ax | fwait | sahf | jn#2 R0>>][Fpu_Else_If | jmp R5>> | R0: | fld #3 | fld #1 | fcompp | fstsw ax | fwait | sahf | jn#2 R0>>][Fpu_Else | jmp R5>> | R0:][Fpu_End_If | R0: | R5:]Proc atan2:    Arguments @pY, @pX, @ConvDegree    Structure @TempStorage 16, @HueDis 0    Uses eax, ebx, ecx    mov ebx D@pY    mov ecx D@pX    fld R\$ebx    fld R\$ecx    fpatan    fstsw ax    wait    shr ax 1    jnb L2>        fclex | stc | xor eax eax | ExitPL2:    .If D@ConvDegree = &TRUE        fmul R\$Float_AtanPiFactor | fst R@HueDis        Fpu_If R@HueDis < R\$FloatZero            fadd R\$Float360        Fpu_Else_If R@HueDis >= R\$Float360            fsub R\$Float360        Fpu_End_If    .End_If    clc    mov eax &TRUEEndP`