B4A Class CamEx class with Face Tracking and more error handling

So the basics of this variant of the CamEx class is I added some error handling, so that subs called before the camera is ready won't crash the program. And you can be sure you're actually getting data by checking CamEx.CameraIsReady.

CommitParameters is called automatically in a few places, and the Panel is made visible automatically to prevent some annoying bug hunts I ran into.

I merged some really helpful stuff like PreviewImageToJpeg, PreviewImageToBMP, and BytesToBmp (converts preview bytes directly to a BMP without writing to a file)

But the biggest feature is the Face Detection. We've had the functions before, but Android uses a (deliberately?) obfuscated coordinate system that:
-is not what the documentation claims (-1000 to 1000)
-varies wildly between different devices (Xperia devices start at 0 instead of -1000)
-varies wildly between different orientations (you can't even apply simple math to rotate it yourself)

So I came up with a method that automatically calibrates the coordinate system, and saves it to to the Android folder (so every program using this code can use the same settings file) only when the data is changed, when you shut the camera down.

Basically, all the user has to do is move their face into each of the 4 corners, for each of the device's orientations. This step isn't required as it'll naturally calibrate over time, but this speeds up the process.

I don't have access to the eye/mouth coordinates yet, as Google's documentation on that is also wrong.

The usage is roughly the same as the existing CamEx class.

B4X:
Sub camera_Ready (Success As Boolean)
   Log("CAMERA IS " & IIF(Success, "READY", "NOT READY"))
   If Success Then
     Log("ACLpanel: " & ACLpanel.Visible & " @ " & ACLpanel.Top & "," & ACLpanel.Left & " - " & ACLpanel.Width & "x" & ACLpanel.Height)
     If camEx.IsInitialized Then
       Try
         camEx.StartPreview
         camEx.StartFaceDetection 'This will start face detection, if it's supported
         'If Graphics.ColorEffect.Length>0 Then camEx.SetColorEffect2(Graphics.ColorEffect)
       Catch
         camera_Ready(False)
       End Try
     End If
   End If
End Sub

Sub camera_FaceDetected(Face As Face)
   Log("FACE: X=" & Face.Location.Left & ", Y=" & Face.Location.Top & ", W=" & Face.Location.Width & ", H=" & Face.Location.Height)
End Sub

'picwidth/height is the size of the image itself (src, before)
'thumbwidth/height is the desired/maximum dimensions (dest, after)
'forcefit expands smaller images to fit picwidth/height while retaining the aspect ratio (ie: letterboxing/pillarboxing)
'forcefull expands smaller images to fill the entire picwidth/height leaving no border, destroying the aspect ratio
Sub Thumbsize(PicWidth As Int, PicHeight As Int, thumbwidth As Int, thumbheight As Int, ForceFit As Boolean, ForceFull As Boolean)As Point
   Dim Temp As Point
   Temp.X=PicWidth
   Temp.Y=PicHeight
  If ForceFit Then
  If Temp.Y < thumbheight Then
  Temp.X = Temp.X * thumbheight / Temp.Y
  Temp.Y = thumbheight
  End If
  End If
  If Temp.X > thumbwidth Then
  Temp.Y = Temp.Y / (Temp.X / thumbwidth)
  Temp.X = thumbwidth
  End If
  If Temp.Y > thumbheight Then
  Temp.X = Temp.X / (Temp.Y / thumbheight)
  Temp.Y = Temp.Y / (Temp.Y / thumbheight)
  End If
  If ForceFull Then
  If Temp.X < thumbwidth Then
  Temp.Y = Temp.Y * (thumbwidth / Temp.X)
  Temp.X = thumbwidth
  End If
  If Temp.Y < thumbheight Then
  Temp.X = Temp.X * (thumbheight / Temp.Y)
  Temp.Y = Temp.Y * (thumbheight / Temp.Y)
  End If
  End If
   Return Temp
End Sub


Sub IIF(Value As Boolean , IFtrue, IfFalse)
   If Value Then Return IFtrue
   Return IfFalse
End Sub

EDIT: Points removed
 

Attachments

  • CameraExClass.bas
    30.6 KB · Views: 396
Last edited:

NeoTechni

Well-Known Member
Licensed User
Longtime User
In any of your Sub Process_Globals, but it'd be better to leave it in the module's so everything is together.
 
Top