2016-06-30 2 views
3

현재 활동 탭 (Android의 단편)을 전환 할 수있는 첫 번째 앱을 개발 중입니다. 탭 중 하나에 4 개의 탭이 있으며 문자 인식 (OCR)을위한 이미지 인식을 구현했습니다. 나는 Priyank Verma에 의해 만들어진 Easy OCR Library이라고 불리는 단순화 된 OCR Tesseract 라이브러리를 사용했다. 나는 그 라이브러리의 예제를 테스트했으며 작동한다. 하지만 내 자신의 응용 프로그램에 대한 라이브러리를 사용할 때 제대로 작동하지 않습니다.OCR 검색에 스캔 된 출력이 표시되지 않습니다.

내 앱의 탭 중 하나에서 내 전화 카메라를 사용하여 사진을 찍는 '스캔'버튼이 있습니다. 사진을 찍은 후 내 응용 프로그램은 문자 인식을 위해 저장된 디렉토리에서 캡처 한 이미지를 스캔해야합니다. 그런 다음 내 앱은 이전의 '스캔'탭으로 돌아가서 해당 탭의 '스캔'버튼 위에 문자 인식 결과를 표시합니다. 그리고 그게, 내 애플 리케이션을 스캔하지 않는 것 같습니다. 진짜 문제는 그림을 찍은 후 &을 저장하면 내 앱이 출력이없는 탭으로 돌아갑니다. 내 코드는 작동해야하지만 슬프게도 그렇지 않습니다. 오류도없고, 아무 것도 아니며, 나는 틀린 것을 알아내는 데 며칠 동안 마음을 잃어 가고 있습니다. ----------

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.kaydarinapp.queueappv2"> 
    <!-- Save file permission --> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    <!-- Read file permission --> 
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    <!-- Camera permission --> 
    <uses-feature android:name="android.hardware.camera" /> 
    <uses-permission android:name="android.permission.CAMERA" /> 
    <!-- Internet permission --> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 
     <activity android:name=".MainActivity" 
      android:screenOrientation="portrait" 
      android:configChanges="keyboardHidden|orientation|screenSize"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

---------- 내 앱의 매니페스트

---- - :

여기에 코드입니다 ------ 내 앱의 탭 ----------

내 탭의 XML에서

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".Tab2" 
    android:gravity="center_horizontal" 
    > 

    <TextView android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/textView" 
     android:layout_marginTop="45dp" 
     android:layout_gravity="center_horizontal" 
     android:textSize="8pt" 
     /> 


    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/button" 
     android:layout_marginTop="20dp" 
     android:text="Scan" 
     android:layout_gravity="center_vertical" /> 

</LinearLayout> 
012 3,516,

내 탭 자바 쉬운 OCR 라이브러리에서

package com.kaydarinapp.queueappv2; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.graphics.Bitmap; 
import android.hardware.Camera; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.FrameLayout; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

import com.wordpress.priyankvex.easyocrscannerdemo.Config; 
import com.wordpress.priyankvex.easyocrscannerdemo.EasyOcrScanner; 
import com.wordpress.priyankvex.easyocrscannerdemo.EasyOcrScannerListener; 

/** 
* Created by Kaydarin on 6/1/2016. 
*/ 

//Our class extending fragment 
public class Tab2 extends Fragment implements EasyOcrScannerListener { 

    private LinearLayout linearLayout; 
    private FragmentActivity fragActivity; 
    EasyOcrScanner mEasyOcrScanner; 
    TextView textView; 
    ProgressDialog mProgressDialog; 
    Button btnCapture; 

    //Overriden method onCreateView 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     fragActivity = super.getActivity(); 
     linearLayout = (LinearLayout) inflater.inflate(R.layout.tab2, container, false); 

     textView = (TextView) fragActivity.findViewById(R.id.textView); 

     // initialize EasyOcrScanner instance. 
     mEasyOcrScanner = new EasyOcrScanner(getActivity(), "EasyOcrScanner", 
       Config.REQUEST_CODE_CAPTURE_IMAGE, "eng"); 

     // Set ocrScannerListener 
     mEasyOcrScanner.setOcrScannerListener(this); 

     btnCapture = (Button) linearLayout.findViewById(R.id.button); 
     btnCapture.setOnClickListener(new View.OnClickListener(){ 
      @Override 
      public void onClick(View v) { 
       mEasyOcrScanner.takePicture(); 
      } 
     }); 

