feat: 增加ocr文字识别功能
1
ocr/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
61
ocr/build.gradle
Normal file
@@ -0,0 +1,61 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.navinfo.ocr'
|
||||
compileSdk 31
|
||||
|
||||
defaultConfig {
|
||||
minSdk 23
|
||||
targetSdk 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
ndk {
|
||||
abiFilters "armeabi", "armeabi-v7a"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
packagingOptions {
|
||||
doNotStrip '**/*.so' // 避免so资源文件编译提示,可忽略
|
||||
}
|
||||
}
|
||||
release {
|
||||
packagingOptions {
|
||||
doNotStrip '**/*.so' // 避免so资源文件编译提示,可忽略
|
||||
}
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'com.google.android.material:material:1.8.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
api files('libs/easyedge-sdk.jar')
|
||||
}
|
||||
BIN
ocr/libs/arm64-v8a/libc++_shared.so
Normal file
BIN
ocr/libs/arm64-v8a/libedge-infer.so
Normal file
BIN
ocr/libs/armeabi-v7a/libc++_shared.so
Normal file
BIN
ocr/libs/armeabi-v7a/libedge-infer.so
Normal file
BIN
ocr/libs/easyedge-sdk.jar
Normal file
21
ocr/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.navinfo.ocr
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.navinfo.ocr", appContext.packageName)
|
||||
}
|
||||
}
|
||||
8
ocr/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- <application-->
|
||||
<!-- android:allowBackup="true"-->
|
||||
<!-- />-->
|
||||
|
||||
</manifest>
|
||||
26
ocr/src/main/assets/infer/infer_cfg.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"version": 1,
|
||||
"framework": "fluid",
|
||||
"model_info": {
|
||||
"n_type": 0,
|
||||
"best_threshold": 0.1,
|
||||
"model_kind": 100
|
||||
},
|
||||
"pre_process": {
|
||||
"mean": [123.675, 116.28, 103.53],
|
||||
"scale": [
|
||||
0.01712475383166,
|
||||
0.01750700280112,
|
||||
0.01742919389978
|
||||
],
|
||||
"color_format": "BGR",
|
||||
"channel_order": "CHW",
|
||||
"resize": [960, 960],
|
||||
"rescale_mode": "keep_ratio",
|
||||
"max_size":960,
|
||||
"ocr_rec_resize": [320,32]
|
||||
},
|
||||
"extra": {
|
||||
"fluid": {"optType": "nb"}
|
||||
}
|
||||
}
|
||||
6624
ocr/src/main/assets/infer/label_list.txt
Normal file
BIN
ocr/src/main/assets/infer/model
Normal file
BIN
ocr/src/main/assets/infer/params
Normal file
2
ocr/src/main/assets/symbols/square.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1659598895605" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3308" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||
</style></defs><path d="M885.333333 938.666667H138.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h746.666666a53.393333 53.393333 0 0 1 53.333334 53.333334v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334zM138.666667 128a10.666667 10.666667 0 0 0-10.666667 10.666667v746.666666a10.666667 10.666667 0 0 0 10.666667 10.666667h746.666666a10.666667 10.666667 0 0 0 10.666667-10.666667V138.666667a10.666667 10.666667 0 0 0-10.666667-10.666667z" fill="#A1DBF5" p-id="3309"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
209
ocr/src/main/java/com/navinfo/ocr/OCRManager.kt
Normal file
@@ -0,0 +1,209 @@
|
||||
package com.navinfo.ocr
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.baidu.ai.edge.core.base.CallException
|
||||
import com.baidu.ai.edge.core.base.Consts
|
||||
import com.baidu.ai.edge.core.infer.InferConfig
|
||||
import com.baidu.ai.edge.core.infer.InferManager
|
||||
import com.baidu.ai.edge.core.ocr.OcrInterface
|
||||
import com.baidu.ai.edge.core.ocr.OcrResultModel
|
||||
import com.baidu.ai.edge.core.util.FileUtil
|
||||
import com.navinfo.ocr.model.OcrViewResultModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
class OCRManager {
|
||||
private var mContext: Context? = null
|
||||
private var modelName = ""
|
||||
private val socList = ArrayList<String>()
|
||||
private var modelType = 0
|
||||
private var soc: String? = null
|
||||
private var mOcrManager: OcrInterface? = null
|
||||
private val CONFIDENCE = 0.3f
|
||||
|
||||
fun ocr(bitmap: Bitmap): List<OcrViewResultModel> {
|
||||
Log.e("jingo", "OCRManager 线程名称3 ${Thread.currentThread().name}")
|
||||
val list = ArrayList<OcrViewResultModel>()
|
||||
if (mOcrManager != null) {
|
||||
val modelList = mOcrManager!!.ocr(bitmap, CONFIDENCE)
|
||||
for (i in modelList.indices) {
|
||||
val mOcrResultModel: OcrResultModel = modelList[i]
|
||||
val mOcrViewResultModel = OcrViewResultModel()
|
||||
mOcrViewResultModel.colorId = mOcrResultModel.labelIndex
|
||||
mOcrViewResultModel.index = i + 1
|
||||
mOcrViewResultModel.confidence = mOcrResultModel.confidence
|
||||
mOcrViewResultModel.name = mOcrResultModel.label
|
||||
mOcrViewResultModel.bounds = mOcrResultModel.points
|
||||
mOcrViewResultModel.isTextOverlay = true
|
||||
list.add(mOcrViewResultModel)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 原有的
|
||||
*/
|
||||
private fun initConfigFromDemoConfig(): Boolean {
|
||||
val confJson =
|
||||
FileUtil.readAssetsFileUTF8StringIfExists(mContext!!.assets, "demo/config.json")
|
||||
if (TextUtils.isEmpty(confJson)) {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
val confObj = JSONObject(confJson)
|
||||
modelName = confObj.optString("modelName", "")
|
||||
val str = confObj.optString("soc", Consts.SOC_ARM)
|
||||
val socs = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
socList.addAll(listOf(*socs))
|
||||
modelType = confObj.getInt("modelType")
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 开放模型
|
||||
*/
|
||||
private fun initConfigFromDemoConf(): Boolean {
|
||||
val confJson =
|
||||
FileUtil.readAssetsFileUTF8StringIfExists(mContext!!.assets, "demo/conf.json")
|
||||
if (TextUtils.isEmpty(confJson)) {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
val confObj = JSONObject(confJson)
|
||||
modelName = confObj.optString("modelName", "")
|
||||
socList.add(Consts.SOC_ARM)
|
||||
val inferCfgJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||
mContext!!.assets,
|
||||
Consts.ASSETS_DIR_ARM + "/infer_cfg.json"
|
||||
)
|
||||
if (TextUtils.isEmpty(inferCfgJson)) {
|
||||
return false
|
||||
}
|
||||
val inferCfgObj = JSONObject(inferCfgJson)
|
||||
modelType = inferCfgObj.getJSONObject("model_info").getInt("model_kind")
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun checkChip(): Boolean {
|
||||
if (socList.contains(Consts.SOC_DSP) && Build.HARDWARE.equals("qcom", ignoreCase = true)) {
|
||||
soc = Consts.SOC_DSP
|
||||
return true
|
||||
}
|
||||
if (socList.contains(Consts.SOC_ADRENO_GPU) && Build.HARDWARE.equals(
|
||||
"qcom",
|
||||
ignoreCase = true
|
||||
)
|
||||
) {
|
||||
soc = Consts.SOC_ADRENO_GPU
|
||||
return true
|
||||
}
|
||||
if (socList.contains(Consts.SOC_NPU) && Build.HARDWARE.contains("kirin980")) {
|
||||
soc = "npu200"
|
||||
return true
|
||||
}
|
||||
if (socList.contains(Consts.SOC_NPU_VINCI)
|
||||
&& (Build.HARDWARE.contains("kirin810") || Build.HARDWARE.contains("kirin820")
|
||||
|| Build.HARDWARE.contains("kirin990") || Build.HARDWARE.contains("kirin985"))
|
||||
) {
|
||||
soc = Consts.SOC_NPU_VINCI
|
||||
return true
|
||||
}
|
||||
if (socList.contains(Consts.SOC_ARM_GPU)) {
|
||||
try {
|
||||
if (InferManager.isSupportOpencl()) {
|
||||
soc = Consts.SOC_ARM_GPU
|
||||
return true
|
||||
}
|
||||
} catch (e: CallException) {
|
||||
Toast.makeText(
|
||||
mContext, e.errorCode.toString() + ", " + e.message,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
if (socList.contains(Consts.SOC_ARM)) {
|
||||
soc = Consts.SOC_ARM
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun init(context: Context) {
|
||||
mContext = context
|
||||
if (initConfigFromDemoConfig()) {
|
||||
return
|
||||
}
|
||||
if (initConfigFromDemoConf()) {
|
||||
return
|
||||
}
|
||||
|
||||
/* 从infer/读配置 */
|
||||
var confJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||
mContext!!.applicationContext.assets,
|
||||
Consts.ASSETS_DIR_ARM + "/conf.json"
|
||||
)
|
||||
if (!TextUtils.isEmpty(confJson)) {
|
||||
try {
|
||||
val confObj = JSONObject(confJson)
|
||||
modelName = confObj.optString("modelName", "")
|
||||
val str = confObj.optString("soc", Consts.SOC_ARM)
|
||||
val socs = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
socList.addAll(listOf(*socs))
|
||||
modelType = confObj.getInt("modelType")
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} else {
|
||||
confJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||
mContext!!.applicationContext.assets,
|
||||
Consts.ASSETS_DIR_ARM + "/infer_cfg.json"
|
||||
)
|
||||
try {
|
||||
val confObj = JSONObject(confJson)
|
||||
socList.add(Consts.SOC_ARM)
|
||||
modelType = confObj.getJSONObject("model_info").getInt("model_kind")
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
MainScope().launch(Dispatchers.IO) {
|
||||
try {
|
||||
Log.e("jingo", "OCRManager 线程名称 ${Thread.currentThread().name}")
|
||||
/* 1. 准备配置类,初始化Manager类。可以在onCreate或onResume中触发,请在非UI线程里调用 */
|
||||
val config = InferConfig(context.assets, "infer")
|
||||
mOcrManager = InferManager(mContext, config, SERIAL_NUM)
|
||||
// cancel()
|
||||
} catch (e: Exception) {
|
||||
Log.e("jingo", "OCRManager 线程名称 ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val instance: OCRManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||
OCRManager()
|
||||
}
|
||||
|
||||
// 请替换为您的序列号
|
||||
private const val SERIAL_NUM = "XXXX-XXXX-XXXX-XXXX"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BasePolygonResultModel extends BaseResultModel implements Parcelable {
|
||||
private int colorId;
|
||||
private boolean isRect;
|
||||
private boolean isTextOverlay;
|
||||
|
||||
private boolean isHasGroupColor = false;
|
||||
private boolean isDrawPoints = false;
|
||||
|
||||
/**
|
||||
* 姿态一个点会有多个pair
|
||||
*/
|
||||
private boolean multiplePairs = false;
|
||||
|
||||
protected BasePolygonResultModel(Parcel in) {
|
||||
super(in);
|
||||
colorId = in.readInt();
|
||||
isRect = in.readByte() != 0;
|
||||
isTextOverlay = in.readByte() != 0;
|
||||
isHasGroupColor = in.readByte() != 0;
|
||||
isDrawPoints = in.readByte() != 0;
|
||||
multiplePairs = in.readByte() != 0;
|
||||
in.readByteArray(mask);
|
||||
semanticMask = in.readByte() != 0;
|
||||
rect = in.readParcelable(Rect.class.getClassLoader());
|
||||
bounds = in.createTypedArrayList(Point.CREATOR);
|
||||
}
|
||||
|
||||
public static final Creator<BasePolygonResultModel> CREATOR = new Creator<BasePolygonResultModel>() {
|
||||
@Override
|
||||
public BasePolygonResultModel createFromParcel(Parcel in) {
|
||||
return new BasePolygonResultModel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePolygonResultModel[] newArray(int size) {
|
||||
return new BasePolygonResultModel[size];
|
||||
}
|
||||
};
|
||||
|
||||
public boolean isTextOverlay() {
|
||||
return isTextOverlay;
|
||||
}
|
||||
|
||||
public void setTextOverlay(boolean textOverlay) {
|
||||
isTextOverlay = textOverlay;
|
||||
}
|
||||
|
||||
public int getColorId() {
|
||||
return colorId;
|
||||
}
|
||||
|
||||
public void setColorId(int colorId) {
|
||||
this.colorId = colorId;
|
||||
}
|
||||
|
||||
private byte[] mask = {};
|
||||
|
||||
/**
|
||||
* 是否是语义分割mask
|
||||
*/
|
||||
private boolean semanticMask;
|
||||
|
||||
private Rect rect;
|
||||
|
||||
BasePolygonResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
BasePolygonResultModel(int index, String name, float confidence, Rect bounds) {
|
||||
super(index, name, confidence);
|
||||
parseFromRect(bounds);
|
||||
}
|
||||
|
||||
BasePolygonResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||
super(index, name, confidence);
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
public Rect getRect() {
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Rect getRect(float ratio, Point origin) {
|
||||
return new Rect((int) (origin.x + rect.left * ratio),
|
||||
(int) (origin.y + rect.top * ratio),
|
||||
(int) (origin.x + rect.right * ratio),
|
||||
(int) (origin.y + rect.bottom * ratio));
|
||||
}
|
||||
|
||||
private void parseFromRect(Rect rect) {
|
||||
Point ptTL = new Point(rect.left, rect.top);
|
||||
Point ptTR = new Point(rect.right, rect.top);
|
||||
Point ptRB = new Point(rect.right, rect.bottom);
|
||||
Point ptLB = new Point(rect.left, rect.bottom);
|
||||
this.bounds = new ArrayList<>();
|
||||
this.bounds.add(ptTL);
|
||||
this.bounds.add(ptTR);
|
||||
this.bounds.add(ptRB);
|
||||
this.bounds.add(ptLB);
|
||||
this.rect = rect;
|
||||
isRect = true;
|
||||
}
|
||||
|
||||
public boolean isRect() {
|
||||
return isRect;
|
||||
}
|
||||
|
||||
public void setRect(boolean rect) {
|
||||
isRect = rect;
|
||||
}
|
||||
|
||||
public byte[] getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public void setMask(byte[] mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public void setSemanticMask(boolean semanticMask) {
|
||||
this.semanticMask = semanticMask;
|
||||
}
|
||||
|
||||
public boolean isSemanticMask() {
|
||||
return semanticMask;
|
||||
}
|
||||
|
||||
private List<Point> bounds;
|
||||
|
||||
public List<Point> getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public List<Point> getBounds(float ratio, Point origin) {
|
||||
List<Point> pointList = new ArrayList<>();
|
||||
for (Point pt : bounds) {
|
||||
int nx = (int) (origin.x + pt.x * ratio);
|
||||
int ny = (int) (origin.y + pt.y * ratio);
|
||||
pointList.add(new Point(nx, ny));
|
||||
}
|
||||
return pointList;
|
||||
}
|
||||
|
||||
public void setBounds(List<Point> bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
public void setBounds(Rect bounds) {
|
||||
parseFromRect(bounds);
|
||||
}
|
||||
|
||||
public boolean isHasMask() {
|
||||
return (mask != null);
|
||||
}
|
||||
|
||||
public boolean isHasGroupColor() {
|
||||
return isHasGroupColor;
|
||||
}
|
||||
|
||||
public void setHasGroupColor(boolean hasGroupColor) {
|
||||
isHasGroupColor = hasGroupColor;
|
||||
}
|
||||
|
||||
public boolean isDrawPoints() {
|
||||
return isDrawPoints;
|
||||
}
|
||||
|
||||
public void setDrawPoints(boolean drawPoints) {
|
||||
isDrawPoints = drawPoints;
|
||||
}
|
||||
|
||||
public void setMultiplePairs(boolean multiplePairs) {
|
||||
this.multiplePairs = multiplePairs;
|
||||
}
|
||||
|
||||
public boolean isMultiplePairs() {
|
||||
return multiplePairs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest,flags);
|
||||
dest.writeInt(colorId);
|
||||
dest.writeByte((byte) (isRect ? 1 : 0));
|
||||
dest.writeByte((byte) (isTextOverlay ? 1 : 0));
|
||||
dest.writeByte((byte) (isHasGroupColor ? 1 : 0));
|
||||
dest.writeByte((byte) (isDrawPoints ? 1 : 0));
|
||||
dest.writeByte((byte) (multiplePairs ? 1 : 0));
|
||||
dest.writeByteArray(mask);
|
||||
dest.writeByte((byte) (semanticMask ? 1 : 0));
|
||||
dest.writeParcelable(rect, flags);
|
||||
dest.writeTypedList(bounds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Created by ruanshimin on 2018/5/16.
|
||||
*/
|
||||
|
||||
public class BaseRectBoundResultModel extends BaseResultModel implements Parcelable {
|
||||
|
||||
private int colorId;
|
||||
|
||||
protected BaseRectBoundResultModel(Parcel in) {
|
||||
super(in);
|
||||
colorId = in.readInt();
|
||||
in.readByteArray(mask);
|
||||
bounds = in.readParcelable(Rect.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final Creator<BaseRectBoundResultModel> CREATOR = new Creator<BaseRectBoundResultModel>() {
|
||||
@Override
|
||||
public BaseRectBoundResultModel createFromParcel(Parcel in) {
|
||||
return new BaseRectBoundResultModel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseRectBoundResultModel[] newArray(int size) {
|
||||
return new BaseRectBoundResultModel[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int getColorId() {
|
||||
return colorId;
|
||||
}
|
||||
|
||||
public void setColorId(int colorId) {
|
||||
this.colorId = colorId;
|
||||
}
|
||||
|
||||
private byte[] mask = {};
|
||||
|
||||
BaseRectBoundResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
BaseRectBoundResultModel(int index, String name, float confidence, Rect bounds) {
|
||||
super(index, name, confidence);
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
public byte[] getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
public void setMask(byte[] mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
private Rect bounds;
|
||||
|
||||
public Rect getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public Rect getBounds(float ratio, Point origin) {
|
||||
return new Rect((int) (origin.x + bounds.left * ratio),
|
||||
(int) (origin.y + bounds.top * ratio),
|
||||
(int) (origin.x + bounds.right * ratio),
|
||||
(int) (origin.y + bounds.bottom * ratio));
|
||||
}
|
||||
|
||||
public void setBounds(Rect bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
public boolean isHasMask() {
|
||||
return (mask != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(colorId);
|
||||
dest.writeByteArray(mask);
|
||||
dest.writeParcelable(bounds, flags);
|
||||
}
|
||||
}
|
||||
80
ocr/src/main/java/com/navinfo/ocr/model/BaseResultModel.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by ruanshimin on 2018/5/16.
|
||||
*/
|
||||
|
||||
public class BaseResultModel implements Parcelable {
|
||||
private int index = 0;
|
||||
private String name = "";
|
||||
private float confidence = 0;
|
||||
|
||||
protected BaseResultModel() {
|
||||
|
||||
}
|
||||
|
||||
protected BaseResultModel(int index, String name, float confidence) {
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
protected BaseResultModel(Parcel in) {
|
||||
index = in.readInt();
|
||||
name = in.readString();
|
||||
confidence = in.readFloat();
|
||||
}
|
||||
|
||||
public static final Creator<BaseResultModel> CREATOR = new Creator<BaseResultModel>() {
|
||||
@Override
|
||||
public BaseResultModel createFromParcel(Parcel in) {
|
||||
return new BaseResultModel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseResultModel[] newArray(int size) {
|
||||
return new BaseResultModel[size];
|
||||
}
|
||||
};
|
||||
|
||||
public float getConfidence() {
|
||||
return confidence;
|
||||
}
|
||||
|
||||
public void setConfidence(float confidence) {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(index);
|
||||
dest.writeString(name);
|
||||
dest.writeFloat(confidence);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by ruanshimin on 2018/5/13.
|
||||
*/
|
||||
|
||||
public class ClassifyResultModel extends BaseResultModel {
|
||||
|
||||
|
||||
public ClassifyResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ClassifyResultModel(int index, String name, float confidence) {
|
||||
|
||||
super(index, name, confidence);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.graphics.Rect;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by ruanshimin on 2018/5/13.
|
||||
*/
|
||||
|
||||
public class DetectResultModel extends BasePolygonResultModel {
|
||||
public DetectResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DetectResultModel(int index, String name, float confidence, Rect bounds) {
|
||||
super(index, name, confidence, bounds);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class OcrViewResultModel extends BasePolygonResultModel{
|
||||
public OcrViewResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
public OcrViewResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||
super(index, name, confidence, bounds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PoseViewResultModel extends BasePolygonResultModel {
|
||||
public PoseViewResultModel() {
|
||||
super();
|
||||
setRect(false);
|
||||
setTextOverlay(false);
|
||||
setDrawPoints(true);
|
||||
setMultiplePairs(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.navinfo.ocr.model;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by ruanshimin on 2018/5/13.
|
||||
*/
|
||||
|
||||
public class SegmentResultModel extends BasePolygonResultModel {
|
||||
|
||||
public SegmentResultModel() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SegmentResultModel(int index, String name, float confidence, List<Point> bounds, byte[] mask) {
|
||||
super(index, name, confidence, bounds);
|
||||
this.setMask(mask);
|
||||
}
|
||||
|
||||
public SegmentResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||
super(index, name, confidence, bounds);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
30
ocr/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
170
ocr/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
5
ocr/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
5
ocr/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
6
ocr/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
ocr/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
ocr/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
ocr/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
ocr/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
ocr/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
ocr/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
ocr/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
ocr/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
ocr/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
ocr/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
16
ocr/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.NavinfoCollect" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
10
ocr/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
3
ocr/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">ocr</string>
|
||||
</resources>
|
||||
16
ocr/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.NavinfoCollect" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
17
ocr/src/test/java/com/navinfo/ocr/ExampleUnitTest.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.navinfo.ocr
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||