安卓使用百度SDK完成OCR文字識別(二)

前言

上一篇完成了初步實現,當時說了要儘快加上相機拍照功能,於是乎,今天我又來啦。
上一篇的鏈接,已經不記得的小夥伴可以查看出處。

首先我還是對上篇進行一下部分的總結,可能誤導了一部分人,我引入的ocr-ui包沒有使用,確實,大家可以去掉,我本來沒看包裏什麼內容就先引用過來了,後來才發現根本沒用到0_0,其次類很簡單也只有兩個 Mainactivity和SimpleTextActivity,多餘的東西可以去掉。

話不多說看代碼

此次代碼就只貼SimpleTextActivity部分內容了,因爲這次的代碼裏面有很多註釋內容,就是我嘗試了種處理方法,但是沒有必要,所以都註釋了,但是這些代碼在別的地方可能需要,我並沒有刪除,方便自己下次記憶。對於大家來說沒有必要看這些亂七八糟的灰色註釋,於是我節選有用的代碼給大家分享一哈。

  //從相冊選取圖片
        findViewById(R.id.enhanced_photo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (hasPermission()) {
                    Intent intent = new Intent(Intent.ACTION_PICK, null);
                    intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                    startActivityForResult(intent, REQUEST_ENHANCED_CODE_ALBUM);
                }
            }
        });
        //拍照選取圖片
        findViewById(R.id.enhanced_take_photo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               takePhoto();
            }
        });

首先是兩個點擊事件,觸發一切的開始。點擊之後進行權限判斷,沒有權限的話打回!,拍照的權限放在takePhoto裏了。

 /**
     * 執行拍照
     */
    private void takePhoto() {
        if (!hasPermission()) {
            return;
        }

        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        if (new File(path).exists()) {
            try {
                new File(path).createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mTmpPath = path + "/temp.jpg";
        mTmpFile = new File(mTmpPath);
        mTmpFile.getParentFile().mkdirs();
        Uri imageUri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String authority = getPackageName() + ".provider";
            imageUri = FileProvider.getUriForFile(SimpleTextActivity.this, authority, mTmpFile);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            List<ResolveInfo> resInfoList = this.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
            for (ResolveInfo resolveInfo : resInfoList) {
                String packageName = resolveInfo.activityInfo.packageName;
                this.grantUriPermission(packageName, imageUri, FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_READ_URI_PERMISSION);
            }
        } else {
            imageUri = Uri.fromFile(mTmpFile);
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, REQUEST_ENHANCED_CODE_CAMERA);
    }

其中mTmpFile和mTmpPath是成員變量,因爲下面傳遞需要。

順便把權限判斷的請求和回調都展示一下

 	/**
     * 判斷是否有權限
     * @return
     */
    private boolean hasPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, REQUEST_PERIMISSION_CODE);
            return false;
        }else {
            return true;
        }
    }

	@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERIMISSION_CODE) {
            if (grantResults.length > 0) {
                for (int grantResult: grantResults) {
                    if (grantResult == PackageManager.PERMISSION_DENIED) {
                        Toast.makeText(SimpleTextActivity.this, "拒絕權限將不能正常使用!", Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
            }
        }
    }

然後在相機返回照片後的處理上,也是我當初不懂踩坑的地方。

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_ALBUM) {
            // 從相冊返回的數據
            if (data != null) {
                // 得到圖片的全路徑
                Uri uri = data.getData();
                recSimpleText(getRealPathFromURI(uri));
            }
        } else if (requestCode == REQUEST_ENHANCED_CODE_ALBUM) {
            // 從相冊返回的數據
            if (data != null) {
                // 得到圖片的全路徑
                Uri uri = data.getData();
                recEnhancedText(getRealPathFromURI(uri));
            }
        } else if (requestCode == REQUEST_ENHANCED_CODE_CAMERA) {
            //相機返回
            recEnhancedText(mTmpPath);
        }
    }

一開始我和上面一樣判斷data是否爲空然後從裏面取uri,但是一直都是空!後來很納悶爲什麼,但是我到現在也不知道爲什麼data返回就是空,然後看了一下別人的做法,並沒有從data裏面獲取uri!而是直接從上面的mTmpPath那直接獲取路徑,確實不用多此一舉!回頭想想也是,人傻了!

然後把provider的相關也貼一下,需要留意的是現在很多使用androidx,不用v4包了,照着網上的導肯定是要飈紅的。

這段貼在AndroidManifest.xml的<application>

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.kxqin.ocrtest.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

filepaths.xml

<resources>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path
            name="camera_photos"
            path="." />
    </paths>
</resources>

不過我寫完了provider之後,有前輩說並不需要,我也不懂這個不需要是指哪部分代碼不需要還是說provider不需要?反正現在運行良好不報錯就行哈哈哈。

對了 ,還有一個需要注意的是,都加上豎屏鎖定吧,因爲在將識別後的文字展示之後,切換橫屏,文字就消失了。

		//設置豎屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

放在onCreate裏。
關於佈局頁面,着實沒啥看的。

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SimpleTextActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/take_a_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="普通文字識別-拍照"
            android:visibility="gone"/>

        <Button
            android:id="@+id/select_a_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="普通文字識別-相冊"/>

        <Button
            android:id="@+id/enhanced_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="高精度文字識別-相冊"/>

        <Button
            android:id="@+id/enhanced_take_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="高精度文字識別-拍照"/>

        <TextView
            android:id="@+id/info_text_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    
</ScrollView>

心滿意足了不?那我去瞅瞅百度人臉識別了,雖無遠大造輪志向,但是大佬們造好的輪子也得會用吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章