Giter VIP home page Giter VIP logo

shubham0204 / facerecognition_with_facenet_android Goto Github PK

View Code? Open in Web Editor NEW
241.0 9.0 84.0 377.81 MB

Face Recognition using the FaceNet model and MLKit on Android.

Home Page: https://towardsdatascience.com/using-facenet-for-on-device-face-recognition-with-android-f84e36e19761

License: Apache License 2.0

Kotlin 100.00%
android android-application android-studio machine-learning face-recognition tensorflow2 kotlin kotlin-android face-detection facenet-model

facerecognition_with_facenet_android's Introduction

Face Recognition and Classification With FaceNet On Android

Store images of people who you would like to recognize and the app, using these images, will classify those people. We don't need to modify the app/retrain any ML model to add more people ( subjects ) for classification

banner

Message from the developer,

You may also like my latest project -> Age + Gender Estimation in Android with TensorFlow. I'm open for freelancing in Android + ML projects as well as Technical Blogging. You may send me an email/message on Google Chat at [email protected].

Features

  • Asynchronous processing with Kotlin Coroutines
  • Quick labelling of faces with C++ computation (See native branch)
  • Use of latest Android development practices with configurable camera facing, GPU usage and mask detection.

Working of the app

If you're ML developer, you might have heard about FaceNet, Google's state-of-the-art model for generating face embeddings. In this
project, we'll use the FaceNet model on Android and generate embeddings ( fixed size vectors ) which hold information of the face.

The accuracy of the face detection system ( with FaceNet ) may not have a considerable accuracy. Make sure you explore other options as well while considering your app's production.

FaceNet

Working of the FaceNet model

So, the aim of the FaceNet model is to generate a 128 dimensional vector of a given face. It takes in an 160 * 160 RGB image and
outputs an array with 128 elements. How is it going to help us in our face recognition project?
Well, the FaceNet model generates similar face vectors for similar faces. Here, by the term "similar", we mean
the vectors which point out in the same direction. In this app, we'll generate two such vectors and use a suitable metric to compare them ( either L2norm or cosine similarity ). The one which is the closest will form our desired output.

You can download the FaceNet Keras .h5 file from this repo and TFLite model from the assets folder.

Usage

Intended File Structure

So, an user can store images in his/her device in a specific folder. If, for instance, the user wants the app to recognize
two people namely "Rahul" and "Neeta". So the user needs to store the images by creating two directories namely "Rahul" and "Neeta"
and store their images inside of these directories. For instance, the file structure for the working example ( as shown above in the GIF ),

Intended File Structure

The app will then process these images and classify these people thereafter. For face recognition, Firebase MLKit is used which
fetches bounding boxes for all the faces present in the camera frame.

For better performance, we recommend developers to use more images of the subjects, they need to recognize.

Working

Sample Prediction

The app's working is described in the steps below:

  1. Scan the images folder present in the internal storage. Next, parse all the images present within images folder and store
    the names of sub directories within images. For every image, collect bounding box coordinates ( as a Rect ) using MLKit. Crop the face from the image ( the one which was collected from user's storage ) using the bounding box coordinates.

  2. Finally, we have a list of cropped Bitmap of the faces present in the images. Next, feed the cropped Bitmap to the FaceNet
    model and get the embeddings ( as FloatArray ). Now, we create a HashMap<String,FloatArray> object where we store the names of
    the sub directories as keys and the embeddings as their corresponding values.

See MainActivity.kt and FileReader.kt for the code.

The above procedure is carried out only on the app's startup. The steps below will execute on each camera frame.

  1. Using androidx.camera.core.ImageAnalysis, we construct a FrameAnalyser class which processes the camera frames. Now, for a
    given frame, we first get the bounding box coordinates ( as a Rect ) of all the faces present in the frame. Crop the face from
    the frame using these boxes.
  2. Feed the cropped faces to the FaceNet model to generate embeddings for them. We compare the embedding with a suitable metric and form clusters for each user. We compute the average score for each cluster. The cluster with the best score is our output. The final output is then stored as a Prediction and passed to the BoundingBoxOverlay which draws boxes and
    text.
  3. For multiple images for a single user, we compute the score for each image. An average score is computed for each group. The group with the best score is chosen as the output. See FrameAnalyser.kt.
images ->  
    Rahul -> 
         image_rahul_1.png -> score=0.6 --- | average = 0.65 --- |
         image_rahul_2.png -> score=0.5 ----|                    | --- output -> "Rahul"
    Neeta ->                                                     |
         image_neeta_1.png -> score=0.4 --- | average = 0.35 --- |
         image_neeta_2.png -> score=0.3 ----|             

See FaceNetModel.kt and FrameAnalyser.kt for the code.

Limitations

Predictions may go wrong as FaceNet does not always produce similar embeddings for the same person. Consider the accuracy of the FaceNet model while using it in your apps. In that case, you may learn to use the FaceNetModel class separating for using FaceNet in some other tasks.

Important Resources

facerecognition_with_facenet_android's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

facerecognition_with_facenet_android's Issues

TfLiteGpuDelegate Invoke: GpuDelegate must run on the same thread

FATAL EXCEPTION: main
Process: com.ml.quaterion.facenetdetection, PID: 11467
java.lang.IllegalArgumentException: Internal error: Failed to run on the given Interpreter: Can not open OpenCL library on this device - dlopen failed: library "libOpenCL.so" not found
Falling back to OpenGL
TfLiteGpuDelegate Invoke: GpuDelegate must run on the same thread where it was initialized.
Node number 181 (TfLiteGpuDelegateV2) failed to invoke.
at org.tensorflow.lite.NativeInterpreterWrapper.run(Native Method)
at org.tensorflow.lite.NativeInterpreterWrapper.run(NativeInterpreterWrapper.java:249)
at org.tensorflow.lite.InterpreterImpl.runForMultipleInputsOutputs(InterpreterImpl.java:133)
at org.tensorflow.lite.Interpreter.runForMultipleInputsOutputs(Interpreter.java:80)
at org.tensorflow.lite.InterpreterImpl.run(InterpreterImpl.java:126)
at org.tensorflow.lite.Interpreter.run(Interpreter.java:80)
at com.ml.quaterion.facenetdetection.model.FaceNetModel.runFaceNet(FaceNetModel.kt:87)
at com.ml.quaterion.facenetdetection.model.FaceNetModel.getFaceEmbedding(FaceNetModel.kt:79)
at com.ml.quaterion.facenetdetection.FileReader$getEmbedding$2.invokeSuspend(FileReader.kt:108)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a0c68f4, Dispatchers.Main]

