Face detection with UWP API (Win10)

Post your working scripts, libraries and tools for AHK v1.1 and older
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Face detection with UWP API (Win10)

22 Feb 2020, 20:29

https://docs.microsoft.com/en-us/uwp/api/windows.media.faceanalysis
The larger the picture is, the longer, but possibly more accurately recognition will be.
The maxheight: = 2000 parameter means that if the image height is more than 2000 pixels, the encoder will reduce it to 2000.
This parameter You can change depending on Your needs.

Code: Select all

msgbox % facedetect("face.jpg")
ExitApp



facedetect(file, maxheight := 2000)
{
   static BitmapDecoderStatics, BitmapTransform, SoftwareBitmapStatics, FaceDetector, SupportedBitmapPixelFormats
   if (FaceDetector = "")
   {
      CreateClass("Windows.Graphics.Imaging.BitmapDecoder", IBitmapDecoderStatics := "{438CCB26-BCEF-4E95-BAD6-23A822E58D01}", BitmapDecoderStatics)
      CreateClass("Windows.Graphics.Imaging.BitmapTransform",, BitmapTransform)
      CreateClass("Windows.Graphics.Imaging.SoftwareBitmap", ISoftwareBitmapStatics := "{DF0385DB-672F-4A9D-806E-C2442F343E86}", SoftwareBitmapStatics)
      CreateClass("Windows.Media.FaceAnalysis.FaceDetector", IFaceDetectorStatics := "{BC042D67-9047-33F6-881B-6746C1B218B8}", FaceDetectorStatics)
      DllCall(NumGet(NumGet(FaceDetectorStatics+0)+6*A_PtrSize), "ptr", FaceDetectorStatics, "ptr*", FaceDetector)   ; CreateAsync
      WaitForAsync(FaceDetector)
      DllCall(NumGet(NumGet(FaceDetectorStatics+0)+7*A_PtrSize), "ptr", FaceDetectorStatics, "ptr*", ReadOnlyList)   ; GetSupportedBitmapPixelFormats
      DllCall(NumGet(NumGet(ReadOnlyList+0)+7*A_PtrSize), "ptr", ReadOnlyList, "int*", count)   ; count
      loop % count
      {
         DllCall(NumGet(NumGet(ReadOnlyList+0)+6*A_PtrSize), "ptr", ReadOnlyList, "int", A_Index-1, "uint*", BitmapPixelFormat)   ; get_Item
         SupportedBitmapPixelFormats .= "|" BitmapPixelFormat "|"
      }
      ObjRelease(FaceDetectorStatics)
      ObjRelease(ReadOnlyList)
   }
   if (SubStr(file, 2, 1) != ":")
      file := A_ScriptDir "\" file
   if !FileExist(file) or InStr(FileExist(file), "D")
   {
      msgbox File "%file%" does not exist
      ExitApp
   }   
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", IID_RandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", &GUID)
   DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", file, "uint", Read := 0, "ptr", &GUID, "ptr*", IRandomAccessStream)
   DllCall(NumGet(NumGet(BitmapDecoderStatics+0)+14*A_PtrSize), "ptr", BitmapDecoderStatics, "ptr", IRandomAccessStream, "ptr*", BitmapDecoder)   ; CreateAsync
   WaitForAsync(BitmapDecoder)
   BitmapFrame := ComObjQuery(BitmapDecoder, IBitmapFrame := "{72A49A1C-8081-438D-91BC-94ECFC8185C6}")
   DllCall(NumGet(NumGet(BitmapFrame+0)+12*A_PtrSize), "ptr", BitmapFrame, "uint*", width)   ; get_PixelWidth
   DllCall(NumGet(NumGet(BitmapFrame+0)+13*A_PtrSize), "ptr", BitmapFrame, "uint*", height)   ; get_PixelHeight
   DllCall(NumGet(NumGet(BitmapFrame+0)+8*A_PtrSize), "ptr", BitmapFrame, "uint*", BitmapPixelFormat)   ; get_BitmapPixelFormat
   BitmapFrameWithSoftwareBitmap := ComObjQuery(BitmapDecoder, IBitmapFrameWithSoftwareBitmap := "{FE287C9A-420C-4963-87AD-691436E08383}")
   if (height > maxheight)
   {
      DllCall(NumGet(NumGet(BitmapTransform+0)+7*A_PtrSize), "ptr", BitmapTransform, "int", floor(maxheight/height*width))   ; put_ScaledWidth
      DllCall(NumGet(NumGet(BitmapTransform+0)+9*A_PtrSize), "ptr", BitmapTransform, "int", maxheight)   ; put_ScaledHeight
      DllCall(NumGet(NumGet(BitmapFrameWithSoftwareBitmap+0)+8*A_PtrSize), "ptr", BitmapFrameWithSoftwareBitmap, "uint", BitmapPixelFormat, "uint", Premultiplied := 0, "ptr", BitmapTransform, "uint", IgnoreExifOrientation := 0, "uint", DoNotColorManage := 0, "ptr*", SoftwareBitmap)   ; GetSoftwareBitmapTransformedAsync
   }
   else
      DllCall(NumGet(NumGet(BitmapFrameWithSoftwareBitmap+0)+6*A_PtrSize), "ptr", BitmapFrameWithSoftwareBitmap, "ptr*", SoftwareBitmap)   ; GetSoftwareBitmapAsync
   WaitForAsync(SoftwareBitmap)
   if !InStr(SupportedBitmapPixelFormats, "|" BitmapPixelFormat "|")
   {
      DllCall(NumGet(NumGet(SoftwareBitmapStatics+0)+7*A_PtrSize), "ptr", SoftwareBitmapStatics, "ptr", SoftwareBitmap, "uint", Gray8 := 62, "ptr*", SoftwareBitmapTemp)   ; Convert
      Close := ComObjQuery(SoftwareBitmap, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
      DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
      ObjRelease(Close)
      ObjRelease(SoftwareBitmap)
      SoftwareBitmap := SoftwareBitmapTemp
   }
   DllCall(NumGet(NumGet(FaceDetector+0)+6*A_PtrSize), "ptr", FaceDetector, ptr, SoftwareBitmap, "ptr*", DetectedFaceList)   ; DetectFacesAsync
   WaitForAsync(DetectedFaceList)
   DllCall(NumGet(NumGet(DetectedFaceList+0)+7*A_PtrSize), "ptr", DetectedFaceList, "int*", count)   ; count
   loop % count
   {
      varsetcapacity(bounds, 16, 0)
      DllCall(NumGet(NumGet(DetectedFaceList+0)+6*A_PtrSize), "ptr", DetectedFaceList, "int", A_Index-1, "ptr*", DetectedFace)   ; get_Item
      DllCall(NumGet(NumGet(DetectedFace+0)+6*A_PtrSize), "ptr", DetectedFace, "ptr", &bounds)   ; BitmapBounds
      x := numget(bounds, 0, "uint")
      y := numget(bounds, 4, "uint")
      width := numget(bounds, 8, "uint")
      height := numget(bounds, 12, "uint")
      result .= "face" A_Index ": x=" x ", y=" y ", width=" width ", height=" height "`n"
      ObjRelease(DetectedFace)
   }
   Close := ComObjQuery(IRandomAccessStream, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
   DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
   ObjRelease(Close)
   Close := ComObjQuery(SoftwareBitmap, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
   DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
   ObjRelease(Close)
   ObjRelease(IRandomAccessStream)
   ObjRelease(BitmapDecoder)
   ObjRelease(BitmapFrame)
   ObjRelease(BitmapFrameWithSoftwareBitmap)
   ObjRelease(SoftwareBitmap)
   ObjRelease(DetectedFaceList)
   return result
}



CreateClass(string, interface := "", ByRef Class := "")
{
   CreateHString(string, hString)
   if (interface = "")
      result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
   else
   {
      VarSetCapacity(GUID, 16)
      DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
      result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   }
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object)
{
   AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
   loop
   {
      DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
      if (status != 0)
      {
         if (status != 1)
         {
            DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
            msgbox AsyncInfo status error: %ErrorCode%
            ExitApp
         }
         ObjRelease(AsyncInfo)
         break
      }
      sleep 10
   }
   DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
   ObjRelease(Object)
   Object := ObjectResult
}
Last edited by malcev on 05 May 2023, 07:18, edited 3 times in total.
blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: Face detection with UWP API (Win10)

24 Feb 2020, 14:36

Hi @malcev,

is it possible use this with real time video camera and guess lets say how many people is in some room at the moment or even better in one or more parts of that room?

I can do it in Python, but something similar with ahk would be even better.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

24 Feb 2020, 15:53

I wrote some time ago script that captures video from camcorder.
If it works for You then I think it is possible.
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=71142
Also here is example how to capture and detect directly in UWP, but I think that I could not translate it to ahk, because do not know how to get dispatcher.
https://github.com/microsoft/Windows-universal-samples/blob/dev/Samples/CameraFaceDetection/cs/MainPage.xaml.cs
User avatar
elModo7
Posts: 217
Joined: 01 Sep 2017, 02:38
Location: Spain
Contact:

Re: Face detection with UWP API (Win10)

25 Feb 2020, 08:26

Works like charm, thanks for sharing @malcev
I also love your webcam capture script and the ocr one!
Will check out UWP API deeper.
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Face detection with UWP API (Win10)

28 Mar 2020, 12:47

Hello, malcev!

I just tested the function and i get.... «no valid com object» and it exits.

If I remove all ExitApp commands, I get that error for each ComObjQuery. I am running latest Windows 10 stable.

Thank you very much .

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

28 Mar 2020, 14:41

Strange. What version of windows do You have?

Code: Select all

msgbox % a_osversion
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Face detection with UWP API (Win10)

28 Mar 2020, 15:39

I am running: Windows v10.0.18363. .....and AHK v1.1.30.

Thank you .
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

28 Mar 2020, 15:58

If You run this code - will You get error?

Code: Select all

CreateClass("Windows.Graphics.Imaging.BitmapDecoder", IBitmapDecoderStatics := "{438CCB26-BCEF-4E95-BAD6-23A822E58D01}", BitmapDecoderStatics)
CreateClass("Windows.Graphics.Imaging.BitmapEncoder", IBitmapEncoderStatics := "{A74356A7-A4E4-4EB9-8E40-564DE7E1CCB2}", BitmapEncoderStatics)
CreateClass("Windows.Graphics.Imaging.SoftwareBitmap", ISoftwareBitmapStatics := "{DF0385DB-672F-4A9D-806E-C2442F343E86}", SoftwareBitmapStatics)
CreateClass("Windows.Media.FaceAnalysis.FaceDetector", IFaceDetectorStatics := "{BC042D67-9047-33F6-881B-6746C1B218B8}", FaceDetectorStatics)
msgbox all ok



CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}


CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Face detection with UWP API (Win10)

28 Mar 2020, 16:24

I do not get any error with the new code. I get, «all ok» ;-).
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

