-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3486bed
Showing
84 changed files
with
2,384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Built application files | ||
*.apk | ||
*.aar | ||
*.ap_ | ||
*.aab | ||
|
||
# Files for the ART/Dalvik VM | ||
*.dex | ||
|
||
# Java class files | ||
*.class | ||
|
||
# Generated files | ||
bin/ | ||
gen/ | ||
out/ | ||
# Uncomment the following line in case you need and you don't have the release build type files in your app | ||
# release/ | ||
|
||
# Gradle files | ||
.gradle/ | ||
build/ | ||
|
||
# Local configuration file (sdk path, etc) | ||
local.properties | ||
|
||
# Proguard folder generated by Eclipse | ||
proguard/ | ||
|
||
# Log Files | ||
*.log | ||
|
||
# Android Studio Navigation editor temp files | ||
.navigation/ | ||
|
||
# Android Studio captures folder | ||
captures/ | ||
|
||
# IntelliJ | ||
.idea/ | ||
|
||
# Keystore files | ||
# Uncomment the following lines if you do not want to check your keystore files in. | ||
#*.jks | ||
#*.keystore | ||
keystore.properties | ||
|
||
# External native build folder generated in Android Studio 2.2 and later | ||
.externalNativeBuild | ||
.cxx/ | ||
|
||
# Google Services (e.g. APIs or Firebase) | ||
# google-services.json | ||
|
||
# Freeline | ||
freeline.py | ||
freeline/ | ||
freeline_project_description.json | ||
|
||
# fastlane | ||
fastlane/report.xml | ||
fastlane/Preview.html | ||
fastlane/screenshots | ||
fastlane/test_output | ||
fastlane/readme.md | ||
|
||
# Version control | ||
vcs.xml | ||
|
||
# lint | ||
lint/intermediates/ | ||
lint/generated/ | ||
lint/outputs/ | ||
lint/tmp/ | ||
# lint/reports/ | ||
|
||
# Android Profiling | ||
*.hprof |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/build | ||
/release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile | ||
import java.util.Locale | ||
import java.util.Properties | ||
|
||
val packageName = "ru.solrudev.facerecognizer" | ||
|
||
plugins { | ||
alias(libs.plugins.android.application) | ||
alias(libs.plugins.kotlin.android) | ||
alias(libs.plugins.kotlin.ksp) | ||
alias(dagger.plugins.hilt.plugin) | ||
alias(androidx.plugins.navigation.safeargs) | ||
alias(libs.plugins.android.cachefix) | ||
} | ||
|
||
kotlin { | ||
jvmToolchain(17) | ||
} | ||
|
||
base { | ||
archivesName.set(packageName) | ||
} | ||
|
||
android { | ||
compileSdk = 34 | ||
buildToolsVersion = "34.0.0" | ||
namespace = packageName | ||
|
||
defaultConfig { | ||
applicationId = packageName | ||
minSdk = 26 | ||
targetSdk = 34 | ||
versionCode = 1 | ||
versionName = "0.0.1" | ||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
vectorDrawables.useSupportLibrary = true | ||
} | ||
|
||
val releaseSigningConfig by signingConfigs.registering { | ||
initWith(signingConfigs["debug"]) | ||
val keystorePropertiesFile = rootProject.file("keystore.properties") | ||
if (keystorePropertiesFile.exists()) { | ||
val keystoreProperties = Properties().apply { | ||
keystorePropertiesFile.inputStream().use(::load) | ||
} | ||
keyAlias = keystoreProperties["keyAlias"] as? String | ||
keyPassword = keystoreProperties["keyPassword"] as? String | ||
storeFile = keystoreProperties["storeFile"]?.let(::file) | ||
storePassword = keystoreProperties["storePassword"] as? String | ||
enableV3Signing = true | ||
enableV4Signing = true | ||
} | ||
} | ||
|
||
buildTypes { | ||
named("debug") { | ||
multiDexEnabled = true | ||
} | ||
named("release") { | ||
isMinifyEnabled = true | ||
isShrinkResources = true | ||
signingConfig = releaseSigningConfig.get() | ||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") | ||
} | ||
} | ||
|
||
splits { | ||
abi { | ||
isEnable = true | ||
reset() | ||
//noinspection ChromeOsAbiSupport | ||
include("arm64-v8a") | ||
isUniversalApk = false | ||
} | ||
} | ||
|
||
compileOptions { | ||
sourceCompatibility = JavaVersion.VERSION_17 | ||
targetCompatibility = JavaVersion.VERSION_17 | ||
} | ||
|
||
buildFeatures { | ||
mlModelBinding = true | ||
viewBinding = true | ||
} | ||
} | ||
|
||
tasks.withType<KotlinJvmCompile>().configureEach { | ||
compilerOptions { | ||
freeCompilerArgs.add("-Xjvm-default=all") | ||
} | ||
} | ||
|
||
tasks.withType<Test>().configureEach { | ||
useJUnitPlatform() | ||
} | ||
|
||
androidComponents { | ||
onVariants(selector().all()) { variant -> | ||
afterEvaluate { | ||
val variantName = variant.name.replaceFirstChar { | ||
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() | ||
} | ||
tasks.getByName<KotlinCompile>("ksp${variantName}Kotlin") { | ||
setSource(tasks.getByName("generate${variantName}MlModelClass").outputs) | ||
} | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
ksp(dagger.bundles.hilt.compilers) | ||
|
||
implementation(dagger.hilt.android) | ||
implementation(androidx.activity.ktx) | ||
implementation(androidx.fragment.ktx) | ||
implementation(androidx.bundles.navigation) | ||
implementation(androidx.bundles.camera) | ||
implementation(libs.materialcomponents) | ||
implementation(libs.kotlinx.coroutines) | ||
implementation(libs.viewbindingpropertydelegate) | ||
implementation(libs.insetter) | ||
implementation(libs.mlkit.facedetection) | ||
implementation(libs.bundles.tensorflow) | ||
|
||
debugImplementation(androidx.multidex) | ||
|
||
testImplementation(libs.kotlin.test) | ||
testImplementation(libs.bundles.junit) | ||
testImplementation(libs.kotlinx.coroutines.test) | ||
androidTestImplementation(androidx.test.ext.junit) | ||
androidTestImplementation(androidx.espresso.core) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-keepattributes LineNumberTable,SourceFile | ||
-renamesourcefileattribute Source | ||
|
||
#### Miscellaneous | ||
-keep,allowobfuscation,allowshrinking class org.tensorflow.lite.gpu.GpuDelegateFactory$Options$GpuBackend | ||
-keep,allowobfuscation,allowshrinking class org.tensorflow.lite.gpu.GpuDelegateFactory$Options |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
|
||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:tools="http://schemas.android.com/tools"> | ||
|
||
<uses-feature | ||
android:name="android.hardware.camera.any" | ||
android:required="false" /> | ||
|
||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.CAMERA" /> | ||
|
||
<application | ||
android:name=".MainApplication" | ||
android:enableOnBackInvokedCallback="true" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.FaceRecognizer" | ||
tools:ignore="UnusedAttribute"> | ||
|
||
<activity | ||
android:name=".ui.MainActivity" | ||
android:exported="true" | ||
android:theme="@style/Theme.FaceRecognizer.NoActionBar"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
<category android:name="android.intent.category.LAUNCHER" /> | ||
</intent-filter> | ||
</activity> | ||
|
||
</application> | ||
</manifest> |
56 changes: 56 additions & 0 deletions
56
app/src/main/kotlin/ru/solrudev/facerecognizer/FaceDetector.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
@file:OptIn(TransformExperimental::class) | ||
|
||
package ru.solrudev.facerecognizer | ||
|
||
import android.graphics.Bitmap | ||
import android.graphics.RectF | ||
import androidx.annotation.OptIn | ||
import androidx.camera.core.ExperimentalGetImage | ||
import androidx.camera.core.ImageProxy | ||
import androidx.camera.view.TransformExperimental | ||
import androidx.camera.view.transform.CoordinateTransform | ||
import com.google.mlkit.vision.common.InputImage | ||
import ru.solrudev.facerecognizer.util.await | ||
import ru.solrudev.facerecognizer.util.crop | ||
import ru.solrudev.facerecognizer.util.rotateCounterclockwise | ||
import javax.inject.Inject | ||
import com.google.mlkit.vision.face.FaceDetector as MlKitVisionFaceDetector | ||
|
||
interface FaceDetector : AutoCloseable { | ||
suspend fun detect( | ||
image: ImageProxy, | ||
rotationDegrees: Int, | ||
previewTransform: CoordinateTransform | ||
): List<DetectedFace> | ||
} | ||
|
||
class MlKitFaceDetector @Inject constructor(private val faceDetector: MlKitVisionFaceDetector) : FaceDetector { | ||
|
||
@OptIn(ExperimentalGetImage::class) | ||
override suspend fun detect( | ||
image: ImageProxy, | ||
rotationDegrees: Int, | ||
previewTransform: CoordinateTransform | ||
): List<DetectedFace> { | ||
val inputImage = InputImage.fromMediaImage(image.image!!, rotationDegrees) | ||
return faceDetector | ||
.process(inputImage) | ||
.await() | ||
.mapNotNull { face -> | ||
val rotatedFaceBoundingBox = face.boundingBox | ||
val faceBoundingBox = rotatedFaceBoundingBox.rotateCounterclockwise( | ||
image.width, image.height, rotationDegrees | ||
) | ||
val faceBitmap = image.toBitmap().crop(faceBoundingBox, rotationDegrees) ?: return@mapNotNull null | ||
previewTransform.mapRect(faceBoundingBox) | ||
val faceId = face.trackingId ?: error("Face tracking is disabled") | ||
DetectedFace(faceId, faceBitmap, faceBoundingBox) | ||
} | ||
} | ||
|
||
override fun close() { | ||
faceDetector.close() | ||
} | ||
} | ||
|
||
data class DetectedFace(val id: Int, val bitmap: Bitmap, val boundingBox: RectF) |
40 changes: 40 additions & 0 deletions
40
app/src/main/kotlin/ru/solrudev/facerecognizer/FaceEmbeddingsRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package ru.solrudev.facerecognizer | ||
|
||
import javax.inject.Inject | ||
import javax.inject.Singleton | ||
|
||
interface FaceEmbeddingsRepository { | ||
suspend fun addFaceEmbeddings(faceEmbeddings: FaceEmbeddings) | ||
suspend fun getAllFaceEmbeddings(): List<FaceEmbeddings> | ||
} | ||
|
||
@Singleton | ||
class InMemoryFaceEmbeddingsRepository @Inject constructor() : FaceEmbeddingsRepository { | ||
|
||
private val faceEmbeddingsList = mutableListOf<FaceEmbeddings>() | ||
|
||
override suspend fun addFaceEmbeddings(faceEmbeddings: FaceEmbeddings) { | ||
faceEmbeddingsList += faceEmbeddings | ||
} | ||
|
||
override suspend fun getAllFaceEmbeddings(): List<FaceEmbeddings> { | ||
return faceEmbeddingsList | ||
} | ||
} | ||
|
||
data class FaceEmbeddings(val name: String, val embeddings: FloatArray) { | ||
|
||
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (javaClass != other?.javaClass) return false | ||
other as FaceEmbeddings | ||
if (name != other.name) return false | ||
return embeddings.contentEquals(other.embeddings) | ||
} | ||
|
||
override fun hashCode(): Int { | ||
var result = name.hashCode() | ||
result = 31 * result + embeddings.contentHashCode() | ||
return result | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
app/src/main/kotlin/ru/solrudev/facerecognizer/FaceRecognition.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package ru.solrudev.facerecognizer | ||
|
||
import android.graphics.Bitmap | ||
import android.graphics.Rect | ||
|
||
data class FaceRecognition(val face: RecognizedFace, val boundingBox: Rect, val bitmap: Bitmap) |
12 changes: 12 additions & 0 deletions
12
app/src/main/kotlin/ru/solrudev/facerecognizer/FaceRecognitionCoroutineScope.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package ru.solrudev.facerecognizer | ||
|
||
import kotlinx.coroutines.CoroutineDispatcher | ||
import kotlinx.coroutines.CoroutineScope | ||
import ru.solrudev.facerecognizer.di.DefaultDispatcher | ||
import javax.inject.Inject | ||
|
||
interface FaceRecognitionCoroutineScope : CoroutineScope | ||
|
||
class FaceRecognitionCoroutineScopeImpl @Inject constructor( | ||
@DefaultDispatcher dispatcher: CoroutineDispatcher | ||
) : FaceRecognitionCoroutineScope, CoroutineScope by CoroutineScope(dispatcher) |
Oops, something went wrong.