     return linearLayout; 
    } 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     // Call onImageTaken() in onActivityResult. 
     if (resultCode == getActivity().RESULT_OK && requestCode == Config.REQUEST_CODE_CAPTURE_IMAGE){ 
      mEasyOcrScanner.onImageTaken(); 
     } 
    } 

    /** 
    * Callback when after taking picture, scanning process starts. 
    * Good place to show a progress dialog. 
    * @param filePath file path of the image file being processed. 
    */ 
    @Override 
    public void onOcrScanStarted(String filePath) { 
     mProgressDialog = new ProgressDialog(getActivity()); 
     mProgressDialog.setMessage("Scanning..."); 
     mProgressDialog.show(); 
    } 

    /** 
    * Callback when scanning is finished. 
    * Good place to hide teh progress dialog. 
    * @param bitmap Bitmap of image that was scanned. 
    * @param recognizedText Scanned text. 
    */ 
    @Override 
    public void onOcrScanFinished(Bitmap bitmap, String recognizedText) { 
     textView.setText(recognizedText); 
     if (mProgressDialog.isShowing()){ 
      mProgressDialog.dismiss(); 
     } 
    } 
} 

---------- ----------

쉬운 OCR 도서관의 매니페스트

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.wordpress.priyankvex.easyocrscanner"> 

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.CAMERA"/> 

</manifest> 

구성 자바

package com.wordpress.priyankvex.easyocrscannerdemo; 

/** 
* Created by Priyank(@priyankvex) on 27/8/15. 
*/ 
public class Config { 

    public static String TAG = "OcrScanner"; 
    public static int REQUEST_CODE_CAPTURE_IMAGE = 1995; 

} 

EasyOCRScannerListener 자바

package com.wordpress.priyankvex.easyocrscannerdemo; 

import android.graphics.Bitmap; 

/** 
* Created by Priyank(@priyankvex) on 27/8/15. 
* 
* Interface for the callbacks for {@link EasyOcrScanner}. 
*/ 
public interface EasyOcrScannerListener { 

    public void onOcrScanStarted(String filePath); 

    public void onOcrScanFinished(Bitmap bitmap, String recognizedText); 
} 

EasyOCRScanner 자바

package com.wordpress.priyankvex.easyocrscannerdemo; 

import android.app.Activity; 
import android.content.Intent; 
import android.net.Uri; 
import android.util.Log; 

import java.io.File; 
import java.util.Calendar; 

/** 
* Created by Priyank(@priyankvex) on 27/8/15. 
* 
* Class to handle scanning of image. 
*/ 
public class EasyOcrScanner { 

    protected Activity mActivity; 
    private String directoryPathOriginal; 
    private String filePathOriginal; 
    private int requestCode; 
    private EasyOcrScannerListener mOcrScannerListener; 
    private String trainedDataCode; 

    public EasyOcrScanner(Activity activity, String directoryPath, int requestCode, String trainedDataCode){ 
     this.mActivity = activity; 
     this.directoryPathOriginal = directoryPath; 
     this.requestCode = requestCode; 
     this.trainedDataCode = trainedDataCode; 
    } 

    public void takePicture(){ 
     Intent e = new Intent("android.media.action.IMAGE_CAPTURE"); 
     this.filePathOriginal = FileUtils.getDirectory(this.directoryPathOriginal) + File.separator + Calendar.getInstance().getTimeInMillis() + ".jpg"; 
     e.putExtra("output", Uri.fromFile(new File(this.filePathOriginal))); 

     startActivity(e); 
    } 

    public void onImageTaken(){ 
     Log.d(Config.TAG, "onImageTaken with path " + this.filePathOriginal); 
     ImageProcessingThread thread = new ImageProcessingThread(this.mOcrScannerListener, 
       this.filePathOriginal, this.directoryPathOriginal, this.mActivity, this.trainedDataCode); 
     thread.execute(); 
    } 

    private void startActivity(Intent intent){ 
     if(this.mActivity != null) { 
      this.mActivity.startActivityForResult(intent, this.requestCode); 
     } 
    } 

    public void setOcrScannerListener(EasyOcrScannerListener mOcrScannerListener) { 
     this.mOcrScannerListener = mOcrScannerListener; 
    } 


} 

Fileutils의 자바

package com.wordpress.priyankvex.easyocrscannerdemo; 

import android.os.Environment; 
import android.util.Log; 

import java.io.File; 

/** 
* Created by Priyank(@priyankvex) on 27/8/15. 
*/ 
public class FileUtils { 

    public static String getDirectory(String folderName) { 
     File directory = null; 
     directory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + folderName); 
     if(!directory.exists()) { 
      directory.mkdirs(); 
     } 