28 Mar 2020, 17:11

I updated 1st post.
Will it work now?
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Face detection with UWP API (Win10)

29 Mar 2020, 03:18

Hello!

Yes, it works now. Thank you very much !

However , have you tested it with various photographs ? I find many where it does not identify any face. About 50% of the photographs with faces I tested it with, no face detected.

The algorithm seems to be... very poor.

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

29 Mar 2020, 07:26

No, I did not test it much.
You can compare results with opencv:
https://www.autohotkey.com/boards/viewtopic.php?p=299604#p299604
Or translate this library
https://autoit.de/thread/86499-facedetection-udf/
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Face detection with UWP API (Win10)

30 Mar 2020, 07:53

Thank you. I'll look into those as well.

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
Malek_Necibi
Posts: 4
Joined: 24 Oct 2017, 20:47

Re: Face detection with UWP API (Win10)

26 Mar 2021, 13:23

So sorry to re-awaken an old thread, but I need some help understanding something from this.

I've seen the CreateClass() used about 3 times on the forum to call the UWP/Runtime API, but I can't seem to find it's origin. Specifically, I can't
find where the 32-byte interface id strings passed as the 2nd parameter to CreateClass() comes from, because they each seem unique to specific operations. If you could direct me to where I can find more info on CreateClass() and/or where I could find a list of interface id's I'd be so grateful.


