B4A Library Extracting Facial States and Facial Landmarks from a Bitmap (photo) using Google Mobile Vision API

It wraps this Github project. It extracts facial states and facial landmark information from a photo (bitmap) containing a human face. See the pic below...

Posting the following:
1. B4A project - b4aAndroidVisionPhotoFaceDetector.zip
2. The B4A library files (AndroidVisionFaceViewLibFiles.zip)
3. The java code as it stands at present (TheJavaCode.zip)
4. A link to all the other jars that will be required - download them from here and copy them to your additional library folder - https://www.dropbox.com/s/se5x5znl1tgpv6r/OtherLibFiles.zip?dl=0
5. resourceAdditionalLibFolder.zip - extract it and copy the resource folder to your additional library folder
6. resource.zip - extract it and copy the resource folder to the same folder level that of the /Files and /Objects folders of the B4A project.

You can download and test it but if you want to use it then you need to

1.png


Sample Code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: AndroidVisionPhotoFaceDetector
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#AdditionalRes: ..\resource
#AdditionalRes: C:\Users\----------2\Documents\Basic 4 Android\JOHAN APPS\JHS LIBS\resource\b4a_appcompat, de.amberhome.objects.appcompat
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design

#ExcludeClasses: .games, .drive, .ads, .fitness, .wearable, .measurement, .cast, .auth, .nearby
#ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .gcm, .maps, .panorama

#Extends: android.support.v7.app.AppCompatActivity

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Dim bm As Bitmap

    Private fv1 As AndroidVisionFaceView
    Private lv1 As ListView

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")

    lv1.SingleLineLayout.Label.TextSize = 15
    lv1.SingleLineLayout.Label.TextColor = Colors.White
    lv1.TwoLinesLayout.Label.TextSize = 15
    lv1.TwoLinesLayout.Label.TextColor = Colors.white
    bm.Initialize(File.DirAssets,"charlize.jpg")
    fv1.Photo = bm

    fv1.CircleColor = Colors.Magenta
    fv1.CircleWidth = 3
    fv1.CircleDiameter = 5

    fv1.build

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub fv1_face_found(LandMarks As Object, IsLeftEyeOpenProbability As Float, IsRightEyeOpenProbability As Float, _
                   IsSmilingProbability As Float, EulerY As Float, EulerZ As Float, iD As Int)


    lv1.AddSingleLine("face ID = " & iD)
    lv1.AddTwoLines("IsLeftEyeOpenProbability:", "" & IsLeftEyeOpenProbability)
    lv1.AddTwoLines("IsRightEyeOpenProbability:", "" & IsRightEyeOpenProbability)
    lv1.AddTwoLines("IsSmilingProbability:", "" & IsSmilingProbability)
    lv1.AddTwoLines("Rotation of face around vertical(Y) axis:", "" & EulerY)
    lv1.AddTwoLines("Rotation of face around Z axis:", "" & EulerZ)

    Dim mylist As List
    mylist = LandMarks
    For i = 0 To mylist.Size - 1
         If mylist.Get(i) = "0" Then lv1.AddSingleLine("Landmark found at BOTTOM_MOUTH")
      If mylist.Get(i) = "1" Then lv1.AddSingleLine("Landmark found at LEFT_CHEEK")
      If mylist.Get(i) = "2" Then lv1.AddSingleLine("Landmark found at LEFT_EAR_TIP")
      If mylist.Get(i) = "3" Then lv1.AddSingleLine("Landmark found at LEFT_EAR")
      If mylist.Get(i) = "4" Then lv1.AddSingleLine("Landmark found at LEFT_EYE")
      If mylist.Get(i) = "5" Then lv1.AddSingleLine("Landmark found at LEFT_MOUTH")
      If mylist.Get(i) = "6" Then lv1.AddSingleLine("Landmark found at NOSE_BASE")
      If mylist.Get(i) = "7" Then lv1.AddSingleLine("Landmark found at RIGHT_CHEEK")
      If mylist.Get(i) = "8" Then lv1.AddSingleLine("Landmark found at RIGHT_EAR_TIP")
      If mylist.Get(i) = "9" Then lv1.AddSingleLine("Landmark found at RIGHT_EAR")
      If mylist.Get(i) = "10" Then lv1.AddSingleLine("Landmark found at RIGHT_EYE")
      If mylist.Get(i) = "11" Then lv1.AddSingleLine("Landmark found at RIGHT_MOUTH")

    Next

    lv1.AddSingleLine("*********************************")