     return directory.getAbsolutePath(); 
    } 

    public static String getTessdataDirectory(String directoryPath){ 
     File tessdataDirectory = new File(directoryPath + "/tessdata"); 
     if (tessdataDirectory.mkdirs()){ 
      Log.d(Config.TAG, "tessdata directory created"); 
     } 
     return tessdataDirectory.getAbsolutePath(); 
    } 
} 

ImageProcessingThread 자바

package com.wordpress.priyankvex.easyocrscannerdemo; 

import android.app.Activity; 
import android.content.res.AssetManager; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Matrix; 
import android.media.ExifInterface; 
import android.os.AsyncTask; 
import android.util.Log; 

import com.googlecode.tesseract.android.TessBaseAPI; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

/** 
* Created by Priyank(@priyankvex) on 27/8/15. 
* 
* Async Task to process the image and scan the image using tesseract library. 
* Equipped with proper callbacks. 
*/ 
public class ImageProcessingThread extends AsyncTask<Void, Void, Void> { 

    private EasyOcrScannerListener mOcrScannerListener; 
    private String filePath; 
    private Bitmap mBitmap; 
    private String scannedText; 
    // trained data file used by Tesseract will be copied in directoryPath/tessdata 
    private String directoryPath; 
    private String absoluteDirectoryPath; 
    private Activity mActivity; 
    String trainedDataCode; 

    public ImageProcessingThread(EasyOcrScannerListener ocrScannerListener, String filePath, 
           String directoryPath, Activity activity, String trainedDataCode) { 
     this.mOcrScannerListener = ocrScannerListener; 
     this.filePath = filePath; 
     this.directoryPath = directoryPath; 
     this.absoluteDirectoryPath = FileUtils.getDirectory(this.directoryPath); 
     this.mActivity = activity; 
     this.trainedDataCode = trainedDataCode; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     mOcrScannerListener.onOcrScanStarted(this.filePath); 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     processImage(); 
     makeTessdataReady(); 
     scannedText = scanImage(); 
     Log.d(Config.TAG, "Scanned test : " + scannedText); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void aVoid) { 
     super.onPostExecute(aVoid); 
     mOcrScannerListener.onOcrScanFinished(mBitmap, scannedText); 
    } 

    private void processImage() { 
     int imageOrientationCode = getImageOrientation(); 
     Bitmap rawBitmap = getBitmapFromPath(); 
     // Getting the bitmap in right orientation. 
     this.mBitmap = rotateBitmap(rawBitmap, imageOrientationCode); 
    } 

    private Bitmap getBitmapFromPath() { 
     BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
     bmOptions.inSampleSize = 4; 
     Bitmap bitmap = BitmapFactory.decodeFile(this.filePath, bmOptions); 
     return bitmap; 
    } 

    private int getImageOrientation() { 
     ExifInterface exif = null; 
     try { 
      exif = new ExifInterface(this.filePath); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     assert exif != null; 
     int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 
       ExifInterface.ORIENTATION_UNDEFINED); 
     return orientation; 
    } 

