简体   繁体   English

如何在Android Studio中使用OpenCV从手机加载图像?

[英]How to load image from my phone using OpenCV with Android Studio?

I am developing an android app using opencv in android studio,I follow the instruction in the book 'OpenCV Android Programming By Example' to code for loading an image from my phone.But I can't show it on ImageView though the code is exactly the same as the book,the main code is following: 我正在android studio中使用opencv开发一个android应用程序,我按照《 OpenCV Android示例编程》一书中的说明进行了从手机中加载图像的代码。尽管代码完全正确,但我无法在ImageView上显示它与本书相同,主要代码如下:

 @Override
  onCreate(...){...}
..........

 @Override
public  boolean onOptionsItemSelected(MenuItem item)    {
    int id  =   item.getItemId();
    if  (id ==  R.id.read_img)  {
        Intent  intent=new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent,"Select  Picture"),
                SELECT_PICTURE);
        return  true;
    }
    return  super.onOptionsItemSelected(item);
 }
  public void onActivityResult(int requeseCode,int resultCode,Intent data){
    if(resultCode==RESULT_OK){
        if(requeseCode==SELECT_PICTURE){
            Uri selectedImgUri=data.getData();
            selectedImagePath=getPath(selectedImgUri);

         loadImage(selectedImagePath);//the method to get the image
        displayImage(sampledImage);//to display the image on ImageView
        }
    }
}
............
getPath(String path){.....}//it works fine

  public void loadImage(String path){
    Mat originalImage=Imgcodecs.imread(path);
    Mat rgbImage=new    Mat();
    Imgproc.cvtColor(originalImage, rgbImage,   Imgproc.COLOR_BGR2RGB);

//to reshape the image.
    Display display =   getWindowManager().getDefaultDisplay();
    Point   size    =   new Point();
    display.getSize(size);
    int width=size.x;
    int height=size.y;
    sampledImage=new Mat();
    double  downSampleRatio=calculateSubSampleSize(rgbImage,width,height);
    Imgproc.resize(rgbImage,sampledImage,new Size(),downSampleRatio,downSampleRatio,Imgproc.INTER_AREA);

//to rotate the image,seems not a problem in this case.
    try {
        ExifInterface   exif    =   new ExifInterface(selectedImagePath);
        int orientation =   exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
    switch (orientation){
        case    ExifInterface.ORIENTATION_ROTATE_90:
            sampledImage=sampledImage.t();
            Core.flip(sampledImage, sampledImage,   1);
            break;
        case    ExifInterface.ORIENTATION_ROTATE_270:
            sampledImage=sampledImage.t();
            Core.flip(sampledImage, sampledImage,   0);
            break;}
    } catch (IOException e){
        e.printStackTrace();
    }
}


 public void displayImage(Mat image){
    Bitmap bitmap=Bitmap.createBitmap(image.cols(),image.rows(),Bitmap.Config.RGB_565);
    Utils.matToBitmap(image,bitmap);
    ImageView imageView2=(ImageView)findViewById(R.id.imageView2);
    imageView2.setImageBitmap(bitmap);
}
 private    static  double  calculateSubSampleSize(Mat  srcImage,   int reqWidth,   int reqHeight)  {
    //  Raw height  and width   of  image
    final   int height  =   srcImage.height();
    final   int width   =   srcImage.width();
    double  inSampleSize    =   1;

    if(height>reqHeight||   width   >   reqWidth)   {
        //  Calculate   ratios  of  requested   height  and width   to  the raw             height  and width
    final   double  heightRatio =   (double)    reqHeight   /   (double)    height;
    final   double  widthRatio  =   (double)    reqWidth    /   (double)    width;
        //  Choose  the smallest    ratio   as  inSampleSize    value,  this    will                    //guarantee final   image   with    both    dimensions  larger  than    or                  //equal to  the requested   height  and width.
    inSampleSize    =   heightRatio<widthRatio  ?   heightRatio :widthRatio;
}       return  inSampleSize;

} } }}

The app can run,but when i choose the image and click OK on my phone,it crashes,the logcat shows: 该应用程序可以运行,但是当我选择图像并在手机上单击“确定”时,它崩溃了,logcat显示:

org.opencv.imgcodecs.Imgcodecs.imread(Imgcodecs.java:118)
                                                                                      at com.example.administrator.opencvdemo.MainActivity.loadImage(MainActivity.java:142)
                                                                                      at com.example.administrator.opencvdemo.MainActivity.onActivityResult(MainActivity.java:118)
                                                                                      at android.app.Activity.dispatchActivityResult(Activity.java:5652)
                                                                                      at android.app.ActivityThread.deliverResults(ActivityThread.java:3600)

Obviously it's the problem of the loadImage() method,but I search google and every where without finding the good answer,i tried to fix it,but it's the same problem.Can someone know how to solve it?It got me crazy.Thanks a lot! 显然,这是loadImage()方法的问题,但是我在google和所有地方搜索时都没有找到好的答案,我试图修复它,但这是同一个问题。有人知道如何解决它吗?这让我发了疯。很多!

Have you checked for the application permissions on the Manifest ? 您是否已检查清单上的应用程序权限? I had the same issue loading a file from my external storage. 我从外部存储设备加载文件时遇到了同样的问题。

I added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to my AndroidManifest.xml . 我在我的AndroidManifest.xml添加了<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> Since Android 6 you need to request permissions on runtime. 从Android 6开始,您需要在运行时请求权限。

I took care of thoose permissions on my MainActivity like the following 我在MainActivity上选择了以下权限:

package test;

import java.io.File;
import java.util.ArrayList;
import java.util.Map;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

public class MainActivity extends Activity implements OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback {

    private String TAG = "MainActivity";

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                } break;

                default:
                {
                    Log.i(TAG, "OpenCV loaded FAILURE");
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mLoaderCallback);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String[] PERMISSIONS = {
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA
        };

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, 1);
        }
        // Do work
    }
}

Hope it can help. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM