当前位置: 首页 > 知识库问答 >
问题:

unsatisfiedLinkError opencv TESS-两个库?

胡鸿志
2023-03-14

我已经下载了这个项目:https://github.com/jhansireddy/androidscannerdemo它使用OpenCV并且工作非常好,它所做的是扫描一张用手机摄像头(或者从图库中)拍摄的照片并扫描它。我的目的是OCR,所以我把tess-two作为一个模块,添加了依赖项并构建了项目,在这一点上我没有得到一个错误。但当我运行它时,logcat显示如下:

12-09 15:08:55.443 10040-10040/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   Process: com.scanner.demo, PID: 10040
                                                   java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.scanner.demo-1/base.apk"],nativeLibraryDirectories=[/data/app/com.scanner.demo-1/lib/arm64, /data/app/com.scanner.demo-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libopencv_java3.so"
                                                       at java.lang.Runtime.loadLibrary(Runtime.java:367)
                                                       at java.lang.System.loadLibrary(System.java:1076)
                                                       at com.scanlibrary.ScanActivity.<clinit>(ScanActivity.java:73)
                                                       at java.lang.Class.newInstance(Native Method)
                                                       at android.app.Instrumentation.newActivity(Instrumentation.java:1072)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2467)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2654)
                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)
                                                       at android.os.Handler.dispatchMessage(Handler.java:111)
                                                       at android.os.Looper.loop(Looper.java:207)
                                                       at android.app.ActivityThread.main(ActivityThread.java:5728)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

在搜索的过程中,我发现这个问题与OpenCV中的库和tess-two中的库之间的冲突有关,但是当我试图按照网站的建议将缺少的*.so从OpenCV中的库复制到tess-two中的库时,没有起到作用,我还尝试在应用程序的build.gradle中添加了exclude'libs/*.so'行,但是也没有起到作用。这是我的主要活动:

package com.scanner.demo;

import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.googlecode.tesseract.android.TessBaseAPI;
import com.scanlibrary.ScanActivity;
import com.scanlibrary.ScanConstants;

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


public class MainActivity extends ActionBarActivity {
    public static final String PACKAGE_NAME = "com.scanner.demo";
    public static final String DATA_PATH = Environment
            .getExternalStorageDirectory().toString() + "/new_ocr_project/";

    // You should have the trained data file in assets folder
    // You can get them at:
    // http://code.google.com/p/tesseract-ocr/downloads/list
    public static final String lang = "eng";

    private static final String TAG = "MainActivity.java";


    private static final int REQUEST_CODE = 99;
    private Button scanButton;
    private Button cameraButton;
    private Button mediaButton;
    private ImageView scannedImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String[] paths = new String[] { DATA_PATH, DATA_PATH + "tessdata/" };

