├── .gitignore ├── .idea ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wt │ │ └── ocr │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── tessdata │ │ ├── chi_sim.traineddata │ │ └── eng.traineddata │ ├── java │ └── com │ │ └── wt │ │ └── ocr │ │ ├── App.java │ │ ├── BaseActivity.java │ │ ├── CutOutPhotoActivity.java │ │ ├── MainActivity.java │ │ ├── ShowCropperedActivity.java │ │ ├── TakePhoteActivity.java │ │ ├── camear │ │ └── ReferenceLine.java │ │ └── utils │ │ ├── UriUtils.java │ │ └── Utils.java │ └── res │ ├── anim │ ├── fade_in.xml │ └── fade_out.xml │ ├── drawable-hdpi │ ├── answer_btn_answered.png │ ├── ic_close_click.png │ ├── ic_close_normal.png │ ├── ic_ok_click.png │ ├── ic_ok_normal.png │ ├── ic_takephoto_click.png │ ├── ic_takephoto_normal.png │ └── icon_camera.png │ ├── drawable-xhdpi │ ├── to_camera.png │ └── to_camera_pressed.png │ ├── drawable │ ├── button_press.xml │ ├── ic_close_selector.xml │ ├── ic_ok_selector.xml │ └── ic_takephoto_selector.xml │ ├── layout │ ├── activity_cutout_phote.xml │ ├── activity_main.xml │ ├── activity_show_croppered.xml │ └── activity_take_phote.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot (1).jpg ├── screenshot (2).jpg ├── screenshot (3).jpg ├── screenshot.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | <<<<<<< HEAD 2 | *.class 3 | 4 | # Mobile Tools for Java (J2ME) 5 | .mtj.tmp/ 6 | 7 | # Package Files # 8 | *.jar 9 | *.war 10 | *.ear 11 | 12 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 13 | hs_err_pid* 14 | ======= 15 | *.iml 16 | .gradle 17 | /local.properties 18 | /.idea/workspace.xml 19 | /.idea/libraries 20 | .DS_Store 21 | /build 22 | /captures 23 | .externalNativeBuild 24 | >>>>>>> init commit 25 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Android 16 | 17 | 18 | CorrectnessLintAndroid 19 | 20 | 21 | LintAndroid 22 | 23 | 24 | PerformanceLintAndroid 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidOCR 2 | Tesseract-OCR 文字识别DEMO 3 | ## Document/文档 4 | [详细说明](https://wangtaot.github.io/2017/11/25/Android-OCR%E4%B9%8BTess-two/) 5 | ## main/主界面 6 |   7 | 8 | ## Take pictures/拍照 9 |   10 | 11 | ## Clipping/截图 12 |   13 | 14 | ## Identification/识别 15 |   16 | 17 | ## Description/说明 18 | app/src/main/assets/tessdata 19 | chi_sim.traineddata Chinese中文字典 20 | eng.traineddata English英文字典 21 | 22 | --- 23 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 33 5 | 6 | defaultConfig { 7 | applicationId "com.wt.ocr" 8 | minSdkVersion 21 9 | targetSdkVersion 33 10 | versionCode 2 11 | versionName "1.1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | dataBinding { 22 | enabled = true 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | //noinspection GradleCompatible 29 | implementation 'androidx.appcompat:appcompat:1.1.0' 30 | testImplementation 'junit:junit:4.12' 31 | 32 | def camerax_version = "1.3.0-alpha04" 33 | // CameraX core library 34 | implementation "androidx.camera:camera-core:$camerax_version" 35 | implementation "androidx.camera:camera-camera2:$camerax_version" 36 | implementation "androidx.camera:camera-lifecycle:$camerax_version" 37 | implementation "androidx.camera:camera-view:$camerax_version" 38 | 39 | //图像裁剪 40 | implementation 'com.edmodo:cropper:1.0.1' 41 | //文字识别 42 | implementation 'cz.adaptech.tesseract4android:tesseract4android:4.4.0' 43 | 44 | //google分析 45 | implementation platform('com.google.firebase:firebase-bom:31.5.0') 46 | implementation 'com.google.firebase:firebase-analytics' 47 | } 48 | apply plugin: 'com.google.gms.google-services' 49 | 50 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "220740679524", 4 | "project_id": "androidocr-196803" 5 | }, 6 | "client": [ 7 | { 8 | "client_info": { 9 | "mobilesdk_app_id": "1:220740679524:android:491dca6eb0989d5b", 10 | "android_client_info": { 11 | "package_name": "com.wt.ocr" 12 | } 13 | }, 14 | "oauth_client": [ 15 | { 16 | "client_id": "220740679524-ban0i86aejdj3387356lrc1l5638oup3.apps.googleusercontent.com", 17 | "client_type": 3 18 | } 19 | ], 20 | "api_key": [ 21 | { 22 | "current_key": "AIzaSyA6NJet6K0HLOV1JZ7G5sN3ID79XWPVa9g" 23 | } 24 | ], 25 | "services": { 26 | "analytics_service": { 27 | "status": 2, 28 | "analytics_property": { 29 | "tracking_id": "UA-108813768-1" 30 | } 31 | }, 32 | "appinvite_service": { 33 | "status": 1, 34 | "other_platform_oauth_client": [] 35 | }, 36 | "ads_service": { 37 | "status": 1 38 | } 39 | } 40 | } 41 | ], 42 | "configuration_version": "1" 43 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wt/ocr/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.wt.ocr", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 40 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/assets/tessdata/chi_sim.traineddata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/assets/tessdata/chi_sim.traineddata -------------------------------------------------------------------------------- /app/src/main/assets/tessdata/eng.traineddata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/assets/tessdata/eng.traineddata -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/App.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.camera.camera2.Camera2Config; 7 | import androidx.camera.core.CameraXConfig; 8 | 9 | /** 10 | * Created by wangt on 2018/3/2. 11 | */ 12 | 13 | public class App extends Application implements CameraXConfig.Provider { 14 | 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | } 19 | 20 | @NonNull 21 | @Override 22 | public CameraXConfig getCameraXConfig() { 23 | return Camera2Config.defaultConfig(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.os.Bundle; 4 | import androidx.annotation.Nullable; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | /** 8 | * Created by wangt on 2018/3/2. 9 | */ 10 | 11 | public class BaseActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/CutOutPhotoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.Bundle; 7 | 8 | import androidx.annotation.Nullable; 9 | import androidx.databinding.DataBindingUtil; 10 | 11 | import com.wt.ocr.databinding.ActivityCutoutPhoteBinding; 12 | 13 | import java.io.File; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.io.OutputStream; 17 | 18 | /** 19 | * 裁剪 20 | */ 21 | public class CutOutPhotoActivity extends BaseActivity { 22 | 23 | private ActivityCutoutPhoteBinding mBinding; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | mBinding = DataBindingUtil.setContentView(this, R.layout.activity_cutout_phote); 29 | String path = getIntent().getStringExtra("path"); 30 | Bitmap bitmap = BitmapFactory.decodeFile(path); 31 | 32 | mBinding.cropImageView.setImageBitmap(bitmap); 33 | 34 | mBinding.btnClosecropper.setOnClickListener(view -> finish()); 35 | 36 | mBinding.btnStartcropper.setOnClickListener(view -> { 37 | Bitmap cropperBitmap = mBinding.cropImageView.getCroppedImage(); 38 | // 图像名称 39 | String path1 = getCacheDir().getPath(); 40 | String resultPath = saveImage(path1, cropperBitmap); 41 | 42 | Intent intent = new Intent(CutOutPhotoActivity.this, ShowCropperedActivity.class); 43 | intent.putExtra("path", resultPath); 44 | intent.putExtra("width", cropperBitmap.getWidth()); 45 | intent.putExtra("height", cropperBitmap.getHeight()); 46 | startActivity(intent); 47 | cropperBitmap.recycle(); 48 | finish(); 49 | }); 50 | } 51 | 52 | /** 53 | * 存储图像 54 | */ 55 | private String saveImage(String path, Bitmap source) { 56 | OutputStream outputStream = null; 57 | File file; 58 | try { 59 | File dir = new File(path); 60 | if (!dir.exists()) { 61 | dir.mkdirs(); 62 | } 63 | file = new File(path, System.currentTimeMillis() + ".jpg"); 64 | if (file.createNewFile()) { 65 | outputStream = new FileOutputStream(file); 66 | if (source != null) { 67 | source.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); 68 | } 69 | } 70 | } catch (IOException e) { 71 | return ""; 72 | } finally { 73 | if (outputStream != null) { 74 | try { 75 | outputStream.close(); 76 | } catch (Throwable t) { 77 | } 78 | } 79 | } 80 | 81 | return file.getPath(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.core.app.ActivityCompat; 12 | import androidx.core.content.ContextCompat; 13 | import androidx.databinding.DataBindingUtil; 14 | import com.google.firebase.analytics.FirebaseAnalytics; 15 | import com.wt.ocr.databinding.ActivityMainBinding; 16 | 17 | import java.io.File; 18 | import java.io.FileOutputStream; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | 22 | public class MainActivity extends BaseActivity implements View.OnClickListener { 23 | 24 | private static final int PERMISSIONS_REQUEST_CAMERA = 454; 25 | 26 | static final String PERMISSION_CAMERA = Manifest.permission.CAMERA; 27 | static final String PERMISSION_WRITE_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE; 28 | 29 | private FirebaseAnalytics mFirebaseAnalytics; 30 | 31 | private ActivityMainBinding mBinding; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); 37 | mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); 38 | 39 | mBinding.btnCamera.setOnClickListener(this); 40 | 41 | new Thread(new Runnable() { 42 | @Override 43 | public void run() { 44 | deepFile("tessdata"); 45 | } 46 | }).start(); 47 | } 48 | 49 | public void onClick(View view) { 50 | if (view.getId() == R.id.btn_camera) { 51 | checkSelfPermission(); 52 | //google分析 53 | Bundle bundle = new Bundle(); 54 | bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "main"); 55 | bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "拍照"); 56 | bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "Action"); 57 | mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle); 58 | } 59 | } 60 | 61 | /** 62 | * 将assets中的文件复制出 63 | * 64 | * @param path 65 | */ 66 | public void deepFile(String path) { 67 | String newPath = getExternalFilesDir(null) + "/"; 68 | try { 69 | String str[] = getAssets().list(path); 70 | if (str.length > 0) {//如果是目录 71 | File file = new File(newPath + path); 72 | file.mkdirs(); 73 | for (String string : str) { 74 | path = path + "/" + string; 75 | deepFile(path); 76 | path = path.substring(0, path.lastIndexOf('/'));//回到原来的path 77 | } 78 | } else {//如果是文件 79 | InputStream is = getAssets().open(path); 80 | FileOutputStream fos = new FileOutputStream(new File(newPath + path)); 81 | byte[] buffer = new byte[1024]; 82 | while (true) { 83 | int len = is.read(buffer); 84 | if (len == -1) { 85 | break; 86 | } 87 | fos.write(buffer, 0, len); 88 | } 89 | is.close(); 90 | fos.close(); 91 | } 92 | } catch (IOException e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | 97 | 98 | @Override 99 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 100 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 101 | if (requestCode == PERMISSIONS_REQUEST_CAMERA) { 102 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 103 | Intent intent = new Intent(this, TakePhoteActivity.class); 104 | startActivity(intent); 105 | } else { 106 | Toast.makeText(this, "请开启权限", Toast.LENGTH_SHORT).show(); 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * 检查权限 113 | */ 114 | void checkSelfPermission() { 115 | if (ContextCompat.checkSelfPermission(this, PERMISSION_CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, PERMISSION_WRITE_STORAGE) != PackageManager.PERMISSION_GRANTED) { 116 | ActivityCompat.requestPermissions(this, new String[]{PERMISSION_CAMERA, PERMISSION_WRITE_STORAGE}, PERMISSIONS_REQUEST_CAMERA); 117 | } else { 118 | Intent intent = new Intent(this, TakePhoteActivity.class); 119 | startActivity(intent); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/ShowCropperedActivity.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.ColorMatrix; 9 | import android.graphics.ColorMatrixColorFilter; 10 | import android.graphics.Paint; 11 | import android.net.Uri; 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | 15 | import androidx.appcompat.app.AppCompatActivity; 16 | 17 | import android.util.Log; 18 | import android.view.ViewGroup; 19 | import android.widget.ImageView; 20 | import android.widget.TextView; 21 | 22 | import com.googlecode.tesseract.android.TessBaseAPI; 23 | import com.wt.ocr.utils.Utils; 24 | 25 | 26 | /** 27 | * 显示截图结果 28 | * 并识别 29 | */ 30 | public class ShowCropperedActivity extends AppCompatActivity { 31 | 32 | private Context context; 33 | //sd卡路径 34 | private static String LANGUAGE_PATH = ""; 35 | //识别语言 36 | private static final String LANGUAGE = "chi_sim";//chi_sim | eng 37 | private static final String TAG = "ShowCropperedActivity"; 38 | private ImageView imageView; 39 | private ImageView imageView2; 40 | private TextView textView; 41 | 42 | private int width; 43 | private int height; 44 | private String path; 45 | private String result; 46 | 47 | private TessBaseAPI baseApi = new TessBaseAPI(); 48 | private Handler handler = new Handler(); 49 | private ProgressDialog dialog; 50 | 51 | private ColorMatrix colorMatrix; 52 | 53 | @Override 54 | protected void onCreate(Bundle savedInstanceState) { 55 | super.onCreate(savedInstanceState); 56 | setContentView(R.layout.activity_show_croppered); 57 | context = this; 58 | LANGUAGE_PATH = getExternalFilesDir("") + "/"; 59 | Log.e("---------", LANGUAGE_PATH); 60 | 61 | width = getIntent().getIntExtra("width", 0); 62 | height = getIntent().getIntExtra("height", 0); 63 | path = getIntent().getStringExtra("path"); 64 | 65 | initView(); 66 | initTess(); 67 | } 68 | 69 | @Override 70 | protected void onResume() { 71 | super.onResume(); 72 | dialog = new ProgressDialog(context); 73 | dialog.setMessage("正在识别..."); 74 | dialog.setCancelable(false); 75 | dialog.show(); 76 | } 77 | 78 | private void initView() { 79 | imageView = findViewById(R.id.image); 80 | imageView2 = findViewById(R.id.image2); 81 | textView = findViewById(R.id.text); 82 | 83 | if (width != 0 && height != 0) { 84 | int screenWidth = Utils.getWidthInPx(this); 85 | float scale = (float) screenWidth / (float) width; 86 | final ViewGroup.LayoutParams lp = imageView.getLayoutParams(); 87 | int imgHeight = (int) (scale * height); 88 | lp.height = imgHeight; 89 | imageView.setLayoutParams(lp); 90 | Log.e(TAG, "imageView.getLayoutParams().width:" + imageView.getLayoutParams().width); 91 | } 92 | imageView.setImageURI(Uri.parse(path)); 93 | } 94 | 95 | private void initTess() { 96 | //字典库 97 | baseApi.init(LANGUAGE_PATH, LANGUAGE); 98 | //设置设别模式 99 | baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO); 100 | Thread myThread = new Thread(runnable); 101 | myThread.start(); 102 | } 103 | 104 | 105 | /** 106 | * 灰度化处理 107 | */ 108 | public Bitmap convertGray(Bitmap bitmap3) { 109 | colorMatrix = new ColorMatrix(); 110 | colorMatrix.setSaturation(0); 111 | ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix); 112 | 113 | Paint paint = new Paint(); 114 | paint.setColorFilter(filter); 115 | Bitmap result = Bitmap.createBitmap(bitmap3.getWidth(), bitmap3.getHeight(), Bitmap.Config.ARGB_8888); 116 | Canvas canvas = new Canvas(result); 117 | 118 | canvas.drawBitmap(bitmap3, 0, 0, paint); 119 | return result; 120 | } 121 | 122 | /** 123 | * 二值化 124 | * 125 | * @param tmp 二值化阈值 默认100 126 | */ 127 | private Bitmap binaryzation(Bitmap bitmap22, int tmp) { 128 | // 获取图片的宽和高 129 | int width = bitmap22.getWidth(); 130 | int height = bitmap22.getHeight(); 131 | // 创建二值化图像 132 | Bitmap bitmap; 133 | bitmap = bitmap22.copy(Bitmap.Config.ARGB_8888, true); 134 | // 遍历原始图像像素,并进行二值化处理 135 | for (int i = 0; i < width; i++) { 136 | for (int j = 0; j < height; j++) { 137 | // 得到当前的像素值 138 | int pixel = bitmap.getPixel(i, j); 139 | // 得到Alpha通道的值 140 | int alpha = pixel & 0xFF000000; 141 | // 得到Red的值 142 | int red = (pixel & 0x00FF0000) >> 16; 143 | // 得到Green的值 144 | int green = (pixel & 0x0000FF00) >> 8; 145 | // 得到Blue的值 146 | int blue = pixel & 0x000000FF; 147 | 148 | if (red > tmp) { 149 | red = 255; 150 | } else { 151 | red = 0; 152 | } 153 | if (blue > tmp) { 154 | blue = 255; 155 | } else { 156 | blue = 0; 157 | } 158 | if (green > tmp) { 159 | green = 255; 160 | } else { 161 | green = 0; 162 | } 163 | 164 | // 通过加权平均算法,计算出最佳像素值 165 | int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11); 166 | // 对图像设置黑白图 167 | if (gray <= 95) { 168 | gray = 0; 169 | } else { 170 | gray = 255; 171 | } 172 | // 得到新的像素值 173 | int newPiexl = alpha | (gray << 16) | (gray << 8) | gray; 174 | // 赋予新图像的像素 175 | bitmap.setPixel(i, j, newPiexl); 176 | } 177 | } 178 | return bitmap; 179 | } 180 | 181 | /** 182 | * 识别线程 183 | */ 184 | private Runnable runnable = new Runnable() { 185 | @Override 186 | public void run() { 187 | final Bitmap bitmap_1 = convertGray(BitmapFactory.decodeFile(path)); 188 | 189 | baseApi.setImage(bitmap_1); 190 | result = baseApi.getUTF8Text(); 191 | baseApi.recycle(); 192 | 193 | handler.post(new Runnable() { 194 | @Override 195 | public void run() { 196 | imageView2.setImageBitmap(bitmap_1); 197 | textView.setText(result); 198 | dialog.dismiss(); 199 | } 200 | }); 201 | } 202 | }; 203 | } 204 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/TakePhoteActivity.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.provider.MediaStore; 8 | import android.util.Log; 9 | import android.view.Surface; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.view.animation.LinearInterpolator; 14 | import android.widget.ImageView; 15 | import android.widget.TextView; 16 | import android.widget.Toast; 17 | 18 | import androidx.annotation.NonNull; 19 | import androidx.appcompat.app.AppCompatActivity; 20 | import androidx.camera.core.AspectRatio; 21 | import androidx.camera.core.CameraSelector; 22 | import androidx.camera.core.ImageCapture; 23 | import androidx.camera.core.ImageCaptureException; 24 | import androidx.camera.core.Preview; 25 | import androidx.camera.lifecycle.ProcessCameraProvider; 26 | import androidx.core.content.ContextCompat; 27 | import androidx.databinding.DataBindingUtil; 28 | 29 | import com.google.common.util.concurrent.ListenableFuture; 30 | import com.wt.ocr.databinding.ActivityTakePhoteBinding; 31 | import com.wt.ocr.utils.UriUtils; 32 | 33 | import java.io.File; 34 | 35 | /** 36 | * 拍照界面 37 | * Created by Administrator on 2016/12/8. 38 | */ 39 | public class TakePhoteActivity extends AppCompatActivity { 40 | 41 | public static final boolean isTransverse = true; 42 | 43 | private static final String TAG = "TakePhoteActivity"; 44 | public static final Uri IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 45 | private ImageCapture imageCapture; 46 | 47 | private ActivityTakePhoteBinding mBinding; 48 | 49 | /** 50 | * 旋转文字 51 | */ 52 | private boolean isRotated = false; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | // 设置全屏 58 | requestWindowFeature(Window.FEATURE_NO_TITLE); 59 | mBinding = DataBindingUtil.setContentView(this, R.layout.activity_take_phote); 60 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 61 | 62 | mBinding.btnClose.setOnClickListener(onClickListener); 63 | mBinding.btnShutter.setOnClickListener(onClickListener); 64 | mBinding.btnAlbum.setOnClickListener(onClickListener); 65 | 66 | startCamera(); 67 | } 68 | 69 | @Override 70 | protected void onResume() { 71 | super.onResume(); 72 | if (isTransverse) { 73 | if (!isRotated) { 74 | TextView tvHint = findViewById(R.id.hint); 75 | ObjectAnimator animator = ObjectAnimator.ofFloat(tvHint, "rotation", 0f, 90f); 76 | animator.setStartDelay(800); 77 | animator.setDuration(500); 78 | animator.setInterpolator(new LinearInterpolator()); 79 | animator.start(); 80 | 81 | ImageView btnShutter = findViewById(R.id.btn_shutter); 82 | ObjectAnimator animator1 = ObjectAnimator.ofFloat(btnShutter, "rotation", 0f, 90f); 83 | animator1.setStartDelay(800); 84 | animator1.setDuration(500); 85 | animator1.setInterpolator(new LinearInterpolator()); 86 | animator1.start(); 87 | 88 | ObjectAnimator animator3 = ObjectAnimator.ofFloat(mBinding.btnAlbum, "rotation", 0f, 90f); 89 | animator3.setStartDelay(800); 90 | animator3.setDuration(500); 91 | animator3.setInterpolator(new LinearInterpolator()); 92 | animator3.start(); 93 | isRotated = true; 94 | } 95 | } 96 | } 97 | 98 | /** 99 | * 开始预览 100 | */ 101 | private void startCamera() { 102 | // 将Camera的生命周期和Activity绑定在一起(设定生命周期所有者),这样就不用手动控制相机的启动和关闭。 103 | ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this); 104 | 105 | cameraProviderFuture.addListener(() -> { 106 | try { 107 | // 将你的相机和当前生命周期的所有者绑定所需的对象 108 | ProcessCameraProvider processCameraProvider = cameraProviderFuture.get(); 109 | 110 | // 创建一个Preview 实例,并设置该实例的 surface 提供者(provider)。 111 | Preview preview = new Preview.Builder() 112 | .setTargetRotation(Surface.ROTATION_90) 113 | .setTargetAspectRatio(AspectRatio.RATIO_16_9) 114 | .build(); 115 | preview.setSurfaceProvider(mBinding.preview.getSurfaceProvider()); 116 | 117 | // 选择后置摄像头作为默认摄像头 118 | CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; 119 | 120 | // 创建拍照所需的实例 121 | imageCapture = new ImageCapture.Builder() 122 | .setTargetRotation(Surface.ROTATION_90) 123 | .setTargetAspectRatio(AspectRatio.RATIO_16_9) 124 | .build(); 125 | 126 | // 重新绑定用例前先解绑 127 | processCameraProvider.unbindAll(); 128 | 129 | // 绑定用例至相机 130 | processCameraProvider.bindToLifecycle(this, cameraSelector, 131 | preview, 132 | imageCapture); 133 | 134 | } catch (Exception e) { 135 | } 136 | }, ContextCompat.getMainExecutor(this)); 137 | } 138 | 139 | private void takePhoto() { 140 | if (imageCapture != null) { 141 | // 创建带时间戳的输出文件以保存图片,带时间戳是为了保证文件名唯一 142 | File photoFile = new File(getCacheDir(), "/" + System.currentTimeMillis() + ".jpg"); 143 | 144 | // 创建 output option 对象,用以指定照片的输出方式 145 | ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions 146 | .Builder(photoFile) 147 | .build(); 148 | 149 | // 执行takePicture(拍照)方法 150 | imageCapture.takePicture(outputFileOptions, 151 | ContextCompat.getMainExecutor(this), 152 | new ImageCapture.OnImageSavedCallback() {// 保存照片时的回调 153 | @Override 154 | public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { 155 | Uri savedUri = Uri.fromFile(photoFile); 156 | launchActivity(savedUri); 157 | } 158 | 159 | @Override 160 | public void onError(@NonNull ImageCaptureException exception) { 161 | } 162 | }); 163 | } 164 | } 165 | 166 | /** 167 | * 拍照界面 168 | */ 169 | private View.OnClickListener onClickListener = new View.OnClickListener() { 170 | @Override 171 | public void onClick(View view) { 172 | switch (view.getId()) { 173 | case R.id.btn_close: //关闭相机 174 | finish(); 175 | break; 176 | case R.id.btn_shutter: //拍照 177 | takePhoto(); 178 | break; 179 | case R.id.btn_album: //相册 180 | Intent intent = new Intent(); 181 | intent.setType("image/*"); 182 | intent.setAction(Intent.ACTION_GET_CONTENT); 183 | startActivityForResult(intent, 1); 184 | break; 185 | } 186 | } 187 | }; 188 | 189 | /** 190 | * 获取图片回调 191 | */ 192 | @Override 193 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 194 | if (resultCode == RESULT_OK) { 195 | Uri uri = data.getData(); 196 | Log.e("uri", uri.toString()); 197 | launchActivity(uri); 198 | } 199 | super.onActivityResult(requestCode, resultCode, data); 200 | } 201 | 202 | private void launchActivity(Uri uri) { 203 | String path = UriUtils.getFileFromUri(this, uri); 204 | if (path == null) { 205 | Toast.makeText(this, "文件已损坏", Toast.LENGTH_SHORT).show(); 206 | return; 207 | } 208 | Intent intent = new Intent(this, CutOutPhotoActivity.class); 209 | intent.putExtra("path", path); 210 | startActivity(intent); 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/camear/ReferenceLine.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr.camear; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | import com.wt.ocr.utils.Utils; 11 | 12 | /** 13 | * 网格参考线 14 | * Created by Administrator on 2016/12/8. 15 | */ 16 | 17 | public class ReferenceLine extends View { 18 | private Paint mLinePaint; 19 | 20 | public ReferenceLine(Context context) { 21 | super(context); 22 | init(); 23 | } 24 | 25 | public ReferenceLine(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | init(); 28 | } 29 | 30 | public ReferenceLine(Context context, AttributeSet attrs, int defStyleAttr) { 31 | super(context, attrs, defStyleAttr); 32 | init(); 33 | } 34 | 35 | private void init() { 36 | mLinePaint = new Paint(); 37 | mLinePaint.setAntiAlias(true); 38 | mLinePaint.setColor(Color.parseColor("#ffffffff")); 39 | mLinePaint.setStrokeWidth(1); 40 | } 41 | 42 | 43 | @Override 44 | protected void onDraw(Canvas canvas) { 45 | int screenWidth = Utils.getScreenWH(getContext()).widthPixels; 46 | int screenHeight = Utils.getScreenWH(getContext()).heightPixels; 47 | 48 | int width = screenWidth / 3; 49 | int height = screenHeight / 3; 50 | 51 | for (int i = width, j = 0; i < screenWidth && j < 2; i += width, j++) { 52 | canvas.drawLine(i, 0, i, screenHeight, mLinePaint); 53 | } 54 | for (int j = height, i = 0; j < screenHeight && i < 2; j += height, i++) { 55 | canvas.drawLine(0, j, screenWidth, j, mLinePaint); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/utils/UriUtils.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr.utils; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.ContentUris; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.provider.DocumentsContract; 9 | import android.provider.MediaStore; 10 | 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.OutputStream; 16 | 17 | public class UriUtils { 18 | /** 19 | * 获取真实路径 20 | *