'  AN EXPLANATION FOR THE LANDMARK STRING VALUES THAT ARE RETURNED TO THE B4A LIST
'  Public static final int BOTTOM_MOUTH = 0;
'  Public static final int LEFT_CHEEK = 1;
'  Public static final int LEFT_EAR_TIP = 2;
'  Public static final int LEFT_EAR = 3;
'  Public static final int LEFT_EYE = 4;
'  Public static final int LEFT_MOUTH = 5;
'  Public static final int NOSE_BASE = 6;
'  Public static final int RIGHT_CHEEK = 7;
'  Public static final int RIGHT_EAR_TIP = 8;
'  Public static final int RIGHT_EAR = 9;
'  Public static final int RIGHT_EYE = 10;
'  Public static final int RIGHT_MOUTH = 11;


End Sub

Library:
AndroidVisionFaceView
Author:
Github: Clayton Wilkinson, Wrapped by: Johan Schoeman
Version: 1
AndroidVisionFaceView
Events:

  • face_found (LandMarks As Object, IsLeftEyeOpenProbability As Float, IsRightEyeOpenProbability As Float, IsSmilingProbability As Float, EulerY As Float, EulerZ As Float, iD As Int)
Fields:
  • ALL_LANDMARKS As Int
  • NO_LANDMARKS As Int
  • ba As BA
