Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/02/2025 in all areas

  1. MattyD

    WinRT Object Libraries

    Hi everyone, On the back of this recent post around xaml islands, I've started to make some progress on those event handlers we were talking about earlier in this thread. So below Is my first attempt at a colour picker with notifications. (if you don't see the control, you'll likely need to swap out the application manifest, as detailed in the other thread!) If we can get things working nicely, I'd probably incorporate something into the WinRT library which would handle the cumbersome part of building the objects. I think people should only need worry about writing handlers and "registering" them! ColorPicker.zip
    2 points
  2. Modern cameras and cellphones include a lot of data about photos taken into the image as EXIF data, which includes exposure info, GPS coordinates, and exposure date/time. In many file operations (moving, editing, etc) the dates don't reflect the real time of exposure, this script fixes that. To use this script you'll have to first install the app from exiftool.org onto your computer. This script simply allows you to select a folder and it grabs the date/time from all the JPGs in it and changes their file created and modified dates to correspond to the EXIF date. Pretty basic, but just adjust the code as you like! ;PROCESS JPG IMAGES IN A SELECTED FOLDER WITH EXIFTOOL TO RETRIEVE SHOOTING DATE AND REWRITES FILE DATES. ;SCANS A DIRECTORY FOR IMAGES AND SETS THE DATES CREATED AND MODIFIED FROM THE EXIF SHOOTING DATE ;The EXIFTOOL app needs to be downloaded from https://exiftool.org/ (then adjust its folder name below) #include <autoitconstants.au3> #include <MsgBoxConstants.au3> $dirname = FileSelectFolder('Select a Folder','') Local $hSearch = FileFindFirstFile($dirname & "\*.jpg") If $hSearch = -1 Then ; Check if the search was successful. MsgBox($MB_SYSTEMMODAL, "", "Error: No JPG files were found in that folder.") exit EndIf Local $imagefile = "", $iResult = 0 local $arr[1] = ['JPG with EXIF GPS - ' & $dirname] SplashTextOn("EXIF DATE CHECK...", "Setting DATE MODIFIED from EXIF in images...",400,100,500,100) While 1 $imagefile = FileFindNextFile($hSearch) ; If there is no more file matching the search. If @error Then ExitLoop $pid = Run(@ComSpec & " /c " & 'd:\apps\exiftool.exe -DateTimeOriginal ' & $dirname & '\' & $imagefile, "", @SW_HIDE, 2) ProcessWaitClose($pid) $sOutput = StringMid(StdoutRead($pid),35) $sOutput = StringRegExpReplace($sOutput,'[: ]','') ConsoleWrite("EXF: " & $sOutput & @CRLF) ;Commment out the fields you don't want to be updated... FileSetTime($dirname & '\' & $imagefile,$sOutput, 0) ;SET FILE MODIFIED TIME TO SHOOTING TIME FROM EXIF FileSetTime($dirname & '\' & $imagefile,$sOutput, 1) ;SET FILE CREATED TIME TO SHOOTING TIME FROM EXIF ; FileSetTime($dirname & '\' & $imagefile,$sOutput, 2) ;SET FILE ACCESSED TIME TO SHOOTING TIME FROM EXIF ConsoleWrite('UPDATED:' & @CRLF) ConsoleWrite('MOD: ' & FileGetTime($dirname & '\' & $imagefile, 0, 1) & @CRLF) ConsoleWrite('CRE: ' & FileGetTime($dirname & '\' & $imagefile, 1, 1) & @CRLF) ConsoleWrite('ACC: ' & FileGetTime($dirname & '\' & $imagefile, 2, 1) & @CRLF) ControlSetText('EXIF DATE CHECK...', "", "Static1", $dirname & '\' & $imagefile & ' ' & $sOutput) WEnd FileClose($hSearch) splashoff() msgbox(64,'Done','File date processing completed.')
    2 points
  3. smbape

    Dlib UDF

    After the opencv udf, Dlib seems to be a missing library for image processing. This UDF provides a way to use dlib in AutoIt The usage is similar to the python usage of dlib Prerequisites Download and extract autoit-dlib-19.24.9-opencv-4.11.0-com-v1.5.0.7z into a folder Sources Here Documentation A generated documentation for functions is available here (v1.5.0) Examples More examples can be found here (v1.5.0) To run them, please follow these instructions (v1.5.0) Face detection #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #AutoIt3Wrapper_AU3Check_Stop_OnWarning=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> #include "autoit-dlib-com\udf\dlib_udf_utils.au3" _Dlib_Open("opencv-4.11.0-windows\opencv\build\x64\vc16\bin\opencv_world4110.dll", "autoit-dlib-com\autoit_dlib_com-19.24.9-4110.dll") OnAutoItExitRegister("_OnAutoItExit") Example() Func Example() Local Const $dlib = _Dlib_get() If Not IsObj($dlib) Then Return Local $detector = $dlib.get_frontal_face_detector() Local $win = _Dlib_ObjCreate("image_window") Local $image_path = _Dlib_FindFile("examples\faces\2008_002470.jpg") Local $img = $dlib.load_rgb_image($image_path) $win.set_image($img) ; 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. Local $dets = $detector.call($img, 1) ConsoleWrite("Number of faces detected: " & UBound($dets) & @CRLF) Local $d For $i = 0 To UBound($dets) - 1 $d = $dets[$i] ConsoleWrite(StringFormat("Detection %d: Left: %d Top: %d Right: %d Bottom: %d", _ $i, $d.left(), $d.top(), $d.right(), $d.bottom()) & @CRLF) Next $win.add_overlay($dets) hit_to_continue() EndFunc ;==>Example Func hit_to_continue() ToolTip("Hit ESC to continue", 0, 0) ConsoleWrite("Hit ESC to continue" & @CRLF) Do Sleep(50) Until _IsPressed("1B") EndFunc ;==>hit_to_continue Func _OnAutoItExit() _Dlib_Close() EndFunc ;==>_OnAutoItExit Camera face detection using opencv First, download the opencv UDF from here #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #AutoIt3Wrapper_AU3Check_Stop_OnWarning=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> #include "autoit-dlib-com\udf\dlib_udf_utils.au3" #include "autoit-opencv-com\udf\opencv_udf_utils.au3" _Dlib_Open("opencv-4.11.0-windows\opencv\build\x64\vc16\bin\opencv_world4110.dll", "autoit-dlib-com\autoit_dlib_com-19.24.9-4110.dll") _OpenCV_Open("opencv-4.11.0-windows\opencv\build\x64\vc16\bin\opencv_world4110.dll", "autoit-opencv-com\autoit_opencv_com4110.dll") OnAutoItExitRegister("_OnAutoItExit") Example() Func Example() Local Const $dlib = _Dlib_get() If Not IsObj($dlib) Then Return Local Const $cv = _OpenCV_get() If Not IsObj($cv) Then Return Local $detector = $dlib.get_frontal_face_detector() Local $cam = _OpenCV_ObjCreate("VideoCapture").create(0) Local $color_green = _OpenCV_Tuple(0, 255, 0) Local $line_width = 3 Local $img, $dets, $det While True If $cam.read() Then $img = $cv.extended[1] $dets = $detector.call($img) For $i = 0 To UBound($dets) - 1 $det = $dets[$i] $cv.rectangle($img, _OpenCV_Tuple($det.left(), $det.top()), _OpenCV_Tuple($det.right(), $det.bottom()), $color_green, $line_width) Next ;; Flip the image horizontally to give the mirror impression $cv.imshow("my webcam", $cv.flip($img, 1)) EndIf If _IsPressed("1B") Then ExitLoop ; esc to quit EndIf Sleep(1) WEnd $cv.destroyAllWindows() EndFunc ;==>Example Func _OnAutoItExit() _OpenCV_Close() _Dlib_Close() EndFunc ;==>_OnAutoItExit
    1 point
  4. Gianni

    WinRT Object Libraries

    Well said! I agree with you... ColorPicker works well (manifest patch needed) and callback function works great! P.S. peeking at ClassExplorer I see that there is a "Windows.UI.Xaml.Controls.IWebView2" what is this for? can you embed a browser with this?!?
    1 point
  5. That sounds good. I will do some reading on this function tonight and play around with it. Wow, thank you for sharing this. There are many really nice things all within that small script. Some really valuable stuff there that I probably have even more use for. This gives me more ideas now.
    1 point
  6. Ohh, you are too quick and too smart unfortunately - I already created a how-to video that I will upload and share, but now you already solved it on your own 😆 . Maybe for others this could help. Video link coming soon ... Best regards Sven
    1 point
  7. Interesting. Not familiar with this, mind sharing how to perform it ? nvm, found it, thanks for giving us a good way to find hidden nodes.
    1 point
  8. Well done @ioa747 This shows why GUI controls should always use the GUI control update functions, when external controls (outside of AutoIt GUI's) should use the Windows management control functions ( @Melba23 wrote this at least a couple of times, I don't remember where) Still, OP got an issue in his script that he'll fix for sure, as there are no control id's [25] in the GUI (all controls are created from [1] to [24] in each array), these arrays being declared of course with [26] elements or a fatal error would have occured during the loop 1 To 25 (when 25 is reached) So it seems that GUICtrlSetData(0, $record_parsed[25]) doesn't create any visible issue (0 is the value of $GUI_input_parsed[25]) ... ... while ControlSetText($Form_record, "", 0, $record_parsed[25]) updates randomly a control (a GUI focused button for example) How strange. If OP had used GUICtrlSetData() in the first place, he would never notice that something was going wrong in his script. The fact that he used ControlSetText() created random issues (blank buttons) which helped to find the issue (25 instead of 24) Have a great day
    1 point
  9. Hi folks 👋 , as @Nine already mentioned, React components are quite different. Even for really simple HTML5 things like a dropdown (select > option) that is straight forward and standardized, React (also other frameworks like Angular and so on) come up with a own variant of dealing with such user interactions 🥴 . Anyhow, I usually debug (Event Listeners Breakpoints) the website with the Chrome DevTools to get the hidden or unreachable "list" (select > option). Then you can simply look for your (option-) selector and do a second click. See this example: _Main() Func _Main() Local Const $sUrl = 'https://react-select.com/home' _WD_Navigate($sSession, $sUrl) Local Const $sDropdownSelector = '//input[@id="react-select-3-input"]' _ClickElement($sDropdownSelector) Local Const $sOption = 'Silver' Local Const $sOptionSelector = StringFormat('//div[contains(@id, "react-select-3-option") and text()="%s"]', $sOption) _ClickElement($sOptionSelector) EndFunc Func _ClickElement($sSelector) Local Const $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector) _WD_ElementAction($sSession, $sElement, 'click') EndFunc You also might noticed the @id structure of the dropdown: The input element, first click, and the option element (which is a div), second click, do have this react-select-3-* prefix which is common for this kind of react component. So you can assume to "simply" change input by option (the suffix) and you will get your element. This depends on the developer (team) who creates the website, but as I said, I saw it many times in that way structured. @Nine this is not a more elegant way, but maybe a more straight forward one. This been said, I really like your low level _WD_Actions variant, because it can be used in other scenarios as well 🤝 . Best regards Sven
    1 point
  10. strange to me at first, after calling Update_Form button 'Previous Record' turns blank but after updating Update_Form, it remains as it is Func Update_Form($RecordName, $record, $record_parsed, $Label) WinSetTitle($Form_record, "", $RecordName) GUICtrlSetData($Label7, "Record " & $row & " of " & $MaxRecords) GUICtrlSetData($GUI_input_parsed[1], $RecordName) For $ind = 1 To 25 GUICtrlSetData($GUI_LBL[$ind], $Label[$ind]) GUICtrlSetData($GUI_input[$ind], $record[$ind]) GUICtrlSetData($GUI_input_parsed[$ind], $record_parsed[$ind]) Next EndFunc ;==>Update_Form
    1 point
  11. First of all, the pics in my preceding post correspond to this order of controls creation : ; my order of controls creation $Btn_Exit = GUICtrlCreateButton("Exit", 232, 736 - 40, 209, 33) $Btn_Prev = GUICtrlCreateButton("Previous Record", 499, 736 - 40, 209, 33) $Label7 = GUICtrlCreateLabel("Record#", 776, 736 - 40, 166, 25) $Btn_Next = GUICtrlCreateButton("Next Record", 1072, 736 - 40, 209, 33) ; OP's order of controls creation ; $Btn_Prev = GUICtrlCreateButton("Previous Record", 499, 737, 209, 33) ; $Btn_Exit = GUICtrlCreateButton("Exit", 232, 736, 209, 33) ; $Btn_Next = GUICtrlCreateButton("Next Record", 1072, 736, 209, 33) ; $Label7 = GUICtrlCreateLabel("Record#", 776, 736, 166, 25) This explains why it's the Exit button that loses his text in the pics (on OP's side it should be $Btn_Prev) Let's stick to my order of creation : if we add this line after $Btn_Exit creation, we would see : ConsoleWrite("$Btn_Exit = " & $Btn_Exit & @crlf) ; 84 During Update_Form(), let's add a ConsoleWrite : For $ind = 1 To 25 ControlSetText("", "", $GUI_LBL[$ind], $Label[$ind]) ControlSetText("", "", $GUI_input[$ind], $record[$ind]) ControlSetText("", "", $GUI_input_parsed[$ind], $record_parsed[$ind]) ConsoleWrite($ind & " " & $GUI_LBL[$ind] & " " & $GUI_input[$ind] & " " & $GUI_input_parsed[$ind] & @crlf) Next Now we run the script using my little array ["a", "b"] to make the script runnable, this is the Console display : $Btn_Exit = 84 1 4 13 22 2 5 14 23 3 6 15 24 4 7 16 25 5 8 17 26 6 9 18 27 7 10 19 28 8 11 20 29 9 31 40 49 10 32 41 50 11 33 42 51 12 34 43 52 13 35 44 53 14 36 45 54 15 37 46 55 16 38 47 56 17 58 67 76 18 59 68 77 19 60 69 78 20 61 70 79 21 62 71 80 22 63 72 81 23 64 73 82 24 65 74 83 25 We note that there are no GUI id's when $ind reaches 25 in the loop ! Because when you created the GUI, you created controls until 24 (not 25), these are the last ones you created : $GUI_LBL[24] = ... ; id 65 $GUI_input[24] = ... ; id 74 $GUI_input_parsed[24] = ... ; id 83 Which means when $ind reaches 25 in the loop, AutoIt will try to do this : ControlSetText("", "", $GUI_input_parsed[25], $record_parsed[25]) ConsoleWrite("$GUI_input_parsed[25] = " & $GUI_input_parsed[25] & @crlf) ; 0 equivalent to ControlSetText("", "", 0, $record_parsed[25]) ConsoleWrite((GUICtrlRead($Btn_Exit) = " ") & @crlf) ; it's not blank, it's one space, e.g. $record_parsed[25] 0 as id control creates a mess, maybe it uses the control id just after the last updated (?) id 83 = $GUI_input_parsed[24] id 84 = $Btn_Exit (with my order of controls creation) This could explain why you got blank texts in some of your buttons, e.g. the fact that your $ind loop reaches 25, while in your GUI, you created controls until 24 (not 25) Good luck
    1 point
  12. ioa747

    Round buttons

    collection of round buttons ; https://www.autoitscript.com/forum/topic/211721-round-buttons/ ;---------------------------------------------------------------------------------------- ; Title...........: RoundButtons.au3 ; Description.....: collection of round buttons ; AutoIt Version..: 3.3.16.1 Author: ioa747 ; Note............: Testet in Win10 22H2 ;---------------------------------------------------------------------------------------- #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <GUIConstantsEx.au3> #include <StaticConstants.au3> Global $MyGui, $aBtn[7][2] Example() Func Example() $MyGui = GUICreate(" My GUI Icons", 300, 500) $aBtn[0][0] = 6 ; cnt of buttons $aBtn[1][1] = "red" $aBtn[1][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[1][1] & "_normal.ico", 0, 20, 20, 64, 64, $SS_NOTIFY) $aBtn[2][1] = "yellow" $aBtn[2][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[2][1] & "_normal.ico", 0, 20, 100, 64, 64, $SS_NOTIFY) $aBtn[3][1] = "green" $aBtn[3][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[3][1] & "_normal.ico", 0, 20, 180, 64, 64, $SS_NOTIFY) $aBtn[4][1] = "turquoise" $aBtn[4][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[4][1] & "_normal.ico", 0, 20, 260, 64, 64, $SS_NOTIFY) $aBtn[5][1] = "cyan" $aBtn[5][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[5][1] & "_normal.ico", 0, 20, 340, 64, 64, $SS_NOTIFY) $aBtn[6][1] = "magenta" $aBtn[6][0] = GUICtrlCreateIcon(@ScriptDir & "\Buttons\" & $aBtn[6][1] & "_normal.ico", 0, 20, 420, 64, 64, $SS_NOTIFY) GUISetState(@SW_SHOW) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $aBtn[1][0] ConsoleWrite($aBtn[1][1] & @CRLF) Case $aBtn[2][0] ConsoleWrite($aBtn[2][1] & @CRLF) Case $aBtn[3][0] ConsoleWrite($aBtn[3][1] & @CRLF) Case $aBtn[4][0] ConsoleWrite($aBtn[4][1] & @CRLF) Case $aBtn[5][0] ConsoleWrite($aBtn[5][1] & @CRLF) Case $aBtn[6][0] ConsoleWrite($aBtn[6][1] & @CRLF) EndSwitch _IsOver() WEnd GUIDelete() EndFunc ;==>Example Func _IsOver() Local Static $iActive, $iClicked = 0 Local $aActive = GUIGetCursorInfo($MyGui) If $aActive[2] And $iClicked = 1 Then Return If $iActive <> $aActive[4] Then $iActive = $aActive[4] For $i = 1 To $aBtn[0][0] If $aBtn[$i][0] = $aActive[4] Then GUICtrlSetImage($aBtn[$i][0], @ScriptDir & "\Buttons\" & $aBtn[$i][1] & "_hover.ico") Else GUICtrlSetImage($aBtn[$i][0], @ScriptDir & "\Buttons\" & $aBtn[$i][1] & "_normal.ico") EndIf Next EndIf If $aActive[2] Or $iClicked = 1 Then For $i = 1 To $aBtn[0][0] If $aBtn[$i][0] = $aActive[4] Then If $iClicked = 0 Then GUICtrlSetImage($aBtn[$i][0], @ScriptDir & "\Buttons\" & $aBtn[$i][1] & "_click.ico") $iClicked = 1 Else GUICtrlSetImage($aBtn[$i][0], @ScriptDir & "\Buttons\" & $aBtn[$i][1] & "_hover.ico") $iClicked = 0 EndIf EndIf Next EndIf EndFunc ;==>_IsOver Extract buttons folder in @ScriptDir Buttons.zip Please, every comment is appreciated! leave your comments and experiences here! Thank you very much
    1 point
  13. Hi All! Long time posting but glad the community is still thriving! I want to share my code for a YoloV8 Image Annotation Tool. It is not yet complete but a good amount is functional. It offers... Screenshot Here GUI with responsive controls and image view Custom image view scaling to keep images in proportion Some improvements like font scaling could be added Load image folder and yolov8 annotation txt folder Click Load Annotations See your first image in the image folder with colored polygons or bounding boxes and an associated label Labels come from a classes.txt file located in the annotation labels folder Polygons and/or rectangles are drawn depending on the number of elements in the annotation file for each class Polygons and labels are automatically redrawn when the window is maximized, restored or resized. Navigate with the "Next" and "Previous" buttons at the bottom of the GUI TODO Add keyboard shortcuts for buttons Add remove button to remove an image and associated annotation text file from the dataset Add a list view on the right of the image for the image file names and select which file is currently displayed Add a list view on the left of the image for the polygons and their labels to select to move or delete individual annotations Add the ability to click within a polygon to select it in the list view on the left for adjustments, removal or changing the assigned class These are just a few items to make this a fully functionally annotation tool but hopefully people have similar needs and want to pitch in. I plan to create a Github soon if anyone is interested. I'm happy to hear any feedback or suggestions Thanks Example Yolov8 Annotations (No Mask/Mask) ==> https://www.consultingjoe.com/wp-content/uploads/2024/09/Example-Yolov8-Annotations.zip #include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <File.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> #include <Array.au3> Global $imageDir, $labelDir, $annotations, $classes, $classes_colors = [] Global $imageFiles, $currentIndex = 1 Global $originalImageWidth, $originalImageHeight, $scaleX, $scaleY ; Create the GUI (with resizing and maximizing options) $mainGUI = GUICreate("YOLOv8 Annotation Tool", 1024, 768, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_SYSMENU, $WS_MINIMIZEBOX, $WS_CAPTION)) ; Input fields GUICtrlCreateLabel("Image Directory:", 10, 10) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) $imageDirInput = GUICtrlCreateInput(@ScriptDir & "\images\", 120, 10, 700, 20) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) GUICtrlCreateLabel("Label Directory:", 10, 40) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) $labelDirInput = GUICtrlCreateInput(@ScriptDir & "\labels\", 120, 40, 700, 20) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Browse buttons $imageDirButton = GUICtrlCreateButton("Browse", 830, 10, 75, 20) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) $labelDirButton = GUICtrlCreateButton("Browse", 830, 40, 75, 20) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Load button $loadButton = GUICtrlCreateButton("Load Annotations", 10, 70, 200, 30) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Navigation buttons $prevButton = GUICtrlCreateButton("Previous", 10, 710, 100, 30) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) $nextButton = GUICtrlCreateButton("Next", 920, 710, 100, 30) GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Image display area, scalable (with the anchor set) $picDisplay = GUICtrlCreatePic("", 10, 110, 1000, 600) GUICtrlSetResizing($picDisplay, $GUI_DOCKHCENTER) ; Show the GUI GUISetState(@SW_SHOW) ; Event Loop While 1 $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_RESTORE ConsoleWrite("RESTORE") Sleep(10) DisplayCurrentImage(0) Case $GUI_EVENT_MAXIMIZE ConsoleWrite("MAXIMIZE") Sleep(10) DisplayCurrentImage(0) Case $GUI_EVENT_RESIZED ConsoleWrite("RESIZED") Sleep(10) DisplayCurrentImage(0) Case $imageDirButton $imageDir = FileSelectFolder("Select Image Directory", @ScriptDir & "\images\") If Not @error Then GUICtrlSetData($imageDirInput, $imageDir) Case $labelDirButton $labelDir = FileSelectFolder("Select Label Directory", @ScriptDir & "\labels\") If Not @error Then GUICtrlSetData($labelDirInput, $labelDir) Case $loadButton $imageDir = GUICtrlRead($imageDirInput) $labelDir = GUICtrlRead($labelDirInput) If $imageDir = "" Or $labelDir = "" Then MsgBox($MB_ICONERROR, "Error", "Please select both image and label directories.") Else LoadImages($imageDir, $labelDir) EndIf Case $prevButton If $currentIndex > 1 Then DisplayCurrentImage(-1) EndIf Case $nextButton If $currentIndex < $imageFiles[0] Then DisplayCurrentImage(1) EndIf EndSwitch WEnd Func AdjustImageDisplay($imageWidth, $imageHeight) ; Get the available space in the GUI for the image display Local $winSize = WinGetClientSize($mainGUI) Local $availableWidth = $winSize[0] Local $availableHeight = $winSize[1] - 220 ; Adjust for top GUI elements (like buttons) ; Calculate the aspect ratio of the image Local $imageAspectRatio = $imageWidth / $imageHeight ; Initialize new dimensions while maintaining the aspect ratio Local $newWidth, $newHeight ; Adjust the dimensions to fit within the available space, maintaining aspect ratio If ($availableWidth / $availableHeight) > $imageAspectRatio Then ; Available space is wider than the image's aspect ratio, so limit by height $newHeight = $availableHeight $newWidth = $newHeight * $imageAspectRatio Else ; Available space is taller than the image's aspect ratio, so limit by width $newWidth = $availableWidth $newHeight = $newWidth / $imageAspectRatio EndIf ; Calculate new position to center the image control horizontally and vertically Local $xPos = ($availableWidth - $newWidth) / 2 Local $yPos = ($availableHeight - $newHeight) / 2 + 110 ; Resize and reposition the image display control GUICtrlSetPos($picDisplay, $xPos, $yPos, $newWidth, $newHeight) EndFunc Func LoadClasses($labelDir) Local $classFile = $labelDir & "\classes.txt" ; Check if the classes.txt file exists in the label directory If FileExists($classFile) Then ; Read the file into an array Local $lines = [] _FileReadToArray($classFile, $lines) ; Check if the file was read successfully If IsArray($lines) Then ;_ArrayDisplay($lines) ; Copy the lines to the global classes array Global $classes = $lines AssignClassColors() ConsoleWrite("Classes loaded successfully: " & _ArrayToString($classes, ", ") & @CRLF) Else MsgBox($MB_ICONERROR, "Error", "Failed to read the classes.txt file.") EndIf Else MsgBox($MB_ICONERROR, "Error", "classes.txt file not found in: " & $labelDir) EndIf EndFunc Func LoadImages($imageDir, $labelDir) ; Load images $labelDir = GUICtrlRead($labelDirInput) $imageFiles = _FileListToArrayRec($imageDir, "*.jpg;*.png", 1) _ArrayDelete($classes, 0) LoadClasses($labelDir) If @error Then MsgBox($MB_ICONERROR, "Error", "No images found in directory: " & $imageDir) Return EndIf ; Set the current index to the first image $currentIndex = 1 ; Display the first image DisplayCurrentImage(0) EndFunc Func DisplayCurrentImage($nextIndex) If $imageFiles = "" Then Return $currentIndex += $nextIndex Local $filename = StringTrimLeft($imageFiles[$currentIndex], StringInStr($imageFiles[$currentIndex], "\", 0, -1)) ; Replace the extension to match the label file Local $labelFilename = StringReplace($filename, ".jpg", ".txt") $labelFilename = StringReplace($labelFilename, ".png", ".txt") Local $imagePath = $imageDir & "\" & $filename Local $labelPath = $labelDir & "\" & $labelFilename If FileExists($labelPath) Then ConsoleWrite("EXISTS "&$labelPath&@crlf) ; Get the original image dimensions Local $imageWidth = _GDIPlus_ImageGetWidth($imagePath) Local $imageHeight = _GDIPlus_ImageGetHeight($imagePath) AdjustImageDisplay($imageWidth, $imageHeight) ; Load and display the image GUICtrlSetImage($picDisplay, $imagePath) DisplayImageWithAnnotations($imagePath, $labelPath) Else MsgBox($MB_ICONERROR, "Error", "Label file not found: " & $labelFilename) EndIf EndFunc Func DisplayImageWithAnnotations($imagePath, $labelPath) ; Clear previous annotations by deleting all elements While UBound($annotations) > 0 _ArrayDelete($annotations, 0) WEnd _GDIPlus_Startup() Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($picDisplay)) Local $hBitmap = _GDIPlus_BitmapCreateFromFile($imagePath) ; Get the image dimensions $originalImageWidth = _GDIPlus_ImageGetWidth($hBitmap) $originalImageHeight = _GDIPlus_ImageGetHeight($hBitmap) ; Get the dimensions of the displayed image area (accounting for GUI scaling) Local $displayWidth = ControlGetPos($mainGUI, "", $picDisplay)[2] Local $displayHeight = ControlGetPos($mainGUI, "", $picDisplay)[3] ; Calculate scaling factors for X and Y $scaleX = $displayWidth / $originalImageWidth $scaleY = $displayHeight / $originalImageHeight ; Draw the image _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) sleep(50) ; Load and parse the annotation file Local $lines = [] _FileReadToArray($labelPath, $lines) If IsArray($lines) Then For $i = 1 To $lines[0] ConsoleWrite($lines[$i] & @CRLF) ; Ensure the line is not empty and $lines[$i] is within bounds If IsString($lines[$i]) And StringStripWS($lines[$i], 3) <> "" Then Local $elements = StringSplit($lines[$i], " ") ; Ensure $elements is an array and has enough elements If IsArray($elements) And UBound($elements) >= 5 Then ; Handle bounding box (4 points) or polygon (more than 4 points) If UBound($elements) > 6 Then ; Draw the polygon and label it DrawPolygon($hGraphic, $elements) LabelPolygon($hGraphic, $elements) Else ; Draw the bounding box DrawBoundingBox($hGraphic, $elements) LabelPolygon($hGraphic, $elements) EndIf ; Store annotation data _ArrayAdd($annotations, $lines[$i]) EndIf EndIf Next Else ;MsgBox($MB_ICONERROR, "Error", "Failed to read label file: " & $labelPath) EndIf ; Cleanup _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_Shutdown() EndFunc Func DrawPolygon($hGraphic, $elements) Local $classIndex = $elements[1] ; Class index is the first element of the annotation ; Calculate the number of points in the polygon Local $numPoints = (UBound($elements) - 2) / 2 ; Declare the array to hold the polygon points as a 2D array Local $points[$numPoints + 1][2] ; +1 to hold the number of vertices at index [0][0] ; The first element contains the number of vertices $points[0][0] = $numPoints ; Convert normalized coordinates to scaled pixel coordinates For $i = 0 To $numPoints - 1 $points[$i + 1][0] = Round($elements[2 + $i * 2] * $originalImageWidth * $scaleX) ; X coordinate $points[$i + 1][1] = Round($elements[3 + $i * 2] * $originalImageHeight * $scaleY) ; Y coordinate Next ; Create a pen for drawing Local $hPen = _GDIPlus_PenCreate($classes_colors[$classIndex+1], 2) ; Draw the polygon using the 2D points array _GDIPlus_GraphicsDrawPolygon($hGraphic, $points, $hPen) ; Clean up _GDIPlus_PenDispose($hPen) EndFunc Func DrawBoundingBox($hGraphic, $elements) ; Scale the bounding box coordinates according to the display scaling Local $classIndex = $elements[1] ; Class index is the first element of the annotation ; Convert normalized coordinates to pixel coordinates Local $xCenter = $elements[2] * $originalImageWidth * $scaleX Local $yCenter = $elements[3] * $originalImageHeight * $scaleY Local $width = $elements[4] * $originalImageWidth * $scaleX Local $height = $elements[5] * $originalImageHeight * $scaleY ; Calculate the top-left corner from center coordinates and width/height Local $x = $xCenter - ($width / 2) Local $y = $yCenter - ($height / 2) ; Create a pen for drawing, using the class color Local $hPen = _GDIPlus_PenCreate($classes_colors[$classIndex + 1], 2) ; Draw the rectangle (bounding box) _GDIPlus_GraphicsDrawRect($hGraphic, $x, $y, $width, $height, $hPen) ; Clean up _GDIPlus_PenDispose($hPen) EndFunc Func LabelPolygon($hGraphic, $elements) ; Get the class index (first element) and calculate the top-center for the label Local $classIndex = $elements[1] ; Class index is the first element of the annotation Local $minX = $originalImageWidth * $scaleX Local $minY = $originalImageHeight * $scaleY Local $maxX = 0 Local $maxY = 0 Local $numPoints = (UBound($elements) - 2) / 2 ; Find the min and max X coordinates and the minimum Y (top of the polygon) For $i = 0 To $numPoints - 1 Local $x = $elements[2 + $i * 2] * $originalImageWidth * $scaleX Local $y = $elements[3 + $i * 2] * $originalImageHeight * $scaleY ; Get the smallest Y (topmost point) and calculate the min/max X values If $x < $minX Then $minX = $x If $x > $maxX Then $maxX = $x If $y < $minY Then $minY = $y If $y > $maxY Then $maxY = $y Next ; Calculate the horizontal center of the polygon Local $centerX = ($minX + $maxX) / 2 ; Draw the label (class index) at the top-center of the polygon Local $hBrush = _GDIPlus_BrushCreateSolid($classes_colors[$classIndex + 1]) ; White color for text Local $hFormat = _GDIPlus_StringFormatCreate() Local $hFamily = _GDIPlus_FontFamilyCreate("Arial") Local $hFont = _GDIPlus_FontCreate($hFamily, 16, 4) ; Font size 12, bold Local $textRect = _GDIPlus_RectFCreate($minX - 35, $maxY - $minY + $minY, 100, 20) ; Draw the label centered horizontally ; Draw the text label at the top-center of the polygon _GDIPlus_GraphicsDrawStringEx($hGraphic, $classes[$classIndex + 1], $hFont, $textRect, $hFormat, $hBrush) ; Clean up _GDIPlus_BrushDispose($hBrush) _GDIPlus_FontDispose($hFont) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontFamilyDispose($hFamily) EndFunc Func AssignClassColors() Local $predefinedColors = [0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFA500, 0xFF800080, 0xFF808080, 0xFF008080] Local $numPredefined = UBound($predefinedColors) ; Loop through the classes array For $i = 0 To UBound($classes) - 1 ; Assign a predefined color if available, otherwise generate a random color If $i < $numPredefined Then _ArrayAdd($classes_colors, $predefinedColors[$i]) Else ; Generate a random color if predefined colors are exhausted _ArrayAdd($classes_colors, RandomColor()) EndIf Next ConsoleWrite("Class colors assigned successfully: " & _ArrayToString($classes_colors, ", ") & @CRLF) EndFunc ; Function to generate a random color in RGB format Func RandomColor() Local $r = Random(0, 255, 1) Local $g = Random(0, 255, 1) Local $b = Random(0, 255, 1) Return ($r * 0x10000 + $g * 0x100 + $b) EndFunc
    1 point
×
×
  • Create New...