21 | * 支持以下 22 | *

23 | * file:// 24 | * content://media/external/file/109009 25 | * FileProvider适配 26 | * content://com.tencent.mobileqq.fileprovider/external_files/storage/emulated/0/Tencent/QQfile_recv/ 27 | * content://com.tencent.mm.external.fileprovider/external/tencent/MicroMsg/Download/ 28 | * content://com.android.providers.downloads.documents" 29 | * content://com.android.externalstorage.documents 30 | * content://com.android.providers.media.documents 31 | * content://com.google.android.apps.photos.content 32 | */ 33 | public static String getFileFromUri(Context context, Uri uri) { 34 | if (uri == null) { 35 | return null; 36 | } 37 | switch (uri.getScheme()) { 38 | case ContentResolver.SCHEME_CONTENT: 39 | if (isGooglePhotosUri(uri)) { 40 | return uri.getLastPathSegment(); 41 | } else if (isMediaDocument(uri)) { 42 | // MediaProvider 43 | final String docId = DocumentsContract.getDocumentId(uri); 44 | final String[] split = docId.split(":"); 45 | final String type = split[0]; 46 | Uri contentUri = null; 47 | if ("image".equals(type)) { 48 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 49 | } else if ("video".equals(type)) { 50 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 51 | } else if ("audio".equals(type)) { 52 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 53 | } 54 | final String selection = "_id=?"; 55 | final String[] selectionArgs = new String[]{split[1]}; 56 | 57 | return getFilePathFromContentUri(context, contentUri, selection, selectionArgs); 58 | } else if (isDownloadsDocument(uri)) { 59 | // DownloadsProvider 60 | final String id = DocumentsContract.getDocumentId(uri); 61 | final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 62 | return getFilePathFromContentUri(context, contentUri, null, null); 63 | } 64 | 65 | return getFilePathFromContentUri(context, uri, null, null); 66 | case ContentResolver.SCHEME_FILE: 67 | default: 68 | //file:// 69 | return new File(uri.getPath()).getAbsolutePath(); 70 | } 71 | } 72 | 73 | /** 74 | * 从uri获取path 或 拷贝 75 | */ 76 | private static String getFilePathFromContentUri(Context context, Uri uri, String selection, String[] selectionArgs) { 77 | if (null == uri) return null; 78 | String data = null; 79 | 80 | String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME}; 81 | Cursor cursor = context.getContentResolver().query(uri, filePathColumn, selection, selectionArgs, null); 82 | if (null != cursor) { 83 | if (cursor.moveToFirst()) { 84 | int index = cursor.getColumnIndex(MediaStore.MediaColumns.DATA); 85 | if (index > -1) { 86 | data = cursor.getString(index); 87 | if (data == null || !fileIsExists(data)) { 88 | //可能拿不到真实路径 或 文件不存在 走拷贝流程 89 | int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME); 90 | String fileName = cursor.getString(nameIndex); 91 | data = getPathFromInputStreamUri(context, uri, fileName); 92 | } 93 | } else { 94 | //拷贝一份 95 | int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME); 96 | String fileName = cursor.getString(nameIndex); 97 | data = getPathFromInputStreamUri(context, uri, fileName); 98 | } 99 | } 100 | cursor.close(); 101 | } 102 | return data; 103 | } 104 | 105 | /** 106 | * 用流拷贝文件一份到自己APP私有目录下 107 | * 108 | * @param context 109 | * @param uri 110 | * @param fileName 111 | */ 112 | private static String getPathFromInputStreamUri(Context context, Uri uri, String fileName) { 113 | InputStream inputStream = null; 114 | String filePath = null; 115 | 116 | if (uri.getAuthority() != null) { 117 | try { 118 | inputStream = context.getContentResolver().openInputStream(uri); 119 | File file = createTemporalFileFrom(context, inputStream, fileName); 120 | filePath = file.getPath(); 121 | 122 | } catch (Exception e) { 123 | } finally { 124 | try { 125 | if (inputStream != null) { 126 | inputStream.close(); 127 | } 128 | } catch (Exception e) { 129 | } 130 | } 131 | } 132 | 133 | return filePath; 134 | } 135 | 136 | private static File createTemporalFileFrom(Context context, InputStream inputStream, String fileName) 137 | throws IOException { 138 | File targetFile = null; 139 | 140 | if (inputStream != null) { 141 | int read; 142 | byte[] buffer = new byte[8 * 1024]; 143 | //自己定义拷贝文件路径 144 | targetFile = new File(context.getExternalCacheDir(), fileName); 145 | if (targetFile.exists()) { 146 | targetFile.delete(); 147 | } 148 | OutputStream outputStream = new FileOutputStream(targetFile); 149 | 150 | while ((read = inputStream.read(buffer)) != -1) { 151 | outputStream.write(buffer, 0, read); 152 | } 153 | outputStream.flush(); 154 | 155 | try { 156 | outputStream.close(); 157 | } catch (IOException e) { 158 | e.printStackTrace(); 159 | } 160 | } 161 | 162 | return targetFile; 163 | } 164 | 165 | private static boolean isDownloadsDocument(Uri uri) { 166 | return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 167 | } 168 | 169 | private static boolean isMediaDocument(Uri uri) { 170 | return "com.android.providers.media.documents".equals(uri.getAuthority()); 171 | } 172 | 173 | public static boolean isGooglePhotosUri(Uri uri) { 174 | return "com.google.android.apps.photos.content".equals(uri.getAuthority()); 175 | } 176 | 177 | //判断文件是否存在 178 | private static boolean fileIsExists(String filePath) { 179 | try { 180 | File f = new File(filePath); 181 | if (!f.exists()) { 182 | return false; 183 | } 184 | } catch (Exception e) { 185 | return false; 186 | } 187 | return true; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /app/src/main/java/com/wt/ocr/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.wt.ocr.utils; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.ContentUris; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.database.Cursor; 8 | import android.graphics.Bitmap; 9 | import android.graphics.Matrix; 10 | import android.graphics.Rect; 11 | import android.net.Uri; 12 | import android.os.Build; 13 | import android.os.Environment; 14 | import android.provider.DocumentsContract; 15 | import android.provider.MediaStore; 16 | import android.util.DisplayMetrics; 17 | 18 | import java.io.File; 19 | 20 | /** 21 | * Created by Administrator on 2016/12/8. 22 | */ 23 | 24 | public class Utils { 25 | public static DisplayMetrics getScreenWH(Context context) { 26 | DisplayMetrics dMetrics = new DisplayMetrics(); 27 | dMetrics = context.getResources().getDisplayMetrics(); 28 | return dMetrics; 29 | } 30 | 31 | public static final int getWidthInPx(Context context) { 32 | final int width = context.getResources().getDisplayMetrics().widthPixels; 33 | return width; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/answer_btn_answered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/answer_btn_answered.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_close_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_close_click.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_close_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_close_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_ok_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_ok_click.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_ok_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_ok_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_takephoto_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_takephoto_click.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_takephoto_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/ic_takephoto_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-hdpi/icon_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/to_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-xhdpi/to_camera.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/to_camera_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangtaoT/AndroidOCR/a3290b0d487287b11306580c2ce5c126e5f76070/app/src/main/res/drawable-xhdpi/to_camera_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_ok_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_takephoto_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_cutout_phote.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 15 | 16 | 20 | 21 | 26 | 27 | 36 | 37 | 38 | 42 | 43 | 49 | 50 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_show_croppered.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 14 | 15 | 20 | 21 | 28 | 29 | 34 | 35 | 42 | 43 | 49 | 50 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_take_phote.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | 26 | 27 | 36 | 37 | 42 | 43 | 51 | 52 | 60 | 61 |