        for (String path : paths) {
            File dir = new File(path);
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    Log.v(TAG, "ERROR: Creation of directory " + path + " on sdcard failed");
                    return;
                } else {
                    Log.v(TAG, "Created directory " + path + " on sdcard");
                }
            }

        }

        // lang.traineddata file with the app (in assets folder)
        // You can get them at:
        // http://code.google.com/p/tesseract-ocr/downloads/list
        // This area needs work and optimization
        if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists()) {
            try {

                AssetManager assetManager = getAssets();
                InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
                //GZIPInputStream gin = new GZIPInputStream(in);
                OutputStream out = new FileOutputStream(DATA_PATH
                        + "tessdata/" + lang + ".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(TAG, "Copied " + lang + " traineddata");
            } catch (IOException e) {
                Log.e(TAG, "Was unable to copy " + lang + " traineddata " + e.toString());
            }
        }

        init();
    }

    private void init() {
        scanButton = (Button) findViewById(R.id.scanButton);
        scanButton.setOnClickListener(new ScanButtonClickListener());
        cameraButton = (Button) findViewById(R.id.cameraButton);
        cameraButton.setOnClickListener(new ScanButtonClickListener(ScanConstants.OPEN_CAMERA));
        mediaButton = (Button) findViewById(R.id.mediaButton);
        mediaButton.setOnClickListener(new ScanButtonClickListener(ScanConstants.OPEN_MEDIA));
        scannedImageView = (ImageView) findViewById(R.id.scannedImage);
    }

    private class ScanButtonClickListener implements View.OnClickListener {

        private int preference;

        public ScanButtonClickListener(int preference) {
            this.preference = preference;
        }

        public ScanButtonClickListener() {
        }

        @Override
        public void onClick(View v) {
            startScan(preference);
        }
    }

    protected void startScan(int preference) {
        Intent intent = new Intent(this, ScanActivity.class);
        intent.putExtra(ScanConstants.OPEN_INTENT_PREFERENCE, preference);
        startActivityForResult(intent, REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            Uri uri = data.getExtras().getParcelable(ScanConstants.SCANNED_RESULT);
            Bitmap bitmap = null;
            try {
                bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                getContentResolver().delete(uri, null, null);
                scannedImageView.setImageBitmap(bitmap);




                Log.v(TAG, "Before baseApi");

                TessBaseAPI baseApi = new TessBaseAPI();
                baseApi.setDebug(true);
                baseApi.init(DATA_PATH, lang);
                baseApi.setImage(bitmap);

                String recognizedText = baseApi.getUTF8Text();

                baseApi.end();

                // You now have the text in recognizedText var, you can do anything with it.
                // We will display a stripped out trimmed alpha-numeric version of it (if lang is eng)
                // so that garbage doesn't make it to the display.

                Log.v(TAG, "OCRED TEXT: " + recognizedText);



            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private Bitmap convertByteArrayToBitmap(byte[] data) {
        return BitmapFactory.decodeByteArray(data, 0, data.length);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

请注意,文件夹new_ocr_project/tessdata是正确创建的,英文traineddata文件是以正确的路径复制的。

编辑1:我试着在应用程序的build.gradle中使用“abifilters”

defaultConfig{
    ndk{
        abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
    }
}

我不再犯那个错误了,但我有了一个新的错误:

E/Tesseract(native): Could not initialize Tesseract API with language=eng!
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x8 in tid 12306 (om.scanner.demo)
            // Convert to ARGB_8888, required by tess
            bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

共有1个答案

韩安顺
2023-03-14

在项目应用程序级分级文件中使用此行,而不是在模块级build.Gradle文件中使用此行

ndk{
    abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
}
 类似资料:
  • 我正在开发一个基于SAAS的站点,我必须将两个DBs中的两个表连接起来,比如说DB1中的table1和DB2中的table2。我必须使用cakephp中的join从表1和表2获取匹配记录,但它会抛出如下错误: 错误:SQLSTATE[42000]:语法错误或访问冲突:1142 SELECT命令拒绝用户'dbname'@'localhost'访问表'table_name'。 有谁能解释一下如何使用c

  • I want to tell you two stories from my career which I think are classic illustrations of the difference between tech companies that are well-managed and tech companies that are disasters. It comes dow

  • 我查看了博客帖子、教程、人们的知识库,但没有任何帮助。以下是我所拥有的: 有两个带有MySQL数据库的Docker容器:和。两个容器都已启动,数据库可见,我可以查询表。 我想在我的项目中有两个数据源:一个用于电子书,另一个用于Spring Security表。 我编写了一个简单的,其中我只是自动连接两个存储库并检查它们的大小。 运行应用程序时,我得到: 但是,如果我在没有第二个数据源并使用常规Sp

  • 我有两个枚举,它们实现了如下相同的接口:- 名为SystemA和SystemB的两个枚举正在实现此接口。 我想要像这样应用getConfigFunction:- 但它会抛出编译时错误,因为形成的流的类型为:Config[]。所以我尝试了以下修改:- 但这也失败了,因为我还需要修改forEach部分。有人能帮忙吗?我该如何修改forEach部分,或者我该如何使用map()/flatmap()函数,这

  • 我写了一个启动两个线程的代码片段;一个线程打印所有奇数,而另一个线程打印所有偶数。我使用了内在锁和线程通信命令的组合来实现两个线程的正确交叉。这是我的代码, 以下是我的问题: > 奇数线程在printOdd()函数中执行,而偶数线程在print偶数()函数中执行。我对两个线程都使用一个内在锁;我不明白两个线程怎么能同时存在于各自的同步块中,因为使用了相同的锁。 我从代码中删除了线程通信语句(通知,

  • 在我的页面中,我有两个AMP表单,一个提交按钮放在第一个表单中,另一个div提交成功按钮放在第二个表单中。我如何在第二个表格中显示第一个表格提交的状态?