Functions/GenXdev.AI/Get-ImageRecognizedFaces.ps1

################################################################################
function Get-ImageRecognizedFaces {
    <#
.SYNOPSIS
    Recognizes faces in an uploaded image by comparing to known faces.
 
.DESCRIPTION
    This function analyzes an image file to identify faces by comparing them
    against known faces in the database. It uses a local face recognition API
    running on port 8080 and returns face matches with a distance less than 0.5
    (indicating a high confidence match).
 
.PARAMETER ImagePath
    The local path to the image file to analyze. This parameter accepts any valid
    file path that can be resolved by the system.
 
.EXAMPLE
    Get-ImageRecognizedFaces -ImagePath "C:\Users\YourName\test.jpg"
 
    Analyzes the specified image file and returns any recognized faces.
 
.EXAMPLE
    "C:\Users\YourName\test.jpg" | Get-ImageRecognizedFaces
 
    Passes an image path through the pipeline to be analyzed for face recognition.
#>

    [CmdletBinding()]
    [Alias()]

    param(
        ########################################################################
        [Parameter(
            Position = 0,
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = "The local path to the image file to analyze"
        )]
        [ValidateNotNullOrEmpty()]
        [string]$ImagePath
        ########################################################################
    )

    begin {

        # ensure that the face recognition service is running
        Microsoft.PowerShell.Utility\Write-Verbose "Ensuring face recognition service is available"
        GenXdev.AI\EnsureFaceRecognition

        # set the api base url for local face recognition service
        $script:ApiBaseUrl = "http://127.0.0.1:8080"

        Microsoft.PowerShell.Utility\Write-Verbose "Using face recognition API at: $script:ApiBaseUrl"
    }

    process {

        try {
            # expand the image path to its full form
            $imagePath = GenXdev.FileSystem\Expand-Path $ImagePath
            Microsoft.PowerShell.Utility\Write-Verbose "Processing image: $imagePath"

            # validate that the file is a valid image
            GenXdev.AI\Test-ImageFile -Path $imagePath

            # construct the api endpoint uri
            $uri = "$($script:ApiBaseUrl)/"
            Microsoft.PowerShell.Utility\Write-Verbose "Sending request to: $uri"

            # create proper multipart form data with boundary for http request
            $boundary = [System.Guid]::NewGuid().ToString()
            $fileName = [System.IO.Path]::GetFileName($imagePath)
            $fileBytes = [System.IO.File]::ReadAllBytes($imagePath)

            # build the multipart form body with the image data
            $bodyLines = @(
                "--$boundary",
                "Content-Disposition: form-data; name=`"file`"; filename=`"$fileName`"",
                "Content-Type: application/octet-stream",
                "",
                [System.Text.Encoding]::GetEncoding("iso-8859-1").GetString($fileBytes),
                "--$boundary--"
            )

            # join the body lines with carriage return and line feed
            $body = $bodyLines -join "`r`n"

            # convert the body to bytes using iso-8859-1 encoding
            $bodyBytes = [System.Text.Encoding]::GetEncoding("iso-8859-1").GetBytes($body)

            # send the web request to the face recognition api
            Microsoft.PowerShell.Utility\Write-Verbose "Sending image data to face recognition API"
            $response = Microsoft.PowerShell.Utility\Invoke-WebRequest `
                -Uri $uri `
                -Method Post `
                -Body $bodyBytes `
                -ContentType "multipart/form-data; boundary=$boundary"

            # convert the json response to a powershell object
            $obj = $response.Content | Microsoft.PowerShell.Utility\ConvertFrom-Json

            # filter faces to only include those with a distance less than 0.5
            # lower distance means higher confidence in the face match
            Microsoft.PowerShell.Utility\Write-Verbose "Filtering faces with distance < 0.5"
            $obj.faces = @($obj.faces |
                Microsoft.PowerShell.Core\Where-Object -Property "dist" -LT 0.5)

            # output the recognition results
            Microsoft.PowerShell.Utility\Write-Verbose (
                "Found {0} recognized face(s)" -f $obj.faces.Count
            )
            Microsoft.PowerShell.Utility\Write-Output $obj
        }
        catch {
            # handle any errors that occur during processing
            Microsoft.PowerShell.Utility\Write-Error "Failed to recognize faces: $_"
        }
    }

    end {
        # no end block processing required
    }
}
################################################################################