Methods:
  • BringToFront
  • DesignerCreateView (base As PanelWrapper, lw As LabelWrapper, props As Map)
  • Initialize (EventName As String)
  • Invalidate
  • Invalidate2 (arg0 As Rect)
  • Invalidate3 (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
  • IsInitialized As Boolean
  • RemoveView
  • RequestFocus As Boolean
  • SendToBack
  • SetBackgroundImage (arg0 As Bitmap)
  • SetColorAnimated (arg0 As Int, arg1 As Int, arg2 As Int)
  • SetLayout (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
  • SetLayoutAnimated (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int, arg4 As Int)
  • SetVisibleAnimated (arg0 As Int, arg1 As Boolean)
  • build
Permissions:
  • android.hardware.camera
  • android.hardware.camera.autofocus
  • android.permission.CAMERA
  • android.permission.FLASHLIGHT
  • android.permission.VIBRATE
  • android.permission.WRITE_EXTERNAL_STORAGE
Properties:
  • Background As Drawable
  • CircleColor As Int [write only]
  • CircleDiameter As Int [write only]
  • CircleWidth As Int [write only]
  • Color As Int [write only]
  • Enabled As Boolean
  • Height As Int
  • LandmarkType As Int [write only]
  • Left As Int
  • MinFaceSize As Float [write only]
  • Parent As Object [read only]
  • Photo As Bitmap [write only]
  • ProminentFaceOnly As Boolean [write only]
  • Tag As Object
  • Top As Int
  • Visible As Boolean
  • Width As Int
Important: Take note of all the files in the B4A project's /Objects/res/blabla folders. Make sure they are set to READ ONLY before you compile the project for the first time

Also important to note the B4A project's Manifest Files

And equally important to set your paths correctly (the below only applicable to my folder setup):

B4X:
#AdditionalRes: ..\resource[/I][/B]
[B][I]#AdditionalRes: C:\Users\----------2\Documents\Basic 4 Android\JOHAN APPS\JHS LIBS\resource\b4a_appcompat, de.amberhome.objects.appcompat
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design
 

Attachments

  • TheJavaCode.zip
    335.2 KB · Views: 583
  • resourceAdditionalLibFolder.zip
    775 bytes · Views: 580
  • resource.zip
    423 bytes · Views: 588
  • b4aAndroidVisionPhotoFaceDetector.zip
    37.1 KB · Views: 633
  • AndroidVisionFaceViewLibFiles.zip
    10.3 KB · Views: 618
Last edited:

danoptic

Member
Licensed User
Longtime User
I add new files to the resource app directory adn this what I get with the following #additionalres:
'#AdditionalRes: ..\resource\

'#AdditionalRes: C:\Users\Owner\Dropbox\basic4android\SourceCode\b4aAndroidVisionFaceTracker\resource\b4a_appcompat, de.amberhome.objects.appcompat
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
'#AdditionalRes: C:\Users\Owner\AppData\Local\Android\android-sdk\extras\google\m2repository\com\google\android\gms, com.google.android.gms
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design

#ExcludeClasses: .games, .drive, .ads, .fitness, .wearable, .measurement, .cast, .auth, .nearby
#ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .gcm, .maps, .panorama

#Extends: android.support.v7.app.AppCompatActivity



B4A version: 6.00
Parsing code. (0.00s)
Compiling code. (0.06s)
Compiling layouts code. (0.04s)
Organizing libraries. (3.09s)
Generating R file. Error
AndroidManifest.xml:21: error: Error: No resource found that matches the given name (at 'theme' with value '@style/MyAppTheme').
AndroidManifest.xml:26: error: Error: No resource found that matches the given name (at 'value' with value '@Integer/google_play_services_version').
 

Johan Schoeman

Expert
Licensed User
Longtime User
I add new files to the resource app directory adn this what I get with the following #additionalres:
'#AdditionalRes: ..\resource\

'#AdditionalRes: C:\Users\Owner\Dropbox\basic4android\SourceCode\b4aAndroidVisionFaceTracker\resource\b4a_appcompat, de.amberhome.objects.appcompat
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
'#AdditionalRes: C:\Users\Owner\AppData\Local\Android\android-sdk\extras\google\m2repository\com\google\android\gms, com.google.android.gms
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design

#ExcludeClasses: .games, .drive, .ads, .fitness, .wearable, .measurement, .cast, .auth, .nearby
#ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .gcm, .maps, .panorama

#Extends: android.support.v7.app.AppCompatActivity



B4A version: 6.00
Parsing code. (0.00s)
Compiling code. (0.06s)
Compiling layouts code. (0.04s)
Organizing libraries. (3.09s)
Generating R file. Error
AndroidManifest.xml:21: error: Error: No resource found that matches the given name (at 'theme' with value '@style/MyAppTheme').
AndroidManifest.xml:26: error: Error: No resource found that matches the given name (at 'value' with value '@Integer/google_play_services_version').
Look at the folder structure of the B4A projects in post #1 and post #7, what they contain, and edit them to see what is going on. Also take a look at the B4A manifest file.

There are a few golden rules to follow when you download a project:
1. See if there is anything out of the ordinary in the B4A manifest file
2. Check and additional resources added to the B4A project (in this case \resource)
3. Check how these additional resources tie up with anything in the B4A manifest
4. Check the B4A project's /Objects/res/blabla folders (values, layouts, drawable, xml, etc) if there is anything that you need to add to a new project.
5.Make sure that the properties of any files in (at least) the folders mentioned in (4) above are set to READ ONLY

If you follow these rules you will have success.
 

okadakadasam

New Member
so witch SDK to use?

this is the full #additionalres. with what to replace it?

'#AdditionalRes: ..\resource\

#AdditionalRes: C:\Users\Owner\Dropbox\basic4android\SourceCode\b4aAndroidVisionFaceTracker\resource\b4a_appcompat, de.amberhome.objects.appcompat
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
#AdditionalRes: C:\Users\Owner\AppData\Local\Android\android-sdk\extras\google\m2repository\com\google\android\gms, com.google.android.gms
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design



"

PLEASE, where I find these files, I can't help them help me, it would be possible to send them here ?

"
 

Johan Schoeman

Expert
Licensed User
Longtime User
Done with B4A V9.80
Lib files attached
B4A sample project attached


No need for this any more - it is commented out in the attached B4A project:
B4X:
'#AdditionalRes: C:\Users\----------2\Documents\Basic 4 Android\JOHAN APPS\JHS LIBS\resource\b4a_appcompat, de.amberhome.objects.appcompat
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms
'#AdditionalRes: C:\ANDRIOD_SDK_TOOLS\extras\android\support\design\res, android.support.design
'
'#ExcludeClasses: .games, .drive, .ads, .fitness, .wearable, .measurement, .cast, .auth, .nearby
'#ExcludeClasses: .tagmanager, .analytics, .wallet, .plus, .gcm, .maps, .panorama

'#Extends: android.support.v7.app.AppCompatActivity

1.png

B4A sample code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: AndroidVisionPhotoFaceDetector
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
    #MultiDex: True
#End Region

#AdditionalRes: ..\resource

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    
    Dim bm As Bitmap

    Private fv1 As AndroidVisionFaceView
    Private lv1 As ListView
    Dim sf As StringFunctions
    
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
    
    sf.Initialize
    
    lv1.SingleLineLayout.Label.TextSize = 15
    lv1.SingleLineLayout.Label.TextColor = Colors.White   
    lv1.TwoLinesLayout.Label.TextSize = 15
    lv1.TwoLinesLayout.Label.TextColor = Colors.white
    bm.Initialize(File.DirAssets,"three.jpg")
    fv1.Photo = bm
    
    fv1.CircleColor = Colors.Cyan
    fv1.CircleWidth = 3
    fv1.CircleDiameter = 5
    
    fv1.MinFaceSize = 0.1                       
    fv1.ShowFaceIds = True

    fv1.build
    
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub fv1_face_found(LandMarks As Object)
        
    Dim mylist As List
    mylist = LandMarks
    Dim lm As Int = sf.Val(mylist.Get(mylist.Size - 1))
    lv1.AddSingleLine("face ID = " & mylist.Get(mylist.Size - 2))
    For i = 0 To lm - 1
      If mylist.Get(i) = "0" Then lv1.AddSingleLine("Landmark found at BOTTOM_MOUTH")   
      If mylist.Get(i) = "1" Then lv1.AddSingleLine("Landmark found at LEFT_CHEEK")
      If mylist.Get(i) = "2" Then lv1.AddSingleLine("Landmark found at LEFT_EAR_TIP")
      If mylist.Get(i) = "3" Then lv1.AddSingleLine("Landmark found at LEFT_EAR")
      If mylist.Get(i) = "4" Then lv1.AddSingleLine("Landmark found at LEFT_EYE")
      If mylist.Get(i) = "5" Then lv1.AddSingleLine("Landmark found at LEFT_MOUTH")
      If mylist.Get(i) = "6" Then lv1.AddSingleLine("Landmark found at NOSE_BASE")
      If mylist.Get(i) = "7" Then lv1.AddSingleLine("Landmark found at RIGHT_CHEEK")
      If mylist.Get(i) = "8" Then lv1.AddSingleLine("Landmark found at RIGHT_EAR_TIP")
      If mylist.Get(i) = "9" Then lv1.AddSingleLine("Landmark found at RIGHT_EAR")
      If mylist.Get(i) = "10" Then lv1.AddSingleLine("Landmark found at RIGHT_EYE")
      If mylist.Get(i) = "11" Then lv1.AddSingleLine("Landmark found at RIGHT_MOUTH")
    Next
    lv1.AddTwoLines("Rotation of face around vertical(Y) axis:", "" & mylist.Get(i))
    lv1.AddTwoLines("Rotation of face around Z axis:", "" & mylist.Get(i+1))
    lv1.AddTwoLines("IsLeftEyeOpenProbability:", "" & mylist.Get(i+2))
    lv1.AddTwoLines("IsRightEyeOpenProbability:", "" & mylist.Get(i+3))
    lv1.AddTwoLines("IsSmilingProbability:", "" & mylist.Get(i+4))
    lv1.AddSingleLine("No of LandMarks = " & mylist.Get(i+6))
    lv1.AddSingleLine("*********************************")

End Sub

Extract resource.zip and copy the folder and its contents to be on the same folder level as that of the /Objects and /Files folders of the B4A project.
Extract the B4A jar and xml lib files and copy them to your additional library folder (should show as V1.03 in the libs tab of the B4A IDE)
 

Attachments

  • resource.zip
    423 bytes · Views: 412
  • AndroidVisionFaceViewLibFilesV1.03.zip
    10.9 KB · Views: 369
  • b4aAndroidVisionPhotoFaceDetector.zip
    138.1 KB · Views: 365

PodSoft2016

Member
hi. tnx alot for your good library. i have a problem with compiling project. had this error.
Maven artifact not found: androidx.annotation/annotation-experimental
it occurs on 1.1 version of library. i update android marven and androidx resources. but error happened yet.
as erel said i did, sdk manager doesnt show annotation-experimental for me at all.
any body has any solution? Thanks alot.
 

PodSoft2016

Member
hello to all. Excuse me for my questions. but now i have a problem during loading this project.
error log is:

main_activity_create (java line: 352)
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:170)
at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
at JHS.b4aAndroidVisionPhotoFaceDetector.main._activity_create(main.java:352)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
at JHS.b4aAndroidVisionPhotoFaceDetector.main.afterFirstLayout(main.java:105)
at JHS.b4aAndroidVisionPhotoFaceDetector.main.access$000(main.java:17)
at JHS.b4aAndroidVisionPhotoFaceDetector.main$WaitForLayout.run(main.java:83)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:64)
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:162)
... 14 more
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.google.android.gms.vision.face.Face.getId()' on a null object reference
at com.google.android.gms.samples.vision.face.photo.FaceView.getId(FaceView.java:187)
at android.view.ForceDarkHelper.updateForceDarkForView(ForceDarkHelper.java:264)
at android.view.View.<init>(View.java:5789)
at android.view.View.<init>(View.java:5196)
at android.view.View.<init>(View.java:5175)
at com.google.android.gms.samples.vision.face.photo.FaceView.<init>(FaceView.java:47)
at photowrapper.photoWrapper._initialize(photoWrapper.java:79)

it seems Face.Getid function is the error reason.

By the way Library version Is 1.01 And Not 1.03!!!

Can any body solve this problem
Tnx a lot.
 
Last edited:
Top