I am getting same name for every image in the frame

HI i am getting same name for every image i.e., first image name. may i know what is the problem. Please inform me is there any issue with code? If that face doesn't added in the folder also it is showing random name

Recognition is not happening

I've created the images folder as you mentioned in ReadMe document but still face recognition is not happening. I'm getting following logs

2020-09-14 22:31:51.541 26060-26060/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:51.550 26060-26060/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:51.564 26060-26060/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:51.589 26060-26093/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "persist.vendor.camera.privapp.list"
2020-09-14 22:31:51.603 26060-26078/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:51.603 26060-26078/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:51.722 26060-26093/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "persist.vendor.camera.privapp.list"
2020-09-14 22:31:51.733 26060-26078/com.ml.quaterion.facenetdetection E/libc: Access denied finding property "vendor.camera.aux.packagelist"
2020-09-14 22:31:52.414 26060-26212/com.ml.quaterion.facenetdetection E/Infoooooooooooooo: 90
2020-09-14 22:31:53.088 26060-26212/com.ml.quaterion.facenetdetection E/Infoooooooooooooo: 90

[request] write detection log to a file

I apologize for asking something so basic.

How can I save in a local text file the name of the faces that the application has detected?

Thank you very much for your help.

Works incorrectly in samsung A21s

App working correctly on all devices I have, but somehow on Samsung A21s, it is producing incorrect results.
It is nearly producing same output for all faces probability between .2 .3, for l2, cosine is also the same.

I thought maybe camera is the problem, so I embedded the pictures inside drawable and matched, but still it is producing nearly the same results for everything.

I noticed FloatArray returned from getCroppedFaceEmbedding producing different results for different phones.

My xiaomi mi9 works alright.

Do you have any ideas?

[issue] Always assign a face even if the image does not exist.

I've done the following test.

I take a photograph of a person (my friend Tom) and put it in his folder. I open the app and the app reads the folder (I only have one person).

ok, the app recognizes all people like Tom, shouldn't it show a warning that his photograph is missing or directly ignore those people?

(if necessary I can record a video showing it to you)

best regards.

Thread Exception: Only the original thread that created a view hierarchy can touch its views

Hi I am trying to run it on API 21, But in FrameAnalyser.kt line no 164 boundingBoxOverlay.invalidate() will through exception.
Please help me I am a beginner Thanks in advance.

E/AndroidRuntime: FATAL EXCEPTION: Thread-3
Process: com.example.facerecognition, PID: 12921
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7809)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1338)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5446)
at android.view.View.invalidateInternal(View.java:14749)
at android.view.View.invalidate(View.java:14713)
at android.view.View.invalidate(View.java:14697)
at com.example.facerecognition.FrameAnalyser$analyze$1$1.run(FrameAnalyser.kt:150)
at java.lang.Thread.run(Thread.java:762)

[Error] : Getting facelist.size as 0 in FrameAnalyser.kt

Hi, i am getting facelist.size is ''0'' . may i know why this is coming.
After that one i am getting this log I/Model: Average score for each user : {}
and then it is going into cache the error in cache was

E/Model: Exception in FrameAnalyser : null

Can you explain why this is going to cache and what i have to do to work the sample properly.

I am using using your latest code.
once the app is launched it cannot show the bounding box over the face.

Please solve my issue as possible as fast.

Application of tflite models and how to convert them.

Hi, I encounter the following error when using a tflite model that has been converted and quantized by toco.

