Last active
June 9, 2024 12:35
-
-
Save markgodiy/85a7c40ede5d468d05dcb98ebc471217 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| 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