{"id":25794274,"url":"https://github.com/generic-matrix/android-face-mask-detection","last_synced_at":"2025-07-26T14:34:08.808Z","repository":{"id":65486124,"uuid":"593145605","full_name":"generic-matrix/android-face-mask-detection","owner":"generic-matrix","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-30T06:17:11.000Z","size":28303,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-27T17:41:40.496Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/generic-matrix.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-25T10:50:09.000Z","updated_at":"2023-01-25T11:05:54.000Z","dependencies_parsed_at":"2023-02-14T07:45:20.868Z","dependency_job_id":null,"html_url":"https://github.com/generic-matrix/android-face-mask-detection","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/generic-matrix/android-face-mask-detection","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/generic-matrix%2Fandroid-face-mask-detection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/generic-matrix%2Fandroid-face-mask-detection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/generic-matrix%2Fandroid-face-mask-detection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/generic-matrix%2Fandroid-face-mask-detection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/generic-matrix","download_url":"https://codeload.github.com/generic-matrix/android-face-mask-detection/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/generic-matrix%2Fandroid-face-mask-detection/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267179148,"owners_count":24048288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-27T13:57:04.255Z","updated_at":"2025-07-26T14:34:08.784Z","avatar_url":"https://github.com/generic-matrix.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dependencies\n\n* Python 3.6\n* TensorFlow 2.1\n* Android Studio\n\n# Outputs\n\nWith Mask           |  Without Mask\n:-------------------------:|:-------------------------:\n![With Mask](https://github.com/generic-matrix/android-face-mask-detection/blob/main/Output/with_mask_1.png?raw=true)  |  ![Without Mask](https://github.com/generic-matrix/android-face-mask-detection/blob/main/Output/without_mask_1.png?raw=true)\n\n\n\n\n# Project Structure\n\nThe project has 4 folders\n\n* Android App -\u003e The Android App code\n* Model -\u003e It has mode.tflite , it is the trained model\n* APK -\u003e The apk.app which can be installed onto an compatible Android device\n* Training -\u003e It has Training.ipynb which can be opened in Google Colab\n* Output\n\n# How to build the Android App\n\n* ```git clone https://github.com/generic-matrix/android-face-mask-detection.git```\n* cd Android App\n* Open the same on the Android Studio\n\n\n# How to create the Android App from scratch\n\n1) Create a new project on Android Studio\n\n2) Copy model.tflite and label.txt and create a new folder called assets here /android/app/src/main/assets get both of them inside assets's folder\n\n3) Create a text file in labels.txt with the exact same contents as below (WithMask and withoutmask are the labels, refer the Training.ipynb in the training folder):\n```\nWithMask\nWithoutMask\n```\n\n4) In build.gradle(:app)  \n```\nimplementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly'\nimplementation 'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly'\nimplementation 'org.tensorflow:tensorflow-lite-support:0.0.0-nightly'\nimplementation 'com.github.esafirm.android-image-picker:imagepicker:2.3.1'\nimplementation 'com.github.bumptech.glide:glide:4.5.0'\nimplementation 'com.google.android.gms:play-services-vision:20.0.0'\napi 'com.otaliastudios:cameraview:2.6.2'\n```\nFollow the code in this file /android/app/res/layout/activity_main.xml (this contain the UI on the Device)\n\nFollow the code in file /android/app/java/com.facemask.android/MainActivity.kt this is the main code.\n\n\n\n# Pseudocode of MainActivity.kt\n ```\n    cameraView.addFrameProcessor{ frame -\u003e\n        overlayView.boundingBox = function processBitmap(){\n            val boundingBoxList = mutableListOf\u003cBox\u003e()\n            val faces = faceDetector.detect(frame)\n            for (i in 0 until faces.size()) {\n                val thisFace = faces.valueAt(i)\n                Crop this thisFace object as bitmapCropped\n                val label = predict(bitmapCropped)\n                Create a Box object to boundingBoxList\n            }\n            return boundingBoxList\n        }\n    }\n\n    function predict(Image bitmap){\n        1) Load The Model from model.tflite\n        2) Create the labels from labels.txt\n        3) Process the bitmap to model's input width and height\n        4) Resize the bitmap image\n        5) Run the model on inputimage buffer and get output buffer\n        6) Using TensorLabel object parse the output buffer\n        7) Return the label\n    }\n```\n\n\n# MainActivity.kt high level explanation \n\n1) In the activity_main.xml add a com.otaliastudios.cameraview.CameraView object to process frame one by one  and also the com.example.facemaskdetection.OverlayView to show the bouding box\n\n2) In the ```OnCreate()``` function \n\nWe are using FaceDetector API (https://developers.google.com/android/reference/com/google/android/gms/vision/face/FaceDetector) from Google Play Services . This API helps to detect face in a given frame .\n\n```\nval faceDetector = FaceDetector.Builder(this).setTrackingEnabled(true).build()\n```\n\nThis function returns FaceDetector.Builder object \n\n3) In the same ```onCreate()``` function \n\nSet lifecycle owner to the the MainActivity.kt\n\n```\ncameraView.setLifecycleOwner(this)\n```\n\nThen add frameprocessor to process a frame \n```\ncameraView.addFrameProcessor{ frame -\u003e\n}\n```\n\n4) See Box.kt \n\nWhich uses android.graphics.RectF\n```\nclass Box(val rectF: RectF, val label: String, val isMask: Boolean)\n```\n\n5) For Each frame we pass it to processBitmap function which returns the List of Box object \n\n    5.1) Create List of Box Object\n\n    ```\n        val boundingBoxList = mutableListOf\u003cBox\u003e()\n    ```\n\n    5.2) We detect faces using the detect function in the FaceDetector.Builder object\n\n    ```\n    val faces = faceDetector.detect(frame)\n    ```\n\n    5.3 ) For Each face (See predict function)\n\n        5.3.1 ) Load The Model from model.tflite\n\n    ```\n        val modelFile = FileUtil.loadMappedFile(this, \"model.tflite\")\n    ```\n\n        5.3.2 ) Create the labels from labels.txt\n\n    ```\n        val labels = FileUtil.loadLabels(this, \"labels.txt\")\n    ```\n\n        5.3.3) Resize the bitmap image\n\n    ```\n        val cropSize = kotlin.math.min(input.width, input.height)\n        ResizeWithCropOrPadOp(cropSize, cropSize)\n    ```\n\n        5.3.4) Process the bitmap to model's input width and height\n    \n    ```\n        val imageDataType = model.getInputTensor(0).dataType() \n        val inputShape = model.getInputTensor(0).shape() \n\n        val outputDataType = model.getOutputTensor(0).dataType() \n        val outputShape = model.getOutputTensor(0).shape() \n\n        var inputImageBuffer = TensorImage(imageDataType)\n        val outputBuffer = TensorBuffer.createFixedSize(outputShape, outputDataType) \n\n        val imageProcessor = ImageProcessor.Builder()\n            .add(ResizeWithCropOrPadOp(cropSize, cropSize)) \n            .add(ResizeOp(inputShape[1], inputShape[2], ResizeOp.ResizeMethod.NEAREST_NEIGHBOR)) \n            .add(NormalizeOp(127.5f, 127.5f)) \n            .build()\n    ```\n\n        5.3.5) Run the model on inputimage buffer and get output buffer\n\n    ```\n            model.run(inputImageBuffer.buffer, outputBuffer.buffer.rewind())\n    ```\n\n        5.3.6) Using TensorLabel object parse the output buffer\n\n    ```\n            val labelOutput = TensorLabel(labels, outputBuffer) \n    ```\n\n        5.3.7) Return the label\n\n    ```\n            val label = labelOutput.mapWithFloatValue\n            return label\n    ```\n\n    5.4) Create a Box object and append boundingBoxList\n\n    Return the boundingBoxList object\n\n\n\n\n\n# Also Refer The Referenced Project\n\n* https://github.com/Cindyalifia/tflite-face-mask-detection-android","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeneric-matrix%2Fandroid-face-mask-detection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeneric-matrix%2Fandroid-face-mask-detection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeneric-matrix%2Fandroid-face-mask-detection/lists"}