    private Bitmap rotateBitmap(Bitmap bitmap, int orientation){ 

     Matrix matrix = new Matrix(); 
     switch (orientation) { 
      case ExifInterface.ORIENTATION_NORMAL: 
       return bitmap; 
      case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: 
       matrix.setScale(-1, 1); 
       break; 
      case ExifInterface.ORIENTATION_ROTATE_180: 
       matrix.setRotate(180); 
       break; 
      case ExifInterface.ORIENTATION_FLIP_VERTICAL: 
       matrix.setRotate(180); 
       matrix.postScale(-1, 1); 
       break; 
      case ExifInterface.ORIENTATION_TRANSPOSE: 
       matrix.setRotate(90); 
       matrix.postScale(-1, 1); 
       break; 
      case ExifInterface.ORIENTATION_ROTATE_90: 
       matrix.setRotate(90); 
       break; 
      case ExifInterface.ORIENTATION_TRANSVERSE: 
       matrix.setRotate(-90); 
       matrix.postScale(-1, 1); 
       break; 
      case ExifInterface.ORIENTATION_ROTATE_270: 
       matrix.setRotate(-90); 
       break; 
      default: 
       return bitmap; 
     } 
     try { 
      Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
      bitmap.recycle(); 
      return bmRotated; 
     } 
     catch (OutOfMemoryError e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    private String scanImage(){ 
     TessBaseAPI baseApi = new TessBaseAPI(); 
     Log.d(Config.TAG, "Data path : " + FileUtils.getDirectory(this.directoryPath)); 
     baseApi.init(FileUtils.getDirectory(this.directoryPath) + "/", this.trainedDataCode); 
     baseApi.setImage(this.mBitmap); 
     String recognizedText = baseApi.getUTF8Text(); 
     baseApi.end(); 

     return recognizedText; 
    } 

    private void makeTessdataReady(){ 

     // created test data directory if necessary under absoluteDirectoryPath and returns its absolute path. 
     String tessdirectoryPath = FileUtils.getTessdataDirectory(this.absoluteDirectoryPath); 

     if (!(new File(tessdirectoryPath+ "/" + this.trainedDataCode + ".traineddata")).exists()) { 
      try { 

       AssetManager assetManager = mActivity.getAssets(); 
       InputStream in = assetManager.open("tessdata/" + this.trainedDataCode + ".traineddata"); 
       //GZIPInputStream gin = new GZIPInputStream(in); 
       // Output stream with the location where we have to write the eng.traineddata file. 
       OutputStream out = new FileOutputStream(tessdirectoryPath + "/" + this.trainedDataCode 
         + ".traineddata"); 

       // Transfer bytes from in to out 
       byte[] buf = new byte[1024]; 
       int len; 
       //while ((lenf = gin.read(buff)) > 0) { 
       while ((len = in.read(buf)) > 0) { 
        out.write(buf, 0, len); 
       } 
       in.close(); 
       //gin.close(); 
       out.close(); 

       Log.v(Config.TAG, "Copied " + " traineddata"); 
      } catch (IOException e) { 
       Log.e(Config.TAG, "Was unable to copy " + " traineddata " + e.toString()); 
      } 
     } 
     else{ 
      Log.d(Config.TAG, "tessdata already present"); 
     } 
    } 

} 

나는 너희들이 나를 도울 수 있기를 바랍니다. 이 코드가 잘못된 점을 파악하는 데 며칠이 걸렸습니다 .......

+0

당신이 성공적으로 안드로이드 스튜디오에서 정팔 포체 lib 디렉토리를 실행 한 않았다 https://developer.android.com/training/permissions/requesting.html 여기

내가 외부 저장 장치에 승 카메라와 R/권한을 얻기 위해 사용하는 코드는? –

+0

@SagarNayak tesseract lib를 실행하면 무엇을 의미합니까? 나는 거기에 내 애플 리케이션을 실행할 수 있으며'프로젝트를 컴파일 (': tess-two')'&'프로젝트 컴파일 (': easy_ocr_library')'프로젝트의 gradle에 포함 시켰습니다. 게다가, 거기 예제 애플 리케이션 및 웹 리소스에서 모든 지침을 따르십시오. – Kaydarin

+0

예. 나는 같은 것을 요구하고있다. 그래서 tess-two를 만들기 위해 ndk를 사용 했습니까? –

답변

0

카메라 작동이 RESULT_OK는 반환하지 않지만 RESULT_CANCELED는 반환하지 않으므로 tesseract는 호출되지 않습니다. 이것을 확인할 수 있습니다. 지. "onActivityResult를"방법의 시작 "Tab2.java"에 추가하여 :

Log.d("PictureEdit", "onActivityResult w/ resultCode=" + resultCode + " (is ok: " + (resultCode == RESULT_OK) + " is canceled: " + (resultCode == RESULT_CANCELED) + ")" + " requestCode=" + requestCode); 

왜 그렇게입니까? Android 6 (Marshmallow)부터 시작하기 때문에 매니페스트에 필요한 권한 만 선언해도 충분하지 않습니다. 또한 권한은 사용자가 런타임에 가져와야합니다.

는 여기를 참조하십시오 :

private void checkPermissions(){ 
    if (Build.VERSION.SDK_INT >= 23) { 
     boolean needWriteExtStorage = checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) 
       != PackageManager.PERMISSION_GRANTED; 
     boolean needCamera = checkSelfPermission(android.Manifest.permission.CAMERA) 
       != PackageManager.PERMISSION_GRANTED; 
     if (needWriteExtStorage || needCamera){ 
      String[] permissions = new String[((needWriteExtStorage)?(1):(0)) + ((needCamera)?(1):(0))]; 
      int idx = 0; 
      if (needWriteExtStorage){ 
       permissions[idx] = android.Manifest.permission.WRITE_EXTERNAL_STORAGE; 
       idx++; 
      } 
      if (needCamera){ 
       permissions[idx] = android.Manifest.permission.CAMERA; 
       idx++; 
      } 
      ActivityCompat.requestPermissions(
        this, permissions, 1); 
     } 
    } else { 
     //permission is automatically granted on sdk<23 upon installation 
     //Log.e("testing", "Permission is already granted"); 
    } 
} 
관련 문제