pythonandroidkotlinchaquopydeepface

Error with DeepFace library in Chaquopy Android Project


I have been trying to run the following snippet of code for deepface for comparing two images containing a face. Python code: face_similarity.py

import base64
from io import BytesIO
from PIL import Image
import numpy as np
import cv2
from deepface import DeepFace
import traceback
import tensorflow as tf
import vitis_quantizer

def convert_to_tflite(model, tflite_filename):
    # Convert the model to TFLite format
    converter = tf.lite.TFLiteConverter.from_saved_model(model)
    tflite_model = converter.convert()

    # Save the TFLite model to a file
    with open(tflite_filename, 'wb') as f:
        f.write(tflite_model)

def calculate_deepface_similarity(ekyc_base64, attendance_base64):
    if not ekyc_base64 or not attendance_base64:
        return "image is missing"

    try:
        ekyc_image = _decode_base64_image(ekyc_base64)
        attendance_image = _decode_base64_image(attendance_base64)

        if ekyc_image is None or attendance_image is None:
            return "invalid image data"

        # Ensure both images are in portrait orientation
        ekyc_image = _convert_to_portrait(ekyc_image)
        attendance_image = _convert_to_portrait(attendance_image)

        ekyc_image_np = np.array(ekyc_image)
        attendance_image_np = np.array(attendance_image)

        # Convert BGR to RGB (DeepFace requires RGB images)
        ekyc_image_rgb = cv2.cvtColor(ekyc_image_np, cv2.COLOR_BGR2RGB)
        attendance_image_rgb = cv2.cvtColor(attendance_image_np, cv2.COLOR_BGR2RGB)
        # Perform face recognition using Facenet512 model
        result = DeepFace.verify(ekyc_image_rgb, attendance_image_rgb, model_name='Facenet512')

        # Check the structure of the result variable
        print("Result:", result)

        similarity_percentage = (1 - result["distance"]) * 100
        return similarity_percentage
    except Exception as e:
        print("Error processing images:", e)
        return str(traceback.format_exc())

def _decode_base64_image(base64_string):
    try:
        image_data = base64.b64decode(base64_string)
        image = Image.open(BytesIO(image_data))
        return image
    except Exception as e:
        print("Error decoding base64 image:", e)
        return None

def _convert_to_portrait(image):
    width, height = image.size
    if width < height:
        return image
    else:
        return image.transpose(Image.ROTATE_90)

def encode_image_to_base64(file_path):
    try:
        with open(file_path, "rb") as image_file:
            # Read the image file in binary mode
            image_binary = image_file.read()

            # Encode the binary data to base64
            encoded_string = base64.b64encode(image_binary).decode("utf-8")

            return encoded_string
    except Exception as e:
        print(f"Error encoding image: {e}")
        return None

if __name__ == "__main__":
    # Example usage
    ekyc_base64 = encode_image_to_base64("Screenshot 2023-11-26 220725.png")
    attendance_base64 = encode_image_to_base64("Screenshot 2023-11-26 220806.png")

    similarity_percentage = calculate_deepface_similarity(ekyc_base64, attendance_base64)
    print("Similarity Percentage:", similarity_percentage)

However, I'm facing the following error:

Traceback (most recent call last):
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/app/face_similarity.py", line 36, in calculate_deepface_similarity
        result = DeepFace.verify(ekyc_image_rgb, attendance_image_rgb, model_name='Facenet512')
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/deepface/DeepFace.py", line 169, in verify
        img1_embedding_obj = represent(
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/deepface/DeepFace.py", line 639, in represent
        model = build_model(model_name)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/deepface/DeepFace.py", line 80, in build_model
        model = model()
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/deepface/basemodels/Facenet512.py", line 11, in loadModel
        model = Facenet.InceptionResNetV2(dimension=512)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/deepface/basemodels/Facenet.py", line 49, in InceptionResNetV2
        inputs = Input(shape=(160, 160, 3))
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/keras/engine/input_layer.py", line 270, in Input
        input_layer = InputLayer(**input_layer_config)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/keras/engine/input_layer.py", line 122, in _init_
        input_tensor = backend.placeholder(
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/keras/backend.py", line 1054, in placeholder
        x = array_ops.placeholder(dtype, shape=shape, name=name)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/ops/array_ops.py", line 2718, in placeholder
        return gen_array_ops.placeholder(dtype=dtype, shape=shape, name=name)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/ops/gen_array_ops.py", line 6031, in placeholder
        _, _, _op, _outputs = _op_def_library._apply_op_helper(
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/framework/op_def_library.py", line 740, in _apply_op_helper
        op = g._create_op_internal(op_type_name, inputs, dtypes=None,
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/framework/func_graph.py", line 593, in _create_op_internal
        return super(FuncGraph, self)._create_op_internal(  # pylint: disable=protected-access
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/framework/ops.py", line 3307, in _create_op_internal
        node_def = _NodeDef(op_type, name, attrs)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/tensorflow_core/python/framework/ops.py", line 1569, in _NodeDef
        node_def.attr[k].CopyFrom(v)
    File "/data/data/rural.ekyc/files/chaquopy/AssetFinder/requirements/google/protobuf/internal/containers.py", line 70, in _getitem_
        return self._values[key]
    TypeError: list indices must be integers or slices, not str

My build.gradle:

import java.text.SimpleDateFormat

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'

    id 'kotlin-android'
    id 'kotlin-parcelize'
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
    id 'androidx.navigation.safeargs.kotlin'
    id 'com.google.gms.google-services'
    id 'com.google.firebase.crashlytics'

    id 'com.chaquo.python'
}

android {
    namespace 'rural.ekyc'
    compileSdk 33

    defaultConfig {
        applicationId "rural.ekyc"
        minSdk 24
        targetSdk 33
        versionCode 1
        versionName "1.0.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        python{

            pip {
                install "deepface==0.0.79"
                install "numpy"
                install "opencv-python"

            }
            buildPython "/usr/local/bin/python3"

        }

        ndk {
            abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
        }
        sourceSets{
            main{
                python.srcDir "src/main/python"
            }
        }


    }

    applicationVariants.all { variant ->
        variant.outputs.all {
            def date = new SimpleDateFormat("dd_MM_yy").format(new Date())
            outputFileName = "eKYC_APP_${date}_${variant.buildType.name}_${defaultConfig.versionName}.apk"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    /* debug {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }*/

    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = '17'
    }
    buildFeatures {
        dataBinding false
        viewBinding true
    }


}

dependencies {

    //Androidx
    implementation 'androidx.core:core-ktx:1.10.1'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
    implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.annotation:annotation:1.6.0'

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    //Google
    implementation 'com.google.firebase:firebase-crashlytics:18.4.0'
    implementation 'com.google.firebase:firebase-analytics:21.3.0'
    implementation 'com.google.android.material:material:1.9.0'

    implementation 'com.google.android.gms:play-services-vision:20.1.3'

    //Intuitx
    implementation 'com.intuit.sdp:sdp-android:1.0.6'
    implementation 'com.intuit.ssp:ssp-android:1.0.6'

    //Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    implementation "com.squareup.okhttp3:okhttp:4.9.0"
    implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"

    //lifecycle
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
    implementation 'androidx.lifecycle:lifecycle-service:2.6.1'

    //Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

    //Dragger Hilt
    implementation "com.google.dagger:hilt-android:$hilt_version"
    kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

    //Glide
    implementation 'com.github.bumptech.glide:glide:4.13.2'
    implementation 'com.github.bumptech.glide:annotations:4.13.2'
    implementation 'com.github.bumptech.glide:okhttp3-integration:4.12.0'
    kapt 'com.github.bumptech.glide:compiler:4.13.2'

    // Room
    implementation "androidx.room:room-runtime:2.5.2"
    kapt "androidx.room:room-compiler:2.5.2"

    // Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:2.5.2"


    implementation 'io.github.rupinderjeet:kprogresshud:1.0.0'
    implementation 'com.github.f0ris.sweetalert:library:1.5.6'
    implementation 'com.github.chivorns:smartmaterialspinner:1.5.0'


    implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.1'
    implementation ('com.thoughtworks.xstream:xstream:1.4.7') {
        exclude group: 'xmlpull', module: 'xmlpull'
    }

    implementation group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.45'
    implementation group: 'javax.xml.crypto', name: 'jsr105-api', version: '1.0.1'
    implementation (group: 'org.apache.santuario', name: 'xmlsec', version: '2.0.3') {
        exclude group: "org.codehaus.woodstox"
    }
    implementation group: 'javax.xml.stream', name: 'stax-api', version: '1.0-2'

    implementation 'com.alimuzaffar.lib:pinentryedittext:2.0.6'

    //bio-metric verification
    implementation 'androidx.biometric:biometric:1.1.0'

    //    rootbeer
    implementation 'com.scottyab:rootbeer-lib:0.1.0'


}

The pip freeze > requirements.txt output for my Windows virtual environment running in Python 3.10.9 is the following

absl-py==2.0.0
astunparse==1.6.3
beautifulsoup4==4.12.2
blinker==1.7.0
cachetools==5.3.2
certifi==2023.7.22
charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
deepface==0.0.79
filelock==3.13.1
fire==0.5.0
Flask==3.0.0
flatbuffers==23.5.26
gast==0.5.4
gdown==4.7.1
google-auth==2.23.4
google-auth-oauthlib==1.0.0
google-pasta==0.2.0
grpcio==1.59.2
gunicorn==21.2.0
h5py==3.10.0
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
keras==2.14.0
libclang==16.0.6
Markdown==3.5.1
MarkupSafe==2.1.3
ml-dtypes==0.2.0
mtcnn==0.1.1
numpy==1.26.2
oauthlib==3.2.2
opencv-python==4.8.1.78
opt-einsum==3.3.0
packaging==23.2
pandas==2.1.3
Pillow==10.1.0
protobuf==4.25.0
pyasn1==0.5.0
pyasn1-modules==0.3.0
PySocks==1.7.1
python-dateutil==2.8.2
pytz==2023.3.post1
requests==2.31.0
requests-oauthlib==1.3.1
retina-face==0.0.13
rsa==4.9
six==1.16.0
soupsieve==2.5
tensorboard==2.14.1
tensorboard-data-server==0.7.2
tensorflow==2.14.0
tensorflow-estimator==2.14.0
tensorflow-intel==2.14.0
tensorflow-io-gcs-filesystem==0.31.0
termcolor==2.3.0
tqdm==4.66.1
typing_extensions==4.8.0
tzdata==2023.3
urllib3==2.1.0
Werkzeug==3.0.1
wrapt==1.14.1

Android Studio version: Android Studio Giraffe | 2022.3.1 Patch 2

Gradle version: 8.1.2

DeepFace version: 0.0.79

Chaquopy version: 14.0.2

The dependencies I have installed deepface, numpy and opencv-python. Also, is there a possibility of running commands to check the python versions running so as to duplicate that in a virtual environment on local system. The code for face_similarity.py works fine on my local system and also in a Windows virtual environment.

If anyone has an idea of what I can do to fix this I would be glad if they helped me. Thanks.

I tried installing various combinations of libraries in my build.gradle file including deepface, open-cv-python, and often got the error that opencv-python version was not found too, and I'm not able to duplicate my python local environment onto Chaquopy Java Kotlin Android Studio


Solution

  • The pip freeze output from your Windows virtual environment is irrelevant, because Chaquopy creates a separate virtual environment using the Android packages from its repository. The newest Tensorflow version in that repository is 2.1.0, which is incompatible with the current protobuf version, 4.25.

    To work around this, add the following line to the pip block in your build.gradle file:

    install "protobuf<4.25"