Jump to content

YoloV8 Image Annotation Tool


Recommended Posts

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

  1. GUI with responsive controls and image view
    1. Custom image view scaling to keep images in proportion
    2. Some improvements like font scaling could be added
  2. Load image folder and yolov8 annotation txt folder
  3. Click Load Annotations
  4. See your first image in the image folder with colored polygons or bounding boxes and an associated label
    1. Labels come from a classes.txt file located in the annotation labels folder
    2. Polygons and/or rectangles are drawn depending on the number of elements in the annotation file for each class
    3. Polygons and labels are automatically redrawn when the window is maximized, restored or resized.
  5. Navigate with the "Next" and "Previous" buttons at the bottom of the GUI
  6. TODO
    1. Add keyboard shortcuts for buttons
    2. Add remove button to remove an image and associated annotation text file from the dataset
    3. Add a list view on the right of the image for the image file names and select which file is currently displayed 
    4. Add a list view on the left of the image for the polygons and their labels to select to move or delete individual annotations
    5. 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

 

Edited by ConsultingJoe
Updated code and added example annotations
Check out ConsultingJoe.com
Link to comment
Share on other sites

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

Check out ConsultingJoe.com
Link to comment
Share on other sites

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

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...

#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 by Werty

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

  • 2 weeks later...
On 9/6/2024 at 5:12 AM, Werty said:

Yes, it's possible...

#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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...