Process: com.ml.quaterion.facenetdetection, PID: 4034
java.lang.IllegalArgumentException: Cannot copy to a TensorFlowLite tensor (input) with 76800 bytes from a Java Buffer with 307200 bytes.
at org.tensorflow.lite.TensorImpl.throwIfSrcShapeIsIncompatible(TensorImpl.java:416)
at org.tensorflow.lite.TensorImpl.setTo(TensorImpl.java:140)
at org.tensorflow.lite.NativeInterpreterWrapper.run(NativeInterpreterWrapper.java:243)
at org.tensorflow.lite.InterpreterImpl.runForMultipleInputsOutputs(InterpreterImpl.java:107)
at org.tensorflow.lite.Interpreter.runForMultipleInputsOutputs(Interpreter.java:80)
at org.tensorflow.lite.InterpreterImpl.run(InterpreterImpl.java:100)
at org.tensorflow.lite.Interpreter.run(Interpreter.java:80)
at com.ml.quaterion.facenetdetection.model.FaceNetModel.runFaceNet(FaceNetModel.kt:104)
at com.ml.quaterion.facenetdetection.model.FaceNetModel.getFaceEmbedding(FaceNetModel.kt:83)
at com.ml.quaterion.facenetdetection.FileReader$getEmbedding$2.invokeSuspend(FileReader.kt:108)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664) 

The model is converted from facenet pretrained model to tflite by QUANTIZED_UINT8 format, the model size is reduced from 93MB to about 23MB, the problem should be caused by the mismatch between UINT8 and FLOAT, I would like to ask how to convert the tflite model in the assets directory of the project and reduce the model size while maintaining the FLOAT format.

Access denied finding property "ro.mediatek.platform"!

Hi,

I try to build the project and debug it after press USE THIS FOLDER button, suddenly the apps crash and here is the error message

` detectFacesImageByteArray.start()
Access denied finding property "ro.mediatek.platform"
detectFacesImageByteArray.end()
FATAL EXCEPTION: main
Process: com.ml.quaterion.facenetdetection, PID: 5566
java.lang.IllegalArgumentException: x must be >= 0
at android.graphics.Bitmap.checkXYSign(Bitmap.java:432)
at android.graphics.Bitmap.createBitmap(Bitmap.java:862)
at android.graphics.Bitmap.createBitmap(Bitmap.java:825)
at com.ml.quaterion.facenetdetection.BitmapUtils$Companion.cropRectFromBitmap(BitmapUtils.kt:46)
at com.ml.quaterion.facenetdetection.FileReader$getEmbedding$2.invokeSuspend(FileReader.kt:109)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@4a30289, Dispatchers.Main]

Please help!

App is hanging with 300 Images

I really appreciated this works very well with few images. How to avoid blocking UI and also to work smoothly with many no of images ?

l2 Norm not working as expected.

Hi,

It was a great code thanks for it.

I am struggling from few days, but could able to achieve face recognition.

  1. I have taken 2 photos of each my 7 friends. (of 720X720, I dont thing this matter much as we crop it to 160x160)
  2. I launched and it processed it (Took some time to process it).
  3. But the detection not working well. It is giving random names.

Is it possible to have SVM integrated with this module?

.listfiles giving a null exception (in app error could not read images)

Hi Shubham,
I wanted to test the efficiency of facenet tf lite model so i tried running your app but it always gives the toast as " could not read images make sure you have files according to readme "

I rebuild your app and added the google services file, i added all the READ/WRITE permissions and i found that imageDir give the proper director but imageDir.listfiles return a null exception. I have directories in the images folder as specified but it is unable to list them

Works on phone but not on tablet

Hello,

The application runs well in two phones that I tested but not in a tablet, when i try to install it show an error message "There was a problem parsing the package".

What could it be?

Internal error: Failed to apply delegate with GpuDelegate

at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8387)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
Caused by: java.lang.IllegalArgumentException: Internal error: Failed to apply delegate: ModifyGraphWithDelegate is disallowed when graph is immutable.
at org.tensorflow.lite.NativeInterpreterWrapper.applyDelegate(Native Method)
at org.tensorflow.lite.NativeInterpreterWrapper.applyDelegates(NativeInterpreterWrapper.java:373)
at org.tensorflow.lite.NativeInterpreterWrapper.init(NativeInterpreterWrapper.java:85)
at org.tensorflow.lite.NativeInterpreterWrapper.(NativeInterpreterWrapper.java:63)
at org.tensorflow.lite.Interpreter.(Interpreter.java:277)
at com.ml.quaterion.facenetdetection.model.FaceNetModel.(FaceNetModel.kt:73)
at com.ml.quaterion.facenetdetection.MainActivity.onCreate(MainActivity.kt:122)
at android.app.Activity.performCreate(Activity.java:8121)
at android.app.Activity.performCreate(Activity.java:8109)


private val useGpu = true
private val useXNNPack = true
private val modelInfo = Models.FACENET_QUANTIZED

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.