Jump to content

KaFu

MVPs
  • Posts

    3,919
  • Joined

  • Last visited

  • Days Won

    15

KaFu last won the day on October 26 2024

KaFu had the most liked content!

About KaFu

Profile Information

  • Member Title
    Hey, it's just me, KhaFoo...
  • Location
    Germany, Hamburg
  • WWW
    https://funk.eu

Recent Profile Visitors

6,612 profile views

KaFu's Achievements

  1. He could check which desktop is active in a tight loop (or is there a notification mechanism for changes)? And then, depending on the desktop IDed, show or hide the window or change the style.
  2. Hi Jos, with each run of tidy the innermost 4 lines are intended by one more tab. I tested it with the latest Beta. Could you please take a look? #cs #cs 1) a 2) b 3) c 4) d #ce #ce Best Regards
  3. Hi @smbape, thanks a lot for this great UDF 😊! Finally a solution I got to work, that can perform face recognition and matching. I used your https://github.com/smbape/node-autoit-dlib-com?tab=readme-ov-file#running-examples guidance to set-up the environment and manually downloaded the two additional dlib-models required. #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; Dlib UDF by smbape ; https://www.autoitscript.com/forum/topic/207773-dlib-udf/ ; Dlib Face Recognition example by KaFu ; https://github.com/davisking/dlib/blob/v19.24/python_examples/face_recognition.py #include <Misc.au3> #include "..\autoit-dlib-com\udf\dlib_udf_utils.au3" ; sample - one of the faces from the example gallery picture "2007_007763.jpg" Local $a_128D_Face_Descriptor_of_Face_to_look_for[129] = [128, -0.091833, 0.0675418, 0.00142617, -0.0139504, -0.0903373, -0.0616875, -0.0384285, -0.14486, 0.0820726, -0.0852851, 0.17568, -0.0610356, -0.145164, -0.0266639, -0.0164959, 0.113634, -0.124758, -0.103387, -0.146446, -0.045612, 0.00516588, -9.29451E-05, 0.0863597, 0.0242456, -0.14534, -0.328905, -0.123818, -0.0685623, 0.0621051, 0.00807183, 0.0105838, 0.0424884, -0.254334, -0.118144, 0.0365846, 0.0897826, -0.0123099, -0.0522731, 0.226144, 0.0407339, -0.18469, 0.0978772, 0.049654, 0.260682, 0.230801, -0.0613484, 0.0384872, -0.0580775, 0.070347, -0.190347, 0.0539085, 0.122605, 0.136734, 0.0766652, -0.029859, -0.040169, 0.0905577, 0.16567, -0.184592, 0.0334291, 0.131489, -0.105992, -0.0602567, 0.043018, 0.142796, 0.110119, -0.086098, -0.164362, 0.0712913, -0.101671, -6.08778E-05, 0.0195526, -0.136251, -0.131349, -0.324134, 0.050356, 0.397348, 0.0955416, -0.193875, 0.0465133, -0.143481, 0.0191909, 0.0440991, 0.0355733, -0.0547336, -0.0449448, -0.105943, 0.0979393, 0.154901, -0.0282238, -0.0588183, 0.193323, 0.00501542, -0.0170646, 0.0698614, 0.130419, -0.161941, -0.0505242, -0.109364, -0.042785, 0.10326, -0.0566043, 0.0215982, 0.107899, -0.215276, 0.213152, -0.0453729, -0.00757293, 0.0653693, -0.0408494, -0.0396944, -0.00927441, 0.126415, -0.17009, 0.166003, 0.15904, -0.0532249, 0.13575, 0.138663, 0.0392869, -0.0467882, 0.0669965, -0.15721, -0.0904878, 0.0118087, 0.0483355, 0.100762, 0.0341779] _Dlib_Open(_Dlib_FindDLL("opencv_world4100*"), _Dlib_FindDLL("autoit_dlib_com-*-4100*")) OnAutoItExitRegister("_OnAutoItExit") Func _OnAutoItExit() _Dlib_Close() EndFunc ;==>_OnAutoItExit Local Const $o_Dlib = _Dlib_get() If Not IsObj($o_Dlib) Then Exit 356 Local $s_Data_Path_Predictor = @ScriptDir & "\data\shape_predictor_5_face_landmarks.dat" ; https://github.com/davisking/dlib-models/raw/master/shape_predictor_5_face_landmarks.dat.bz2 Local $s_Data_Path_Face_Rec_Model = @ScriptDir & "\data\dlib_face_recognition_resnet_model_v1.dat" ; https://github.com/davisking/dlib-models/raw/master/dlib_face_recognition_resnet_model_v1.dat.bz2 ; Load all the models we need: a detector to find the faces, a shape predictor to find face landmarks so we can precisely localize the face, and finally the face recognition model. Local $o_Dlib_Frontal_Face_Detector = $o_Dlib.get_frontal_face_detector() Local $o_Dlib_Shape_Predictor = _Dlib_ObjCreate("shape_predictor").create($s_Data_Path_Predictor) Local $o_Dlib_Face_Rec_Model = _Dlib_ObjCreate("face_recognition_model_v1").create($s_Data_Path_Face_Rec_Model) ; For display of results only, not required for the operation itself Local $o_Dlib_Window = _Dlib_ObjCreate("image_window") Local $a_All_Files_found_to_process = _Dlib_FindFiles("*.jpg", @ScriptDir & "\faces\") ; Now process all the images For $s_Current_File_to_process In $a_All_Files_found_to_process $s_Current_File_to_process = @ScriptDir & "\faces\" & "\" & $s_Current_File_to_process ConsoleWrite(@CRLF & "Processing file: " & $s_Current_File_to_process & @CRLF) $o_Dlib_Image = $o_Dlib.load_rgb_image($s_Current_File_to_process) $o_Dlib_Window.clear_overlay() $o_Dlib_Window.set_title($s_Current_File_to_process) $o_Dlib_Window.set_image($o_Dlib_Image) ; Ask the detector to find the bounding boxes of each face. ; The 1 in the second argument indicates that we should upsample the image 1 time. This will make everything bigger and allow us to detect more faces. ; The third argument to run is an optional adjustment to the detection threshold, where a negative value will return more detections and a positive value fewer. $a_Detected_Faces_Rect = $o_Dlib_Frontal_Face_Detector($o_Dlib_Image, 1, 0) ; $a_Detected_Faces_Rect = $o_Dlib.extended[0] ; same result ConsoleWrite("Number of faces detected in image: " & UBound($a_Detected_Faces_Rect) & @CRLF) ; You can ask the detector to tell you the score for each detection. The score is bigger for more confident detections. $a_Detected_Faces_Confidence_Scores = $o_Dlib.extended[1] ; The idx tells you which of the face sub-detectors matched. This can be used to broadly identify faces in different orientations. $a_Detected_Faces_Matching_Filter_idx = $o_Dlib.extended[2] ; https://github.com/davisking/dlib/blob/master/dlib/image_processing/frontal_face_detector.h ; 1 = front looking ; 2 = left looking ; 3 = right looking ; 4 = front looking but rotated left ; 5 = front looking but rotated right #cs ; Show an overlay of all detected faces in preview window $o_Dlib_All_Rectangles_of_all_detected_Faces = _Dlib_ObjCreate("VectorOfRectangle") For $i_Detected_Faces_Enum = 0 To UBound($a_Detected_Faces_Rect) - 1 $o_Dlib_All_Rectangles_of_all_detected_Faces.Add($a_Detected_Faces_Rect[$i_Detected_Faces_Enum]) Next $o_Dlib_Window.add_overlay($o_Dlib_All_Rectangles_of_all_Faces) #ce ; Now process each face we found. For $i_Detected_Faces_Enum = 0 To UBound($a_Detected_Faces_Rect) - 1 $t_Detected_Face_Rectangle = $a_Detected_Faces_Rect[$i_Detected_Faces_Enum] ConsoleWrite("+ Face #" & $i_Detected_Faces_Enum + 1 & @TAB & @TAB) ConsoleWrite(StringFormat("Left: %d, Top: %d, Right: %d, Bottom: %d", $t_Detected_Face_Rectangle.left(), $t_Detected_Face_Rectangle.top(), $t_Detected_Face_Rectangle.right(), $t_Detected_Face_Rectangle.bottom()) & @CRLF) ConsoleWrite("Confidence score = " & $a_Detected_Faces_Confidence_Scores[$i_Detected_Faces_Enum] & @TAB & @CRLF) ConsoleWrite("Matching filter = " & $a_Detected_Faces_Matching_Filter_idx[$i_Detected_Faces_Enum] & @CRLF) ; Get the landmarks/parts for the face in box $t_Detected_Face_Rectangle $o_Detected_Face_Landmarks_Shape = $o_Dlib_Shape_Predictor($o_Dlib_Image, $t_Detected_Face_Rectangle) ; ; Get the landmarks/parts for the face ConsoleWrite(StringFormat("Landmark 0: %s, Landmark 1: %s ...", $o_Detected_Face_Landmarks_Shape.part(0).ToString(), $o_Detected_Face_Landmarks_Shape.part(1).ToString()) & @CRLF) ; Draw the face landmarks on the screen so we can see what face is currently being processed. $o_Dlib_Window.clear_overlay() $o_Dlib_Window.add_overlay($t_Detected_Face_Rectangle) $o_Dlib_Window.add_overlay($o_Detected_Face_Landmarks_Shape) ; Compute the 128D vector that describes the face in img identified by shape. ; It should also be noted that you can also call this function like this: ; face_descriptor = facerec.compute_face_descriptor(img, shape, 100, 0.25) ; The version of the call without the 100 gets 99.13% accuracy on LFW while the version with 100 gets 99.38%. However, the 100 makes the call 100x slower to execute, so choose whatever version you like. To explain a little, the 3rd argument tells the code how many times to ; jitter/resample the image. When you set it to 100 it executes the face descriptor extraction 100 times on slightly modified versions of the face and returns the average result. You could also pick a more middle value, such as 10, which is only 10x slower but still gets an ; LFW accuracy of 99.3%. 4th value (0.25) is padding around the face. If padding == 0 then the chip will be closely cropped around the face. Setting larger padding values will result a looser cropping. In particular, a padding of 0.5 would double the width of the cropped area, a value of ; would triple it, and so forth. There is another overload of compute_face_descriptor that can take as an input an aligned image. ConsoleWrite("Computing 128D face description vector..." & @CRLF) $o_Detected_Face_Descriptor = $o_Dlib_Face_Rec_Model.compute_face_descriptor($o_Dlib_Image, $o_Detected_Face_Landmarks_Shape) ; $o_Detected_Face_Descriptor = $o_Dlib_Face_Rec_Model.compute_face_descriptor($o_Dlib_Image, $o_Detected_Face_Landmarks_Shape, 4, 1) ConsoleWrite("$o_Detected_Face_Descriptor.ToString() = " & @TAB & @TAB & @TAB & StringReplace($o_Detected_Face_Descriptor.ToString(), @LF, ",") & @CRLF) ; It is important to generate the aligned image as dlib.get_face_chip would do it i.e. the size must be 150x150, centered and scaled. ConsoleWrite("Computing description on aligned image..." & @CRLF) ; Let's generate the aligned image using get_face_chip $o_Detected_Face_Chip_Aligned_Image = $o_Dlib.get_face_chip($o_Dlib_Image, $o_Detected_Face_Landmarks_Shape) ; https://dlib.net/python/#dlib_pybind11.get_face_chip #cs ; Show 5 jittered images without data augmentation Local $a_Jittered_Images = $o_Dlib.jitter_image($o_Detected_Face_Chip_Aligned_Image, 5) show_jittered_images($o_Dlib_Window, $a_Jittered_Images) ; Show 5 jittered images with data augmentation $a_Jittered_Images = $o_Dlib.jitter_image($o_Detected_Face_Chip_Aligned_Image, 5, True) show_jittered_images($o_Dlib_Window, $a_Jittered_Images) #ce ; Now we simply pass this chip (aligned image) to the api $o_Detected_Face_Descriptor_from_prealigned_image = $o_Dlib_Face_Rec_Model.compute_face_descriptor($o_Detected_Face_Chip_Aligned_Image) ConsoleWrite("$o_Detected_Face_Descriptor_from_prealigned_image.ToString() = " & @TAB & StringReplace($o_Detected_Face_Descriptor_from_prealigned_image.ToString(), @LF, ",") & @CRLF) $a_Detected_Face_Descriptor_128D = StringSplit($o_Detected_Face_Descriptor_from_prealigned_image.ToString(), @LF) If Not IsArray($a_128D_Face_Descriptor_of_Face_to_look_for) Then ; if no target has been set yet, use the first face found as pattern for the search If UBound($a_Detected_Face_Descriptor_128D) = 129 Then $a_128D_Face_Descriptor_of_Face_to_look_for = $a_Detected_Face_Descriptor_128D #cs ; manually create 128D target descriptor $s_128D_Face_Descriptor_of_Face_to_look_for = "$a_128D_Face_Descriptor_of_Face_to_look_for[129] = [128" For $i = 1 To 128 $s_128D_Face_Descriptor_of_Face_to_look_for &= "," & $a_128D_Face_Descriptor_of_Face_to_look_for[$i] Next $s_128D_Face_Descriptor_of_Face_to_look_for &= "]" ConsoleWrite($s_128D_Face_Descriptor_of_Face_to_look_for & @CRLF) #ce ContinueLoop 2 Else ContinueLoop ; Descriptor not valid EndIf EndIf $i_128D_Euclidean_Distance = _Euclidean_Distance_of_128D_Vectors($a_Detected_Face_Descriptor_128D, $a_128D_Face_Descriptor_of_Face_to_look_for) If $i_128D_Euclidean_Distance <= 0.5 Then ; Possible match ConsoleWrite("+ Possible MATCH, Euclidean Distance = " & @TAB & $i_128D_Euclidean_Distance & @CRLF) MsgBox(32, "Dlib Face Recognition result - Possible MATCH", "Possible Face MATCH found" & @CRLF & @CRLF _ & "Euclidean Distance to Face to look for = " & $i_128D_Euclidean_Distance _ & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF _ & "In general, if two face descriptor vectors have a Euclidean distance between them less than 0.6 then they are from the same person, otherwise they are from different people." & @CRLF & @CRLF _ & "KaFu: I found 0.5 to be more accurate, more testing required") Else ; No match ConsoleWrite("- Face does not seem to match, Euclidean Distance = " & @TAB & $i_128D_Euclidean_Distance & @CRLF) MsgBox(48, "Dlib Face Recognition result - Not matching", "Face does not seem to match" & @CRLF & @CRLF _ & "Euclidean Distance to Face to look for = " & $i_128D_Euclidean_Distance _ & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF _ & "In general, if two face descriptor vectors have a Euclidean distance between them less than 0.6 then they are from the same person, otherwise they are from different people." & @CRLF & @CRLF _ & "KaFu: I found 0.5 to be more accurate, more testing required") EndIf Next Next Func _Euclidean_Distance_of_128D_Vectors($a_Vector_1, $a_Vector_2) If UBound($a_Vector_1) <> 129 Then Return SetError(1, 0, -1) ; 1-based 128 array required If UBound($a_Vector_2) <> 129 Then Return SetError(2, 0, -1) ; https://en.wikipedia.org/wiki/Euclidean_distance Local $i_Euclidean_Distance_of_128D_Vectors For $i = 1 To 128 $i_Euclidean_Distance_of_128D_Vectors += ($a_Vector_1[$i] - $a_Vector_2[$i]) ^ 2 ; ConsoleWrite("_Euclidean_Distance_of_128D_Vectors = " & $i & @TAB & $i_128D_Vector_Euclidean_Distance & @TAB & $a_Vector_1[$i] & @TAB & $a_Vector_2[$i] & @CRLF) Next Return Sqrt($i_Euclidean_Distance_of_128D_Vectors) EndFunc ;==>_Euclidean_Distance_of_128D_Vectors Func show_jittered_images($window, $jittered_images) ; Shows the specified jittered images one by one For $i = 0 To UBound($jittered_images) - 1 Local $img = $jittered_images[$i] $window.set_image($img) MsgBox(0, "show_jittered_images", "jittered image " & $i & ": ") Next EndFunc ;==>show_jittered_images Currently the dll is compiled for 64bit, maybe you could provide a 32bit version too? Your effort is much appreciated 👍!
  4. That works fine for all combination, no issues there.
  5. It's hard to tell the reason without knowing the internal workings of DllOpen() vs DllCall() with and without a handle. Also that it's only related to uncompiled 32bit scripts makes it even more hard to explain. And that it seems not a common problem, but only few people seem to experience (or realize) it or seem to be able to reproduce it. It seems to be related to a certain system setup only, though I think at least @UEZ, @@therks and myself stumbled over it now.
  6. No, all uncompiled 32bits scripts using CreateFileMappingW, CreateSemaphoreW and also CreateMutexW fail when called like Local $aHandle = DllCall("kernel32.dll", "handle", "CreateMutexW", "struct*", $tSecurityAttributes, "bool", 1, "wstr", $sOccurrenceName) but work when called with a either a global or local variable for kernel32.dll like Local $h_DLL_Kernel32 = DllOpen("kernel32.dll") Local $aHandle = DllCall($h_DLL_Kernel32, "handle", "CreateMutexW", "struct*", $tSecurityAttributes, "bool", 1, "wstr", $sOccurrenceName)
  7. Wow, now it's getting really wild 🙄. After reading this post by @therks (which I didn't see that time, kudos!), I gave it a try. Now if I don't call the dlls directly, but open the kernel32.dll frist via dllopen, then it works for my uncompiled 32bit scripts too . #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** Local $hSemaphore = _SingletonSemaphore_Org("TestSemaphore", 1) If $hSemaphore = 0 Then MsgBox(16, "Warning - _SingletonSemaphore_Org - Does not work for me from an uncompiled 32bit script", "An occurrence of test is already running", 30) Exit Else MsgBox(64, "OK - _SingletonSemaphore_Org - Does not work for me from an uncompiled 32bit script", "The first occurrence of test is running", 30) DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hSemaphore) EndIf Func _SingletonSemaphore_Org($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 $hStartEvent = DllCall("kernel32.dll", 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall("kernel32.dll", "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Return 0 ; meh Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc Global $hDLL_Kernel32 = DllOpen("kernel32.dll") Local $hSemaphore = _SingletonSemaphore_DllOpen("TestSemaphore", 1) If $hSemaphore = 0 Then MsgBox(16, "Warning - _SingletonSemaphore_DllOpen - Works for me from an uncompiled 32bit script too", "An occurrence of test is already running", 30) Exit Else MsgBox(64, "OK - _SingletonSemaphore_DllOpen - Works for me from an uncompiled 32bit script too", "The first occurrence of test is running", 30) DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hSemaphore) endif Func _SingletonSemaphore_DllOpen($sOccurrenceName, $iFlag = 0) Local Const $ERROR_ALREADY_EXISTS = 183 ; Local $hDLL_Kernel32 = DllOpen("kernel32.dll") $hStartEvent = DllCall($hDLL_Kernel32, 'handle', 'CreateSemaphoreW', 'struct*', 0, 'long', 0, 'long', 1, 'wstr', $sOccurrenceName) If @error Then Return SetError(@error, @extended, 0) Local $hError = DllCall($hDLL_Kernel32, "dword", "GetLastError") If $hError[0] = $ERROR_ALREADY_EXISTS Then DllCall($hDLL_Kernel32, "bool", "CloseHandle", "handle", $hStartEvent[0]) If @error Then Return SetError(@error, @extended, 0) If BitAND($iFlag, 1) Then Return SetError($hError[0], $hError[0], 0) Else Return 0 ; meh Exit -1 EndIf EndIf Return $hStartEvent[0] EndFunc ;==>_SingletonSemaphore Edit: Same result for CreateFileMappingW. Using a handle from dllopen it works for uncompiled 32bit scripts, using a direct dllcall to kernel32.dll it does not work.
  8. Sadly the same result, all works (compiled 32bit and 64bit and uncompiled 64bit), only uncompiled 32bit code still does not work.
  9. I think they are all different means of accessing shared memory... and that there's something underlying principle that prevents my un-compiled 32bit scripts, on a x64 OS, run through SciTE to access this shared memory space. No need to change to WinExist or something, as the compiled code works fine. Just testing on the fly won't work, only hard-coded through msgbox or similar debugging means.
  10. Yes, tried that, didn't change the outcome. Also strange is that _WinAPI_IsWow64Process() still reports 1 after the successful call of _WinAPI_Wow64EnableWow64FsRedirection(False), I would have expected a 0 then. But maybe _WinAPI_IsWow64Process() still is true even if the redirection has been disable. Also tried "Wow64DisableWow64FsRedirection", also didn't help.
  11. Hi @UEZ, did you ever solve this wow64 related topic here? I have the feeling that my topic could be related to the Wow64 redirection too. Is there anything Wow64 related that the autoit3.exe compiler does? Or in the manifest? My 32bit compiled scripts work as expected, un-compiled scripts running as 32 bit from SciTE fail.
  12. Thanks for testing and following up! So it really seems like there's something freaky in my own setup going on, good to know that at least it's not a common problem. I'll post a result, if I ever find out what it was 🙃. Best Regards
  13. I'm using Win10 Home 22H2 64bit, AutoIt 3.3.16.1 and SciTE 32-bit, Version 4.4.6, Mar 12 2022 10:14:43
  14. It's getting even more strange. When I use x64 (#AutoIt3Wrapper_UseX64=y), it seems to work for me too in both directions. When I switch to x86 (#AutoIt3Wrapper_UseX64=n) and - start SciTE first, the executable can detect the existing filemapping - start the executable first, SciTE can not detect the existing filemapping
  15. Returns 0 on first run as exe and also on subsequent runs in SciTE.
×
×
  • Create New...