├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── idcard.jks ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── kbyai │ │ └── idcardrecognition │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── kbyai │ │ │ └── idcardrecognition │ │ │ ├── AboutActivity.kt │ │ │ ├── CameraActivityKt.kt │ │ │ ├── FaceView.java │ │ │ ├── MainActivity.kt │ │ │ ├── ResultActivity.kt │ │ │ ├── ResultAdapter.java │ │ │ ├── ResultDataFragment.kt │ │ │ ├── ResultItem.java │ │ │ ├── ResultOverviewFragment.kt │ │ │ ├── ResultViewPagerAdapter.kt │ │ │ └── Utils.java │ └── res │ │ ├── drawable │ │ ├── ic_about.xml │ │ ├── ic_camera.xml │ │ ├── ic_email.xml │ │ ├── ic_gallery.xml │ │ ├── ic_github.png │ │ ├── ic_kby.png │ │ ├── ic_settings.xml │ │ ├── ic_skype.png │ │ ├── ic_telegram.png │ │ ├── ic_tip.xml │ │ └── ic_whatsapp.png │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_camera.xml │ │ ├── activity_camera_kt.xml │ │ ├── activity_main.xml │ │ ├── activity_result.xml │ │ ├── fragment_result_data.xml │ │ ├── fragment_result_overview.xml │ │ └── item_result.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── data_extraction_rules.xml │ │ └── file_paths.xml │ └── test │ └── java │ └── com │ └── kbyai │ └── idcardrecognition │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libfotoapparat ├── build.gradle └── fotoapparat-2.7.0.aar ├── libidsdk ├── .gitignore └── build.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | /.idea/ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | ### Our facial recognition algorithm is globally top-ranked by NIST in the FRVT 1:1 leaderboards. badge 8 | [Latest NIST FRVT evaluation report 2024-12-20](https://pages.nist.gov/frvt/html/frvt11.html) 9 | 10 | ![FRVT Sheet](https://github.com/user-attachments/assets/16b4cee2-3a91-453f-94e0-9e81262393d7) 11 | 12 | #### 🆔 ID Document Liveness Detection - Linux - [Here](https://web.kby-ai.com) badge 13 | #### 🤗 Hugging Face - [Here](https://huggingface.co/spaces/kby-ai/IDCardRecognition) 14 | #### 📚 Product & Resources - [Here](https://github.com/kby-ai/Product) 15 | #### 🛟 Help Center - [Here](https://docs.kby-ai.com/help/product/id-card-sdk) 16 | #### 💼 KYC Verification Demo - [Here](https://github.com/kby-ai/KYC-Verification-Demo-Android) 17 | #### 🙋‍♀️ Docker Hub - [Here](https://hub.docker.com/r/kbyai/idcard-recognition) 18 | 19 | # IDCardRecognition-Android 20 | ## Overview 21 | 22 | This repository demonstrates `ID document recognition`, `ID card recognition`, `ID card scanner and reader` `ID document scanner and reader`, `ID Card OCR`, `passport reader` and `passport recognition` technology developed by `KBY-AI`. 23 | 24 | > In this repository, we integrated `KBY-AI`'s `ID document OCR` solution into `Android` native platform.
25 | ## Try the APK 26 | 27 | ### Google Play 28 | 29 | 30 | 31 | 32 | 33 | ## Performance Video 34 | You can visit our YouTube video [here](https://www.youtube.com/watch?v=s3G3MzrdDXI) to see how well our demo app works.