P.S. I've been using ahk regularly for about 5 years, but this is my first ever post. Thanks for bearing with me!
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Face detection with UWP API (Win10)

26 Mar 2021, 14:15

For example here
https://docs.microsoft.com/en-us/uwp/api/windows.media.faceanalysis.facedetector?view=winrt-19041
we see
[Windows.Foundation.Metadata.ContractVersion(typeof(Windows.Foundation.UniversalApiContract), 65536)]
[Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
[Windows.Foundation.Metadata.Threading(Windows.Foundation.Metadata.ThreadingModel.Both)]
[Windows.Foundation.Metadata.Static(typeof(Windows.Media.FaceAnalysis.IFaceDetectorStatics), 65536, "Windows.Foundation.UniversalApiContract")]
public sealed class FaceDetector
Windows.Foundation.Metadata.Static - means interface with static methods
https://docs.microsoft.com/en-us/uwp/api/windows.foundation.metadata?view=winrt-19041
To find its guid we can go to
https://github.com/tpn/winsdk-10/tree/master/Include/10.0.14393.0/winrt
find our namespace
https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/winrt/windows.media.faceanalysis.h
and find our interface
MIDL_INTERFACE("BC042D67-9047-33F6-881B-6746C1B218B8")
IFaceDetectorStatics : public IInspectable
Malek_Necibi
Posts: 4
Joined: 24 Oct 2017, 20:47

Re: Face detection with UWP API (Win10)

26 Mar 2021, 16:57

Thank you so much for your help. I just managed to get my little Biometric Verification script up and running, and its working beautifully.

While I have you here, do you have any idea why the methods seem to all index from 6? (Like in the +6*A_PtrSize) At first I thought it might be because the interface objects are constant size, but that doesn't seem right because the the methods are double pointers inside the interfaces so they're in different memory space... Maybe I'm just missing something basic here, but nonetheless thanks again for the help!

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Google [Bot] and 205 guests