ConsultingJoe Posted September 5 Share Posted September 5 (edited) 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 expandcollapse popup#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 Edited September 5 by ConsultingJoe Updated code and added example annotations ioa747 and Danyfirex 2 Check out ConsultingJoe.com Link to comment Share on other sites More sharing options...
argumentum Posted September 5 Share Posted September 5 56 minutes ago, ConsultingJoe said: I'm happy to hear any feedback or suggestions ok, ..zip an example with a images, labels, etc. relative paths to the script, so that it could run on my PC. Thanks. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
ConsultingJoe Posted September 5 Author Share Posted September 5 1 hour ago, argumentum said: ok, ..zip an example with a images, labels, etc. relative paths to the script, so that it could run on my PC. Thanks. Thanks for the quick feedback. Well taken. Just updated the code for relative default paths and added and example 8 image dataset, 4 with masks and 4 people without masks. Let me know your thoughts from there. Joe argumentum 1 Check out ConsultingJoe.com Link to comment Share on other sites More sharing options...
ConsultingJoe Posted September 6 Author Share Posted September 6 After thinking about this more and how difficult it would be to manage having the user adjust existing boxes and polygon points. It would be very hard all with GDI+ but possible. I found openlayers that gives you map controls to draw polygons on a canvas and adjust the points. May have to adapt this project to nodejs and front-end javascript. https://openlayers.org/en/latest/examples/draw-and-modify-features.html Check out ConsultingJoe.com Link to comment Share on other sites More sharing options...
Werty Posted September 6 Share Posted September 6 (edited) 8 hours ago, ConsultingJoe said: After thinking about this more and how difficult it would be to manage having the user adjust existing boxes and polygon points. It would be very hard all with GDI+ but possible. Yes, it's possible... expandcollapse popup#include <GDIPlus.au3> #include <misc.au3> ; Line Global $Linepoints[3][2] = [[2,0],[584,211],[617,184]] ; Face Global $rightbrowpoints[6][2] = [[5,0],[184,211],[217,184],[274,183],[273,195],[224,197]] Global $leftbrowpoints[6][2] = [[5,0],[335,181],[341,192],[367,190],[388,200],[371,177]] Global $righteyepoints[9][2] = [[8,0],[234,213],[222,219],[212,225],[225,224],[235,225],[252,224],[266,219],[252,214]] Global $lefteyepoints[9][2] = [[8,0],[349,206],[337,209],[330,215],[342,218],[351,218],[364,219],[379,217],[366,209]] Global $mouthpoints[15][2] = [[14,0],[312,323],[291,319],[257,325],[235,337],[247,352],[262,361],[282,370],[306,372],[327,366],[345,354],[354,344],[359,334],[347,323],[328,317]] Global $headpoints[15][2] = [[14,0],[150,130],[136,199],[137,276],[151,346],[213,405],[311,451],[363,406],[387,356],[404,283],[402,197],[388,121],[342,78],[278,63],[203,80]] Local $pt = 0 Global $dll = DllOpen("user32.dll") $gui = GUICreate("", 1024, 768) GUISetState() Opt("MouseCoordMode", 2) ClosedCurveOrPolygon() Func ClosedCurveOrPolygon() Local $0nPoint, $mouseDiffX, $mouseDiffY, $MouseStartPos, $pos _GDIPlus_Startup() Global $hBitmap = _GDIPlus_BitmapCreateFromScan0(1024, 768, $GDIP_PXF32ARGB) Global $hBitmap_clone = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 1024, 768) Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($gui) Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) Global $retValue2 = "head" Draw(-1) Do $msg = GUIGetMsg() If $msg = -3 Then ExitLoop If _IsPressed("01", $dll) Then $MouseStartPos = MouseGetPos() $0nPoint = CheckOverPoint($MouseStartPos[0], $MouseStartPos[1]) $mouseDiffX = 0 If $0nPoint >= 0 Then $moveAll = 1 Draw($0nPoint) $GrnPt = $0nPoint While _IsPressed("01", $dll) $pos = MouseGetPos() $mouseDiffX = Int(($pos[0] - $MouseStartPos[0])) $mouseDiffY = Int(($pos[1] - $MouseStartPos[1])) If Abs($mouseDiffX) > 0 Or Abs($mouseDiffY) > 0 Then If $retValue2 = "head" Then $headpoints[$0nPoint][0] = $pos[0] $headpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "mouth" Then $mouthpoints[$0nPoint][0] = $pos[0] $mouthpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "righteye" Then $righteyepoints[$0nPoint][0] = $pos[0] $righteyepoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "lefteye" Then $lefteyepoints[$0nPoint][0] = $pos[0] $lefteyepoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "rightbrow" Then $rightbrowpoints[$0nPoint][0] = $pos[0] $rightbrowpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "leftbrow" Then $leftbrowpoints[$0nPoint][0] = $pos[0] $leftbrowpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "Line" Then $Linepoints[$0nPoint][0] = $pos[0] $Linepoints[$0nPoint][1] = $pos[1] EndIf Draw($0nPoint) Sleep(20) EndIf Sleep(20) WEnd Else $moveAll = 0 Draw(-1) EndIf EndIf ; mouse BTN 1 pressed?? Sleep(20) Until _IsPressed("1B") ; ESC key DllClose($dll) EndFunc ;==>ClosedCurveOrPolygon Func CheckOverPoint($MouseX, $MouseY) Local $x1, $x2, $x3, $x4, $x5, $x6, $x7, $retValue = -1 For $x1 = 1 To UBound($headpoints) - 1 If $MouseX < $headpoints[$x1][0] + 5 And $MouseX > $headpoints[$x1][0] - 5 And $MouseY < $headpoints[$x1][1] + 5 And $MouseY > $headpoints[$x1][1] - 5 Then $retValue = $x1 $retValue2 = "head" EndIf Next For $x2 = 1 To UBound($mouthpoints) - 1 If $MouseX < $mouthpoints[$x2][0] + 5 And $MouseX > $mouthpoints[$x2][0] - 5 And $MouseY < $mouthpoints[$x2][1] + 5 And $MouseY > $mouthpoints[$x2][1] - 5 Then $retValue = $x2 $retValue2 = "mouth" EndIf Next For $x3 = 1 To UBound($righteyepoints) - 1 If $MouseX < $righteyepoints[$x3][0] + 5 And $MouseX > $righteyepoints[$x3][0] - 5 And $MouseY < $righteyepoints[$x3][1] + 5 And $MouseY > $righteyepoints[$x3][1] - 5 Then $retValue = $x3 $retValue2 = "righteye" EndIf Next For $x4 = 1 To UBound($lefteyepoints) - 1 If $MouseX < $lefteyepoints[$x4][0] + 5 And $MouseX > $lefteyepoints[$x4][0] - 5 And $MouseY < $lefteyepoints[$x4][1] + 5 And $MouseY > $lefteyepoints[$x4][1] - 5 Then $retValue = $x4 $retValue2 = "lefteye" EndIf Next For $x5 = 1 To UBound($rightbrowpoints) - 1 If $MouseX < $rightbrowpoints[$x5][0] + 5 And $MouseX > $rightbrowpoints[$x5][0] - 5 And $MouseY < $rightbrowpoints[$x5][1] + 5 And $MouseY > $rightbrowpoints[$x5][1] - 5 Then $retValue = $x5 $retValue2 = "rightbrow" EndIf Next For $x6 = 1 To UBound($leftbrowpoints) - 1 If $MouseX < $leftbrowpoints[$x6][0] + 5 And $MouseX > $leftbrowpoints[$x6][0] - 5 And $MouseY < $leftbrowpoints[$x6][1] + 5 And $MouseY > $leftbrowpoints[$x6][1] - 5 Then $retValue = $x6 $retValue2 = "leftbrow" EndIf Next For $x7 = 1 To UBound($Linepoints) - 1 If $MouseX < $Linepoints[$x7][0] + 5 And $MouseX > $Linepoints[$x7][0] - 5 And $MouseY < $Linepoints[$x7][1] + 5 And $MouseY > $Linepoints[$x7][1] - 5 Then $retValue = $x7 $retValue2 = "Line" EndIf Next Return $retValue EndFunc ;==>CheckOverPoint Func draw($pt) $hPen = _GDIPlus_PenCreate(0xFFFFFFFF, 2); white $hBrushRed = _GDIPlus_BrushCreateSolid(0x8fff0000) ;red $hBrushGreen = _GDIPlus_BrushCreateSolid(0x8f00ff00) ;Green _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 2) _GDIPlus_GraphicsClear($backbuffer, 0x00000000) _GDIPLus_GraphicsDrawImageRect($backbuffer, $hBitmap_clone, 0, 0, 1024, 768) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $headpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $mouthpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $righteyepoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $lefteyepoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $rightbrowpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $leftbrowpoints, $hPen) _GDIPlus_GraphicsDrawLine ($backbuffer, $Linepoints[1][0],$Linepoints[1][1],$Linepoints[2][0],$Linepoints[2][1], $hPen) $esize = 6 For $x1 = 1 To UBound($headpoints) - 1 If $x1 = $pt AND $retValue2 = "head" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize) Next For $x2 = 1 To UBound($mouthpoints) - 1 If $x2 = $pt And $retValue2 = "mouth" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize) Next For $x3 = 1 To UBound($righteyepoints) - 1 If $x3 = $pt And $retValue2 = "righteye" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize) Next For $x4 = 1 To UBound($lefteyepoints) - 1 If $x4 = $pt And $retValue2 = "lefteye" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize) Next For $x5 = 1 To UBound($rightbrowpoints) - 1 If $x5 = $pt And $retValue2 = "rightbrow" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize) Next For $x6 = 1 To UBound($leftbrowpoints) - 1 If $x6 = $pt And $retValue2 = "leftbrow" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize) Next For $x7 = 1 To UBound($Linepoints) - 1 If $x7 = $pt And $retValue2 = "Line" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize) Next _GDIPlus_GraphicsDrawImageRect ($hGraphic, $hBitmap, 0, 0, 1024, 768) _GDIPlus_PenDispose($hPen) _GDIPlus_BrushDispose($hBrushRed) _GDIPlus_BrushDispose($hBrushGreen) EndFunc Edited September 6 by Werty ConsultingJoe, ioa747 and Danyfirex 3 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
ConsultingJoe Posted September 19 Author Share Posted September 19 On 9/6/2024 at 5:12 AM, Werty said: Yes, it's possible... expandcollapse popup#include <GDIPlus.au3> #include <misc.au3> ; Line Global $Linepoints[3][2] = [[2,0],[584,211],[617,184]] ; Face Global $rightbrowpoints[6][2] = [[5,0],[184,211],[217,184],[274,183],[273,195],[224,197]] Global $leftbrowpoints[6][2] = [[5,0],[335,181],[341,192],[367,190],[388,200],[371,177]] Global $righteyepoints[9][2] = [[8,0],[234,213],[222,219],[212,225],[225,224],[235,225],[252,224],[266,219],[252,214]] Global $lefteyepoints[9][2] = [[8,0],[349,206],[337,209],[330,215],[342,218],[351,218],[364,219],[379,217],[366,209]] Global $mouthpoints[15][2] = [[14,0],[312,323],[291,319],[257,325],[235,337],[247,352],[262,361],[282,370],[306,372],[327,366],[345,354],[354,344],[359,334],[347,323],[328,317]] Global $headpoints[15][2] = [[14,0],[150,130],[136,199],[137,276],[151,346],[213,405],[311,451],[363,406],[387,356],[404,283],[402,197],[388,121],[342,78],[278,63],[203,80]] Local $pt = 0 Global $dll = DllOpen("user32.dll") $gui = GUICreate("", 1024, 768) GUISetState() Opt("MouseCoordMode", 2) ClosedCurveOrPolygon() Func ClosedCurveOrPolygon() Local $0nPoint, $mouseDiffX, $mouseDiffY, $MouseStartPos, $pos _GDIPlus_Startup() Global $hBitmap = _GDIPlus_BitmapCreateFromScan0(1024, 768, $GDIP_PXF32ARGB) Global $hBitmap_clone = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 1024, 768) Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($gui) Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) Global $retValue2 = "head" Draw(-1) Do $msg = GUIGetMsg() If $msg = -3 Then ExitLoop If _IsPressed("01", $dll) Then $MouseStartPos = MouseGetPos() $0nPoint = CheckOverPoint($MouseStartPos[0], $MouseStartPos[1]) $mouseDiffX = 0 If $0nPoint >= 0 Then $moveAll = 1 Draw($0nPoint) $GrnPt = $0nPoint While _IsPressed("01", $dll) $pos = MouseGetPos() $mouseDiffX = Int(($pos[0] - $MouseStartPos[0])) $mouseDiffY = Int(($pos[1] - $MouseStartPos[1])) If Abs($mouseDiffX) > 0 Or Abs($mouseDiffY) > 0 Then If $retValue2 = "head" Then $headpoints[$0nPoint][0] = $pos[0] $headpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "mouth" Then $mouthpoints[$0nPoint][0] = $pos[0] $mouthpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "righteye" Then $righteyepoints[$0nPoint][0] = $pos[0] $righteyepoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "lefteye" Then $lefteyepoints[$0nPoint][0] = $pos[0] $lefteyepoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "rightbrow" Then $rightbrowpoints[$0nPoint][0] = $pos[0] $rightbrowpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "leftbrow" Then $leftbrowpoints[$0nPoint][0] = $pos[0] $leftbrowpoints[$0nPoint][1] = $pos[1] ElseIf $retValue2 = "Line" Then $Linepoints[$0nPoint][0] = $pos[0] $Linepoints[$0nPoint][1] = $pos[1] EndIf Draw($0nPoint) Sleep(20) EndIf Sleep(20) WEnd Else $moveAll = 0 Draw(-1) EndIf EndIf ; mouse BTN 1 pressed?? Sleep(20) Until _IsPressed("1B") ; ESC key DllClose($dll) EndFunc ;==>ClosedCurveOrPolygon Func CheckOverPoint($MouseX, $MouseY) Local $x1, $x2, $x3, $x4, $x5, $x6, $x7, $retValue = -1 For $x1 = 1 To UBound($headpoints) - 1 If $MouseX < $headpoints[$x1][0] + 5 And $MouseX > $headpoints[$x1][0] - 5 And $MouseY < $headpoints[$x1][1] + 5 And $MouseY > $headpoints[$x1][1] - 5 Then $retValue = $x1 $retValue2 = "head" EndIf Next For $x2 = 1 To UBound($mouthpoints) - 1 If $MouseX < $mouthpoints[$x2][0] + 5 And $MouseX > $mouthpoints[$x2][0] - 5 And $MouseY < $mouthpoints[$x2][1] + 5 And $MouseY > $mouthpoints[$x2][1] - 5 Then $retValue = $x2 $retValue2 = "mouth" EndIf Next For $x3 = 1 To UBound($righteyepoints) - 1 If $MouseX < $righteyepoints[$x3][0] + 5 And $MouseX > $righteyepoints[$x3][0] - 5 And $MouseY < $righteyepoints[$x3][1] + 5 And $MouseY > $righteyepoints[$x3][1] - 5 Then $retValue = $x3 $retValue2 = "righteye" EndIf Next For $x4 = 1 To UBound($lefteyepoints) - 1 If $MouseX < $lefteyepoints[$x4][0] + 5 And $MouseX > $lefteyepoints[$x4][0] - 5 And $MouseY < $lefteyepoints[$x4][1] + 5 And $MouseY > $lefteyepoints[$x4][1] - 5 Then $retValue = $x4 $retValue2 = "lefteye" EndIf Next For $x5 = 1 To UBound($rightbrowpoints) - 1 If $MouseX < $rightbrowpoints[$x5][0] + 5 And $MouseX > $rightbrowpoints[$x5][0] - 5 And $MouseY < $rightbrowpoints[$x5][1] + 5 And $MouseY > $rightbrowpoints[$x5][1] - 5 Then $retValue = $x5 $retValue2 = "rightbrow" EndIf Next For $x6 = 1 To UBound($leftbrowpoints) - 1 If $MouseX < $leftbrowpoints[$x6][0] + 5 And $MouseX > $leftbrowpoints[$x6][0] - 5 And $MouseY < $leftbrowpoints[$x6][1] + 5 And $MouseY > $leftbrowpoints[$x6][1] - 5 Then $retValue = $x6 $retValue2 = "leftbrow" EndIf Next For $x7 = 1 To UBound($Linepoints) - 1 If $MouseX < $Linepoints[$x7][0] + 5 And $MouseX > $Linepoints[$x7][0] - 5 And $MouseY < $Linepoints[$x7][1] + 5 And $MouseY > $Linepoints[$x7][1] - 5 Then $retValue = $x7 $retValue2 = "Line" EndIf Next Return $retValue EndFunc ;==>CheckOverPoint Func draw($pt) $hPen = _GDIPlus_PenCreate(0xFFFFFFFF, 2); white $hBrushRed = _GDIPlus_BrushCreateSolid(0x8fff0000) ;red $hBrushGreen = _GDIPlus_BrushCreateSolid(0x8f00ff00) ;Green _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 2) _GDIPlus_GraphicsClear($backbuffer, 0x00000000) _GDIPLus_GraphicsDrawImageRect($backbuffer, $hBitmap_clone, 0, 0, 1024, 768) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $headpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $mouthpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $righteyepoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $lefteyepoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $rightbrowpoints, $hPen) _GDIPlus_GraphicsDrawClosedCurve ($backbuffer, $leftbrowpoints, $hPen) _GDIPlus_GraphicsDrawLine ($backbuffer, $Linepoints[1][0],$Linepoints[1][1],$Linepoints[2][0],$Linepoints[2][1], $hPen) $esize = 6 For $x1 = 1 To UBound($headpoints) - 1 If $x1 = $pt AND $retValue2 = "head" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $headpoints[$x1][0] - $esize/2, $headpoints[$x1][1] - $esize/2, $esize, $esize) Next For $x2 = 1 To UBound($mouthpoints) - 1 If $x2 = $pt And $retValue2 = "mouth" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $mouthpoints[$x2][0] - $esize/2, $mouthpoints[$x2][1] - $esize/2, $esize, $esize) Next For $x3 = 1 To UBound($righteyepoints) - 1 If $x3 = $pt And $retValue2 = "righteye" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $righteyepoints[$x3][0] - $esize/2, $righteyepoints[$x3][1] - $esize/2, $esize, $esize) Next For $x4 = 1 To UBound($lefteyepoints) - 1 If $x4 = $pt And $retValue2 = "lefteye" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $lefteyepoints[$x4][0] - $esize/2, $lefteyepoints[$x4][1] - $esize/2, $esize, $esize) Next For $x5 = 1 To UBound($rightbrowpoints) - 1 If $x5 = $pt And $retValue2 = "rightbrow" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $rightbrowpoints[$x5][0] - $esize/2, $rightbrowpoints[$x5][1] - $esize/2, $esize, $esize) Next For $x6 = 1 To UBound($leftbrowpoints) - 1 If $x6 = $pt And $retValue2 = "leftbrow" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $leftbrowpoints[$x6][0] - $esize/2, $leftbrowpoints[$x6][1] - $esize/2, $esize, $esize) Next For $x7 = 1 To UBound($Linepoints) - 1 If $x7 = $pt And $retValue2 = "Line" Then _GDIPlus_GraphicsFillEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize, $hBrushGreen) Else _GDIPlus_GraphicsFillEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize, $hBrushRed) EndIf _GDIPlus_GraphicsDrawEllipse($backbuffer, $Linepoints[$x7][0] - $esize/2, $Linepoints[$x7][1] - $esize/2, $esize, $esize) Next _GDIPlus_GraphicsDrawImageRect ($hGraphic, $hBitmap, 0, 0, 1024, 768) _GDIPlus_PenDispose($hPen) _GDIPlus_BrushDispose($hBrushRed) _GDIPlus_BrushDispose($hBrushGreen) EndFunc Holy cow. That's amazing. WOW Check out ConsultingJoe.com Link to comment Share on other sites More sharing options...
Werty Posted September 19 Share Posted September 19 It's been 13 years since "i made it" so completely forgot I'm not the original author of it, I only removed some stuff and added other stuff, credits goes to @Malkey for his... ...example. ConsultingJoe and SOLVE-SMART 1 1 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now