35 | [![ID Card Recognition iOS](https://img.youtube.com/vi/s3G3MzrdDXI/0.jpg)](https://www.youtube.com/watch?v=s3G3MzrdDXI) 36 | 37 | ## Screenshots 38 | 39 |

40 | 41 | 42 | 43 |

44 | 45 | ### ◾ID Card Recognition SDK Main Functionalities 46 | 47 | | Surpported ID Type | Functionalities | Release Type | 48 | |------------------|------------------|------------------| 49 | | ID Card | Extracting Information(OCR) | Android(`Kotlin & Java`) | 50 | | Passport | Scanning Barcode | iOS(`Swift & Objectiv-C`) | 51 | | Driver License | Parsing MRZ | Flutter(`Dart`) | 52 | | | Auto Capturing | Web Front-end(`Javascript`) | 53 | | | Scanning QR code | Server-Windows(`Python`) | 54 | | | Supporting 200+ Countries' ID Documents | Server-Linux(`Python`) | 55 | | | Supporting 130+ Languages | | 56 | | | ID Document Detection | | 57 | 58 | ### ◾ID Card Recognition Product List 59 | | No. | Repository | Release Type | 60 | |------------------|------------------|------------------| 61 | | ➡️ | [ID Card Recognition - Android](https://github.com/kby-ai/IDCardRecognition-Android) | Android | 62 | | 2 | [ID Card Recognition - iOS](https://github.com/kby-ai/IDCardRecognition-iOS) | iOS | 63 | | 3 | [ID Card Recognition - Flutter](https://github.com/kby-ai/IDCardRecognition-Flutter) | Flutter | 64 | | 4 | [ID Auto Capture - React](https://github.com/kby-ai/ID-document-capture-React) | Web Front-end | 65 | | 5 | [ID Card Recognition - Windows](https://github.com/kby-ai/IDCardRecognition-Windows) | Server-Windows | 66 | | 6 | [ID Card Recognition - Linux](https://github.com/kby-ai/IDCardRecognition-Docker) | Server-Linux | 67 | | 7 | [ID Card Recognition - C#](https://github.com/kby-ai/IDCardRecognition-CSharp-.NET) | Server-Windows | 68 | 69 | ## SDK License 70 | 71 | - The code line below shows how to update SDK with the `license key`: https://github.com/kby-ai/IDCardRecognition-Android/blob/1db9754a66b0211715ab458a23d3a2dd93f9303d/app/src/main/java/com/kbyai/idcardrecognition/MainActivity.kt#L22-L31 72 | - To request `license key`, please contact us:
73 | 🧙`Email:` contact@kby-ai.com
74 | 🧙`Telegram:` [@kbyai](https://t.me/kbyai)
75 | 🧙`WhatsApp:` [+19092802609](https://wa.me/+19092802609)
76 | 🧙`Discord:` [KBY-AI](https://discord.gg/CgHtWQ3k9T)
77 | 🧙`Teams:` [KBY-AI](https://teams.live.com/l/invite/FBAYGB1-IlXkuQM3AY)
78 | 79 | ## How To Run 80 | ### 1. Placing Library File 81 | Download the `SDK library` file for `Android`(`idsdk.aar`) from [here](https://drive.google.com/file/d/1hys99a7QG7-px_m8DGa9RKqR7wr6E8bS/view?usp=sharing) and put it on the suitable `SDK` folder(folder `libidsdk`).
82 | ### 3. Running the App 83 | Try to build this repo on `Android Studio` by linking real `Android` phone, not `simulator`. Once it works fine, you are ready to integrate our `SDK` to your project.
84 | 85 | ## About SDK 86 | 87 | ### 1. Set up 88 | 1. Download our SDK library file(`idsdk.aar`) from [here](https://drive.google.com/file/d/1hys99a7QG7-px_m8DGa9RKqR7wr6E8bS/view?usp=sharing) and paste it to SDK folder(folder `libidsdk`).
Try to build this repo to make sure that SDK works fine by linking real `Android` phone, not `simulator`. Once it works fine, you are ready to integrate our SDK to your project.
89 | And then copy the SDK(folder `libidsdk`) to the `root` folder in your project. 90 | 91 | 2. Add SDK to the project in `settings.gradle`. 92 | ```bash 93 | include ':libidsdk' 94 | ``` 95 | 96 | 3. Add dependency to your `build.gradle`. 97 | ```bash 98 | implementation project(path: ':libidsdk') 99 | ``` 100 | 101 | ### 2. Initializing the SDK 102 | 103 | - Step One 104 | 105 | To begin, you need to activate the SDK using the `license key` that you have received. 106 | ```kotlin 107 | IDSDK.setActivation("...") 108 | ``` 109 | 110 | If activation is successful, SDK would return `SDK_SUCCESS`. Otherwise, it would return an error message. 111 | 112 | - Step Two 113 | 114 | Once activation is successful, you can call initialization function supported by our SDK. 115 | ```kotlin 116 | IDSDK.init(getAssets()); 117 | ``` 118 | If initialization is successful, SDK would return `SDK_SUCCESS`. Otherwise, it would return an error message. 119 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | namespace 'com.kbyai.idcardrecognition' 8 | compileSdk 34 9 | 10 | defaultConfig { 11 | applicationId "com.kbyai.idcardrecognition" 12 | minSdk 24 13 | targetSdk 34 14 | versionCode 8 15 | versionName "1.7" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | 19 | ndk { 20 | abiFilters 'arm64-v8a', 'armeabi-v7a' 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | kotlinOptions { 35 | jvmTarget = '1.8' 36 | } 37 | } 38 | 39 | dependencies { 40 | 41 | implementation 'androidx.core:core-ktx:1.7.0' 42 | implementation 'androidx.appcompat:appcompat:1.6.1' 43 | implementation 'com.google.android.material:material:1.9.0' 44 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 45 | 46 | implementation project(path: ':libidsdk') 47 | 48 | implementation 'com.itextpdf:itextpdf:5.5.10' 49 | 50 | // PDF library 51 | // implementation 'io.fotoapparat:fotoapparat:2.7.0' 52 | implementation project(path: ':libfotoapparat') 53 | 54 | testImplementation 'junit:junit:4.13.2' 55 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 56 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 57 | } -------------------------------------------------------------------------------- /app/idcard.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kby-ai/IDCardRecognition-Android/d0632898f94939b908f857abb91b0ae3a2217f61/app/idcard.jks -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/kbyai/idcardrecognition/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.kbyai.idcardrecognition 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.kbyai.idcardrecognition", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 41 | 46 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/kbyai/idcardrecognition/AboutActivity.kt: -------------------------------------------------------------------------------- 1 | package com.kbyai.idcardrecognition 2 | 3 | import android.content.Intent 4 | import android.content.pm.ResolveInfo 5 | import android.net.Uri 6 | import android.os.Bundle 7 | import android.widget.TextView 8 | import androidx.appcompat.app.AppCompatActivity 9 | import com.kbyai.idcardrecognition.R 10 | 11 | 12 | class AboutActivity : AppCompatActivity() { 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | setContentView(R.layout.activity_about) 16 | 17 | findViewById(R.id.txtMail).setOnClickListener { 18 | val intent = Intent(Intent.ACTION_SEND) 19 | intent.type = "plain/text" 20 | intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("contact@kby-ai.com")) 21 | intent.putExtra(Intent.EXTRA_SUBJECT, "License Request") 22 | intent.putExtra(Intent.EXTRA_TEXT, "") 23 | startActivity(Intent.createChooser(intent, "")) 24 | } 25 | 26 | findViewById(R.id.txtWhatsapp).setOnClickListener { 27 | val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://com.whatsapp/kbyai")) 28 | val generalResolvers: HashSet = HashSet() 29 | val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0) 30 | for (info in generalResolveInfo) { 31 | if (info.activityInfo.packageName != null) { 32 | generalResolvers.add(info.activityInfo.packageName) 33 | } 34 | } 35 | 36 | val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://wa.me/19092802609")) 37 | var goodResolver = 0 38 | 39 | val resInfo: List = packageManager.queryIntentActivities(telegram, 0) 40 | if (!resInfo.isEmpty()) { 41 | for (info in resInfo) { 42 | if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) { 43 | goodResolver++ 44 | telegram.setPackage(info.activityInfo.packageName) 45 | } 46 | } 47 | } 48 | 49 | if (goodResolver != 1) { 50 | telegram.setPackage(null) 51 | } 52 | if (telegram.resolveActivity(packageManager) != null) { 53 | startActivity(telegram) 54 | } 55 | } 56 | 57 | findViewById(R.id.txtTelegram).setOnClickListener { 58 | val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.com/kbyai")) 59 | val generalResolvers: HashSet = HashSet() 60 | val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0) 61 | for (info in generalResolveInfo) { 62 | if (info.activityInfo.packageName != null) { 63 | generalResolvers.add(info.activityInfo.packageName) 64 | } 65 | } 66 | 67 | val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/kbyai")) 68 | var goodResolver = 0 69 | 70 | val resInfo: List = packageManager.queryIntentActivities(telegram, 0) 71 | if (!resInfo.isEmpty()) { 72 | for (info in resInfo) { 73 | if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) { 74 | goodResolver++ 75 | telegram.setPackage(info.activityInfo.packageName) 76 | } 77 | } 78 | } 79 | 80 | if (goodResolver != 1) { 81 | telegram.setPackage(null) 82 | } 83 | if (telegram.resolveActivity(packageManager) != null) { 84 | startActivity(telegram) 85 | } 86 | } 87 | 88 | findViewById(R.id.txtSkype).setOnClickListener { 89 | val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://com.skype/kbyai")) 90 | val generalResolvers: HashSet = HashSet() 91 | val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0) 92 | for (info in generalResolveInfo) { 93 | if (info.activityInfo.packageName != null) { 94 | generalResolvers.add(info.activityInfo.packageName) 95 | } 96 | } 97 | 98 | val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://join.skype.com/invite/OffY2r1NUFev")) 99 | var goodResolver = 0 100 | 101 | val resInfo: List = packageManager.queryIntentActivities(telegram, 0) 102 | if (!resInfo.isEmpty()) { 103 | for (info in resInfo) { 104 | if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) { 105 | goodResolver++ 106 | telegram.setPackage(info.activityInfo.packageName) 107 | } 108 | } 109 | } 110 | 111 | if (goodResolver != 1) { 112 | telegram.setPackage(null) 113 | } 114 | if (telegram.resolveActivity(packageManager) != null) { 115 | startActivity(telegram) 116 | } 117 | } 118 | 119 | findViewById(R.id.txtGitHub).setOnClickListener { 120 | val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/kby-ai")) 121 | val generalResolvers: HashSet = HashSet() 122 | val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0) 123 | for (info in generalResolveInfo) { 124 | if (info.activityInfo.packageName != null) { 125 | generalResolvers.add(info.activityInfo.packageName) 126 | } 127 | } 128 | 129 | val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/kby-ai")) 130 | var goodResolver = 0 131 | 132 | val resInfo: List = packageManager.queryIntentActivities(telegram, 0) 133 | if (!resInfo.isEmpty()) { 134 | for (info in resInfo) { 135 | if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) { 136 | goodResolver++ 137 | telegram.setPackage(info.activityInfo.packageName) 138 | } 139 | } 140 | } 141 | 142 | if (goodResolver != 1) { 143 | telegram.setPackage(null) 144 | } 145 | if (telegram.resolveActivity(packageManager) != null) { 146 | startActivity(telegram) 147 | } 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /app/src/main/java/com/kbyai/idcardrecognition/CameraActivityKt.kt: -------------------------------------------------------------------------------- 1 | package com.kbyai.idcardrecognition; 2 | 3 | import android.Manifest 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageManager 7 | import android.graphics.Rect 8 | import android.os.Bundle 9 | import android.util.Log 10 | import android.util.Size 11 | import androidx.appcompat.app.AppCompatActivity 12 | import androidx.core.app.ActivityCompat 13 | import androidx.core.content.ContextCompat 14 | import com.kbyai.idsdk.IDSDK 15 | import io.fotoapparat.Fotoapparat 16 | import io.fotoapparat.parameter.Resolution 17 | import io.fotoapparat.preview.Frame 18 | import io.fotoapparat.preview.FrameProcessor 19 | import io.fotoapparat.selector.back 20 | import io.fotoapparat.view.CameraView 21 | import org.json.JSONObject 22 | 23 | class CameraActivityKt : AppCompatActivity() { 24 | 25 | val TAG = CameraActivityKt::class.java.simpleName 26 | val PREVIEW_WIDTH = 720 27 | val PREVIEW_HEIGHT = 1280 28 | 29 | private lateinit var cameraView: CameraView 30 | private lateinit var faceView: FaceView 31 | private lateinit var fotoapparat: Fotoapparat 32 | private lateinit var context: Context 33 | private var documenName: String = "" 34 | private var positionRect: Rect = Rect() 35 | 36 | private var recognized = false 37 | 38 | override fun onCreate(savedInstanceState: Bundle?) { 39 | super.onCreate(savedInstanceState) 40 | setContentView(R.layout.activity_camera_kt) 41 | 42 | context = this 43 | cameraView = findViewById(R.id.preview) 44 | faceView = findViewById(R.id.faceView) 45 | 46 | fotoapparat = Fotoapparat.with(this) 47 | .into(cameraView) 48 | .lensPosition(back()) 49 | .frameProcessor(FaceFrameProcessor()) 50 | .previewResolution { Resolution(PREVIEW_HEIGHT,PREVIEW_WIDTH) } 51 | .build() 52 | 53 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 54 | == PackageManager.PERMISSION_DENIED 55 | ) { 56 | ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1) 57 | } else { 58 | fotoapparat.start() 59 | } 60 | } 61 | 62 | override fun onResume() { 63 | super.onResume() 64 | recognized = false 65 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 66 | == PackageManager.PERMISSION_GRANTED 67 | ) { 68 | fotoapparat.start() 69 | } 70 | } 71 | 72 | override fun onPause() { 73 | super.onPause() 74 | fotoapparat.stop() 75 | faceView.setDocumentInfos(null, "") 76 | } 77 | 78 | override fun onRequestPermissionsResult( 79 | requestCode: Int, 80 | permissions: Array, 81 | grantResults: IntArray 82 | ) { 83 | super.onRequestPermissionsResult(requestCode, permissions, grantResults) 84 | if (requestCode == 1) { 85 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 86 | == PackageManager.PERMISSION_GRANTED 87 | ) { 88 | fotoapparat.start() 89 | } 90 | } 91 | } 92 | 93 | inner class FaceFrameProcessor : FrameProcessor { 94 | 95 | override fun process(frame: Frame) { 96 | 97 | if(recognized == true) { 98 | return 99 | } 100 | 101 | val bitmap = IDSDK.yuv2Bitmap(frame.image, frame.size.width, frame.size.height, 6) 102 | val result = IDSDK.idcardRecognition(bitmap) 103 | 104 | try { 105 | val jsonResult = JSONObject(result) 106 | val positionObj = jsonResult["Position"] as JSONObject 107 | val hasMrz = jsonResult.has("MRZ") 108 | documenName = jsonResult["Document Name"] as String 109 | val quality = jsonResult["Quality"] as Int 110 | val x1 = positionObj["x1"] as Int 111 | val y1 = positionObj["y1"] as Int 112 | val x2 = positionObj["x2"] as Int 113 | val y2 = positionObj["y2"] as Int 114 | positionRect = Rect(x1, y1, x2, y2) 115 | if (quality > 86 && (documenName != "Unknown" || hasMrz == true)) { 116 | recognized = true 117 | 118 | runOnUiThread { 119 | faceView.setFrameSize(Size(bitmap.width, bitmap.height)) 120 | faceView.setDocumentInfos(positionRect, documenName) 121 | } 122 | 123 | runOnUiThread { 124 | ResultActivity.resultString = jsonResult.toString() 125 | val intent = Intent(context, ResultActivity::class.java) 126 | startActivity(intent) 127 | } 128 | } 129 | documenName = documenName + " " + quality 130 | } catch (e1: Exception) { 131 | documenName = "" 132 | positionRect = Rect() 133 | } 134 | 135 | runOnUiThread { 136 | faceView.setFrameSize(Size(bitmap.width, bitmap.height)) 137 | faceView.setDocumentInfos(positionRect, documenName) 138 | } 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /app/src/main/java/com/kbyai/idcardrecognition/FaceView.java: -------------------------------------------------------------------------------- 1 | package com.kbyai.idcardrecognition; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.util.AttributeSet; 9 | import android.util.Log; 10 | import android.util.Size; 11 | import android.view.View; 12 | 13 | import androidx.annotation.Nullable; 14 | 15 | import java.util.List; 16 | 17 | public class FaceView extends View { 18 | 19 | private Context context; 20 | private Paint realPaint; 21 | private Paint spoofPaint; 22 | 23 | private Size frameSize; 24 | 25 | private Rect position; 26 | 27 | private String documentName; 28 | 29 | public FaceView(Context context) { 30 | this(context, null); 31 | 32 | this.context = context; 33 | init(); 34 | } 35 | 36 | public FaceView(Context context, @Nullable AttributeSet attrs) { 37 | super(context, attrs); 38 | this.context = context; 39 | 40 | init(); 41 | } 42 | 43 | public void init() { 44 | setLayerType(View.LAYER_TYPE_SOFTWARE, null); 45 | 46 | realPaint = new Paint(); 47 | realPaint.setStyle(Paint.Style.STROKE); 48 | realPaint.setStrokeWidth(3); 49 | realPaint.setColor(Color.GREEN); 50 | realPaint.setAntiAlias(true); 51 | realPaint.setTextSize(50); 52 | 53 | spoofPaint = new Paint(); 54 | spoofPaint.setStyle(Paint.Style.STROKE); 55 | spoofPaint.setStrokeWidth(3); 56 | spoofPaint.setColor(Color.RED); 57 | spoofPaint.setAntiAlias(true); 58 | spoofPaint.setTextSize(50); 59 | } 60 | 61 | public void setFrameSize(Size frameSize) 62 | { 63 | this.frameSize = frameSize; 64 | } 65 | 66 | public void setDocumentInfos(Rect position, String documentName) 67 | { 68 | this.position = position; 69 | this.documentName = documentName; 70 | invalidate(); 71 | } 72 | 73 | @Override 74 | protected void onDraw(Canvas canvas) { 75 | super.onDraw(canvas); 76 | 77 | if(position != null && !position.isEmpty()) { 78 | float x_scale = this.frameSize.getWidth() / (float)canvas.getWidth(); 79 | float y_scale = this.frameSize.getHeight() / (float)canvas.getHeight(); 80 | 81 | realPaint.setStrokeWidth(3); 82 | realPaint.setStyle(Paint.Style.FILL_AND_STROKE); 83 | canvas.drawText(documentName, (position.left / x_scale) + 10, (position.top / y_scale) - 30, realPaint); 84 | 85 | realPaint.setStyle(Paint.Style.STROKE); 86 | realPaint.setStrokeWidth(5); 87 | 88 | canvas.drawRect(new Rect((int)(position.left / x_scale), (int)(position.top / y_scale), 89 | (int)(position.right / x_scale), (int)(position.bottom / y_scale)), realPaint); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/kbyai/idcardrecognition/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.kbyai.idcardrecognition 2 | 3 | import android.content.Intent 4 | import android.graphics.Bitmap 5 | import android.os.Bundle 6 | import android.util.Log 7 | import android.widget.Button 8 | import android.widget.TextView 9 | import androidx.appcompat.app.AppCompatActivity 10 | import com.kbyai.idsdk.IDSDK 11 | import org.json.JSONObject 12 | import android.widget.Toast 13 | 14 | class MainActivity : AppCompatActivity() { 15 | companion object { 16 | private val SELECT_PHOTO_REQUEST_CODE = 1 17 | private val IDCARD_RECOGNITION_REQUEST_CODE = 2 18 | } 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | setContentView(R.layout.activity_main) 23 | 24 | var ret = IDSDK.setActivation( 25 | "kUWgfFn5kv5ZeJ659tvyW3poZO2xb5llqL/se3g69rVmUJdOuUp8lyAwoeiZe+6e6PeER97sw4zL\n" + 26 | "/rMR0qYVp0nupe6W7TzgQHtjq119BJKVDuxXjbQEyuM29nSEeRVYSwO2htOUEF/V1IH9BIfo33Vc\n" + 27 | "sAg9ohvVuB5DT9BKHXQKevmEmE2AXba2t6ponKAUQ6VwWIX+w1NON8A+6hCoSIDlzVkacbsAp6Kg\n" + 28 | "B0Abfqzbqhz8GG5WNPZlonx7XRNwKlYU+sPo/X6noy1gr7iAAhC+KpWetD2KOWsunyAswkZ5cg2Y\n" + 29 | "WK5/HQXG+h2oGSkjrZj9zH7kGbzzDbn+2qT2jA==" 30 | ) 31 | if(ret == IDSDK.SDK_SUCCESS) { 32 | ret = IDSDK.init(this) 33 | } 34 | 35 | findViewById