Skip to content

Instantly share code, notes, and snippets.

@markgodiy
Last active June 9, 2024 12:35
Show Gist options
  • Select an option

  • Save markgodiy/85a7c40ede5d468d05dcb98ebc471217 to your computer and use it in GitHub Desktop.

Select an option

Save markgodiy/85a7c40ede5d468d05dcb98ebc471217 to your computer and use it in GitHub Desktop.
<#
A MarkGo project. JUN2024.
Person Sensor Developer Guide
https://github.com/usefulsensors/person_sensor_docs?tab=readme-ov-file#connecting
Byte format (39 bytes)
--------------------
0,1 Reserved
2 Data Length (first byte)
3 Data Length (second byte)
4 Number of Faces
5 Face #0 Box Confidence
6 Face #0 Box Left
7 Face #0 Box Top
8 Face #0 Box Right
9 Face #0 Box Bottom
10 Face #0 Recognition Confidence
11 Face #0 Recognition ID
12 Face #0 Is Looking At
13-20 Face #1
21-28 Face #2
29-36 Face #3
37-38 Reserved for checksum first and second byte
#>
Add-Type -AssemblyName PresentationFramework
[xml]$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Person Sensor Viewer" Height="400" Width="355">
<Grid>
<Canvas Name="canvas" VerticalAlignment="Top" Height="255" Width="255"/>
<Button Name="toggleButton" Content="Start Detection" Width="120" Height="30" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,10"/>
</Grid>
</Window>
"@
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
$canvas = $window.FindName("canvas")
$toggleButton = $window.FindName("toggleButton")
# IoT library
$iotlibrary = "\\pathto\Iot.Device.Bindings.dll"
try {
[System.Reflection.Assembly]::LoadFrom($iotlibrary)
}
catch {
[System.Windows.MessageBox]::Show("Failed to load required assemblies.")
return
}
$Board1Serial = "FT999999"
$PersonSensorAddress = 0x62
$devices = [Iot.Device.FtCommon.FtCommon]::GetDevices()
if ($devices.Count -eq 0) {
[System.Windows.MessageBox]::Show("No FT232H devices found.")
return
}
$device = $devices | Where-Object { $_.SerialNumber -eq $Board1Serial }
if ($null -eq $device) {
[System.Windows.MessageBox]::Show("FT232H device with serial $Board1Serial not found.")
return
}
$ft232h = [Iot.Device.Ft232H.Ft232HDevice]::new($device)
$i2cSettings = [System.Device.I2c.I2cConnectionSettings]::new(0, $PersonSensorAddress)
$i2cDevice = $ft232h.CreateI2cDevice($i2cSettings)
$readBuffer = New-Object byte[] 39
$timer = New-Object System.Windows.Threading.DispatcherTimer
$timer.Interval = [TimeSpan]::FromSeconds(1)
# Add a black rectangle around the detectable area
$timer.add_Tick({
try {
$i2cDevice.Read($readBuffer)
$canvas.Children.Clear()
AddDetectableAreaBorder -canvas $canvas
ParseSensorData -data $readBuffer
}
catch {
Write-Host "Error reading from Person Sensor: $_"
}
})
# Function to toggle face detection
$toggleButton.add_Click({
if ($timer.IsEnabled) {
$timer.Stop()
$toggleButton.Content = "Start Detection"
}
else {
$timer.Start()
$toggleButton.Content = "Stop Detection"
}
})
# dispose everything disposable when the window is closed
$window.add_Closed({
Write-Host "Closing window and disposing objects"
$timer.Stop()
$i2cDevice.Dispose()
$ft232h.Dispose()
})
function ParseSensorData {
param ($data)
if ($data.Length -lt 39) {
Write-Host "Invalid data length."
return
}
Write-Host $data
$numberOfFaces = $data[4]
Write-Host "Number of faces detected: $numberOfFaces"
for ($i = 0; $i -lt $numberOfFaces; $i++) {
$offset = 5 + $i * 8 # Calculate offset for each face
$confidence = $data[$offset] # Face Box Confidence
$left = $data[$offset + 1] # Face Box Left
$top = $data[$offset + 2] # Face Box Top
$right = $data[$offset + 3] # Face Box Right
$bottom = $data[$offset + 4] # Face Box Bottom
$recognitionconfidence = $data[$offset + 5] # Face Recognition Confidence
$recognitionID = $data[$offset + 6] # Face Recognition ID
$islooking = $data[$offset + 7] # Is Looking At
$width = $right - $left
$height = $bottom - $top
Write-Host "Face #$($i) - Confidence: $confidence, Recognition: $recognitionID ($recognitionconfidence), IsLooking: $islooking"
Write-Host "Left: $left, Top: $top, Right: $right, Bottom: $bottom, Width: $width, Height: $height"
if ($width -gt 0 -and $height -gt 0) {
# Draw rectangle
$rectangle = New-Object Windows.Shapes.Rectangle
$rectangle.Stroke = [Windows.Media.Brushes]::Red
$rectangle.StrokeThickness = 2
$rectangle.Width = $width
$rectangle.Height = $height
[Windows.Controls.Canvas]::SetLeft($rectangle, $left)
[Windows.Controls.Canvas]::SetTop($rectangle, $top)
# Add face number
$textBlockFace = New-Object Windows.Controls.TextBlock
$textBlockFace.Text = "Face $i ($confidence %)"
$textBlockFace.Foreground = [Windows.Media.Brushes]::Red
[Windows.Controls.Canvas]::SetLeft($textBlockFace, $right + 10)
[Windows.Controls.Canvas]::SetTop($textBlockFace, $top )
# Add islooking
$textBlockLooking = New-Object Windows.Controls.TextBlock
$textBlockLooking.Text = "IsLooking: $islooking"
$textBlockLooking.Foreground = [Windows.Media.Brushes]::Red
[Windows.Controls.Canvas]::SetLeft($textBlockLooking, $right + 10)
[Windows.Controls.Canvas]::SetTop($textBlockLooking, $top + 15)
# Add ID Text Blovck
$textBlockID = New-Object Windows.Controls.TextBlock
$textBlockID.Text = "ID: $recognitionID ($recognitionconfidence %)"
$textBlockID.Foreground = [Windows.Media.Brushes]::Red
[Windows.Controls.Canvas]::SetLeft($textBlockID, $right + 10)
[Windows.Controls.Canvas]::SetTop($textBlockID, $top + 30)
# Add elements to canvas
$canvas.Children.Add($rectangle)
$canvas.Children.Add($textBlockFace)
$canvas.Children.Add($textBlockLooking)
$canvas.Children.Add($textBlockID)
# Draw lines from the center of the rectangle to the corners of the perimeter box
DrawConnectingLines -canvas $canvas -rectangle $rectangle -left $left -top $top -right $right -bottom $bottom
}
else {
Write-Host "Invalid dimensions for face #$($i + 1) - Width: $width, Height: $height"
}
}
}
function AddDetectableAreaBorder {
param (
[Parameter(Mandatory = $true)]
[Windows.Controls.Canvas]$canvas
)
$border = New-Object Windows.Shapes.Rectangle
$border.Stroke = [Windows.Media.Brushes]::Black
$border.StrokeThickness = 2
$border.Width = $canvas.Width
$border.Height = $canvas.Height
[Windows.Controls.Canvas]::SetLeft($border, 0)
[Windows.Controls.Canvas]::SetTop($border, 0)
$canvas.Children.Add($border)
}
function DrawConnectingLines {
param (
[Parameter(Mandatory = $true)]
[Windows.Controls.Canvas]$canvas,
[Parameter(Mandatory = $true)]
[Windows.Shapes.Rectangle]$rectangle,
[Parameter(Mandatory = $true)]
[double]$left,
[Parameter(Mandatory = $true)]
[double]$top,
[Parameter(Mandatory = $true)]
[double]$right,
[Parameter(Mandatory = $true)]
[double]$bottom
)
$centerX = $left + ($rectangle.Width / 2)
$centerY = $top + ($rectangle.Height / 2)
# Corner points of the perimeter box
$corners = @(
@{ X = 0; Y = 0 },
@{ X = $canvas.Width; Y = 0 },
@{ X = 0; Y = $canvas.Height },
@{ X = $canvas.Width; Y = $canvas.Height }
)
foreach ($corner in $corners) {
$line = New-Object Windows.Shapes.Line
$line.Stroke = [Windows.Media.Brushes]::Gray
$line.StrokeThickness = 1
$line.X1 = $centerX
$line.Y1 = $centerY
$line.X2 = $corner.X
$line.Y2 = $corner.Y
$canvas.Children.Add($line)
# Add details to the line
$textBlockLine = New-Object Windows.Controls.TextBlock
$textBlockLine.Text = "(${centerX},${centerY}) to (${corner.X},${corner.Y})"
$textBlockLine.Foreground = [Windows.Media.Brushes]::Gray
[Windows.Controls.Canvas]::SetLeft($textBlockLine, ($centerX + $corner.X) / 2)
[Windows.Controls.Canvas]::SetTop($textBlockLine, ($centerY + $corner.Y) / 2)
$canvas.Children.Add($textBlockLine)
}
}
$window.ShowDialog() | Out-Null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment