Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object ApiConfig {
.build()
val retrofit = Retrofit.Builder()
// .baseUrl("http://192.168.0.107:3000/")
.baseUrl("http://192.168.0.244:3000/")
.baseUrl("http://192.168.0.221:3000/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class CameraManager(
}

fun onTakeImage(callback: OnTakeImageCallback) {
Handler(Looper.getMainLooper()).post {
callback.onTakeImageStart()
}
imageCapture.takePicture(cameraExecutor, object : OnImageCapturedCallback() {
override fun onCaptureSuccess(imageProxy: ImageProxy) {
@SuppressLint("UnsafeOptInUsageError")
Expand Down Expand Up @@ -139,8 +142,6 @@ class CameraManager(
}
}



override fun onError(exception: ImageCaptureException) {
Handler(Looper.getMainLooper()).post {
callback.onTakeImageError(exception)
Expand Down Expand Up @@ -172,6 +173,7 @@ class CameraManager(
interface OnTakeImageCallback {
fun onTakeImageSuccess(image : Bitmap)
fun onTakeImageError(exception: Exception)
fun onTakeImageStart()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,38 @@ class FaceAntiSpoofing @Throws(IOException::class) constructor(assetManager: Ass
}

fun antiSpoofing(bitmap: Bitmap): Float {
// Resize the face to 256X256, because the shape of the placeholder required for the feed data below is (1, 256, 256, 3)
// 1. Resize ke 224x224
val bitmapScale = Bitmap.createScaledBitmap(bitmap, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE, true)
val img: Array<Array<FloatArray>> = normalizeImage(bitmapScale)
val input: Array<Array<Array<FloatArray>>?> = arrayOfNulls(1)
input[0] = img
val clss_pred = Array(1) { FloatArray(8) }
val leaf_node_mask = Array(1) { FloatArray(8) }
val outputs: MutableMap<Int, Any> = HashMap()
outputs[interpreter.getOutputIndex("Identity")] = clss_pred
outputs[interpreter.getOutputIndex("Identity_1")] = leaf_node_mask
interpreter.runForMultipleInputsOutputs(arrayOf<Any>(input), outputs)

Log.i(
TAG, "[" + clss_pred[0][0] + ", " + clss_pred[0][1] + ", "
+ clss_pred[0][2] + ", " + clss_pred[0][3] + ", " + clss_pred[0][4] + ", "
+ clss_pred[0][5] + ", " + clss_pred[0][6] + ", " + clss_pred[0][7] + "]"
)
Log.i(
TAG, "[" + leaf_node_mask[0][0] + ", " + leaf_node_mask[0][1] + ", "
+ leaf_node_mask[0][2] + ", " + leaf_node_mask[0][3] + ", " + leaf_node_mask[0][4] + ", "
+ leaf_node_mask[0][5] + ", " + leaf_node_mask[0][6] + ", " + leaf_node_mask[0][7] + "]"
)

return leaf_score1(clss_pred, leaf_node_mask);
}
// 2. Normalisasi gambar ke array [224][224][3]
val normalizedImage = normalizeImage(bitmapScale)

private fun leaf_score1(clss_pred: Array<FloatArray>, leaf_node_mask: Array<FloatArray>): Float {
var score = 0f
for (i in 0..7) {
score += abs(clss_pred[0][i]) * leaf_node_mask[0][i]
// 3. Bungkus ke dalam shape [1][224][224][3] sesuai input model
val input = Array(1) {
Array(INPUT_IMAGE_SIZE) {
Array(INPUT_IMAGE_SIZE) {
FloatArray(3)
}
}
}
return score
}

private fun leaf_score2(clss_pred: Array<FloatArray>): Float {
return clss_pred[0][ROUTE_INDEX]
for (i in 0 until INPUT_IMAGE_SIZE) {
for (j in 0 until INPUT_IMAGE_SIZE) {
input[0][i][j] = normalizedImage[i][j]
}
}

// 4. Output model adalah [1][1], jadi kita siapkan array untuk menampung hasilnya
val output = Array(1) { FloatArray(1) }

// 5. Jalankan model
interpreter.run(input, output)

// 6. Ambil nilai prediksi dari output[0][0]
val prediction = output[0][0]
Log.d(TAG, "Anti-spoofing prediction result: $prediction")

return prediction
}

fun normalizeImage(bitmap: Bitmap): Array<Array<FloatArray>> {
Expand Down Expand Up @@ -97,9 +93,15 @@ class FaceAntiSpoofing @Throws(IOException::class) constructor(assetManager: Ass
*/
fun laplacian(bitmap: Bitmap): Int {
// Resize the face to a size of 256X256, because the shape of the placeholder that needs feed data below is (1, 256, 256, 3)
val bitmapScale = Bitmap.createScaledBitmap(bitmap, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE, true)
val bitmapScale = Bitmap.createScaledBitmap(bitmap, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE, false
)

val laplace = arrayOf(intArrayOf(0, 1, 0), intArrayOf(1, -4, 1), intArrayOf(0, 1, 0))
// val laplace = arrayOf(intArrayOf(0, 1, 0), intArrayOf(1, -4, 1), intArrayOf(0, 1, 0))
val laplace = arrayOf(
intArrayOf(1, 1, 1),
intArrayOf(1, -8, 1),
intArrayOf(1, 1, 1)
)
val size = laplace.size
val img: Array<IntArray> = Utils.convertGreyImg(bitmapScale)
val height = img.size
Expand All @@ -115,7 +117,7 @@ class FaceAntiSpoofing @Throws(IOException::class) constructor(assetManager: Ass
result += (img[x + i][y + j] and 0xFF) * laplace[i][j]
}
}
if (result > LAPLACE_THRESHOLD) {
if (abs(result) > LAPLACE_THRESHOLD) {
score++
}
}
Expand All @@ -125,10 +127,10 @@ class FaceAntiSpoofing @Throws(IOException::class) constructor(assetManager: Ass

companion object {
private val TAG = "FaceAntiSpoofing"
private val MODEL_FILE = "DeepTreeFaceAntiSpoofing.tflite"
private val MODEL_FILE = "model_anti_spoofing_final_test.tflite"

val INPUT_IMAGE_SIZE: Int = 256 // The width and height of the placeholder image that needs feed data
val THRESHOLD: Float = 0.2f // Set a threshold, greater than this value is considered an attack
val INPUT_IMAGE_SIZE: Int = 224 // The width and height of the placeholder image that needs feed data
val THRESHOLD: Float = 0.5f // Set a threshold, greater than this value is considered an attack

val ROUTE_INDEX: Int = 6 // Route indices observed during training

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class FaceRecognizer @Throws(IOException::class) constructor(assetManager: Asset
return evaluate(embeddings)
}

// change into images into embedding with mobile facenet
fun getEmbeddingsOfImage(bitmapImage: Bitmap): Array<FloatArray> {
val bitmapScale = Bitmap.createScaledBitmap(bitmapImage, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE, true)
val datasets: Array<Array<Array<FloatArray>>> = getImagesDataset(bitmapScale)
Expand Down
32 changes: 24 additions & 8 deletions AndroidApps/app/src/main/java/com/mfa/utils/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,30 @@ class Utils {
return dataImage
}

fun setFirebaseEmbedding(embedingFloatList: List<String> ){
val mdatabase = FirebaseDatabase.getInstance().reference
val user = FirebaseAuth.getInstance().currentUser
val userName = user!!.uid + "_" + user.displayName!!.replace(" ", "")
//overwrites existing records instead of appending them
mdatabase.child("newfaceantispooflog").child(userName)
.child("faceEmbeddings")
.setValue(embedingFloatList)
fun setFirebaseEmbedding(embeddingFloatList: List<String>) {
try {
val user = FirebaseAuth.getInstance().currentUser
if (user == null) {
Log.e("FirebaseEmbedding", "User not logged in")
return
}

val userName = user.uid + "_" + (user.displayName ?: "unknown").replace(" ", "")
val database = FirebaseDatabase.getInstance().reference

database.child("newfaceantispooflog")
.child(userName)
.child("faceEmbeddings")
.setValue(embeddingFloatList)
.addOnSuccessListener {
Log.d("FirebaseEmbedding", "Embeddings saved successfully")
}
.addOnFailureListener { e ->
Log.e("FirebaseEmbedding", "Failed to save embeddings", e)
}
} catch (e: Exception) {
Log.e("FirebaseEmbedding", "Error saving embeddings", e)
}
}

/**
Expand Down
Loading