Java 将位图变量传递给扩展类中的方法

Java 将位图变量传递给扩展类中的方法,java,android,oop,methods,bitmap,Java,Android,Oop,Methods,Bitmap,我的代码实现了TFlite,我有两个类: 1) 处理相机活动和图像处理 2) 处理模型和检测器的细节 我在运行模型的扩展类中有一个方法。 我试图从主类中调用该方法。我是Java新手,所以我不太清楚为什么我总是遇到Java.lang.NullPointerException错误 请参阅下面的代码(我将在相关部分周围留下大量空白和注释): 进行调用的方法: // Class was called Classifier classifier; protected void onActivityRes

我的代码实现了TFlite,我有两个类:

1) 处理相机活动和图像处理

2) 处理模型和检测器的细节

我在运行模型的扩展类中有一个方法。 我试图从主类中调用该方法。我是Java新手,所以我不太清楚为什么我总是遇到Java.lang.NullPointerException错误

请参阅下面的代码(我将在相关部分周围留下大量空白和注释):

进行调用的方法:

// Class was called
Classifier classifier;

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // Called when image was captured from camera

        // ...
        // Obtains bitmap image from camera and processes it to a new Bitmap variable: rotatedBitmap
        // ...

/* Here is where the issue begins.
I can obtain the processed image and set it to my ImageView no problem, so the variable rotatedBitmap
is NOT null. But when I try to pass it to classifier.recognizeImage() it throws the null pointer error
and crashes the app
*/ 
        if (resultCode == RESULT_OK) {
            // Set the image captured to our ImageView
            mImageView.setImageBitmap(rotatedBitmap);

            if (rotatedBitmap != null) {
                float[][] result = classifier.recognizeImage(rotatedBitmap); // Says that rotatedBitmap is null

                // Display results
                String message = Arrays.toString(result[0]);
                Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout), message,
                        Snackbar.LENGTH_SHORT);
                mySnackbar.show();
            }
        }
    }
完整代码:

public class CameraActivity extends AppCompatActivity {

    private static final int PERMISSION_CODE = 1000;
    private static final int IMAGE_CAPTURE_CODE = 1001;

    Classifier classifier;

    Button mCaptureBtn;
    ImageView mImageView;

    Uri image_uri;
    public Bitmap rotatedBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageView = findViewById(R.id.image_view);
        mCaptureBtn = findViewById(R.id.capture_image_btn);

        mCaptureBtn.setOnClickListener(new View.OnClickListener() {
            // 1: Create the button
            // 2: Create an instance of OnClickListener to wait for the click
            // 3: Override the onClick method
            @Override
            public void onClick(View v) {
                // If the operating system is newer or equal to Marshmello
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    // Check for permissions
                    if (checkSelfPermission(Manifest.permission.CAMERA) ==
                            PackageManager.PERMISSION_DENIED ||
                            checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
                                    PackageManager.PERMISSION_DENIED) {
                        // Permission not enables so request it
                        String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
                        requestPermissions(permission, PERMISSION_CODE);
                    } else {
                        // Permission already granted
                        openCamera();
                    }
                } else {
                    openCamera();
                }
            }
        });
    }

    private void openCamera() {
        // ContentValues creates a set-type object that can store values that ContentResolver can access
        ContentValues values = new ContentValues();

        // Store values
        values.put(MediaStore.Images.Media.TITLE, "New Picture");
        values.put(MediaStore.Images.Media.DESCRIPTION, "From the camera");

        // Obtain the uri(uniform resource identifier) using the ContentValues previously made
        image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        // Camera intent
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // The EXTRA_OUTPUT constraint outputs the full-sized image data to the uri
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);

        if (cameraIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE);
        }
    }

    // Handling permission request
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        // THis method is called whenever the user presses allow or deny from the Perm Req prompt
        switch (requestCode){
            case PERMISSION_CODE:{
                if (grantResults.length > 0 && grantResults[0] ==
                        PackageManager.PERMISSION_GRANTED) {
                    // permission from popup was granted
                    openCamera();
                }
                else {
                    // permission from popup was denied
                    Toast.makeText(this, "Permission denied...", Toast.LENGTH_SHORT).show();
                }
    }
}
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // Called when image was captured from camera


        // Obtain the image from the uri
        Bitmap bitmap = null;
        int orientation;

        // Make sure we have an image_uri
        try {
            // Convert uri to an InputStream
            InputStream in = getContentResolver().openInputStream(image_uri);
            // Obtain Exif info from the InputStream
            ExifInterface ei = new ExifInterface(in);

            // Get bitmap depending on version
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                try {
                    bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(getContentResolver(), image_uri));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                try {
                    bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), image_uri);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            // Obtain orientation information from image
            orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);

            // Rotate the image (if needed) to portrait mode
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotatedBitmap = rotateImage(bitmap, 90);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotatedBitmap = rotateImage(bitmap, 180);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotatedBitmap = rotateImage(bitmap, 270);
                    break;
                case ExifInterface.ORIENTATION_NORMAL:
                default:
                    rotatedBitmap = bitmap;
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }





/* Here is where the issue begins.
I can obtain the processed image and set it to my ImageView no problem, so the variable rotatedBitmap
is NOT null. But when I try to pass it to classifier.recognizeImage() it throws the null pointer error
and crashes the app
*/ 
        if (resultCode == RESULT_OK) {
            // Set the image captured to our ImageView
            //mImageView.setImageURI(image_uri);
            mImageView.setImageBitmap(rotatedBitmap);

            if (rotatedBitmap != null) {
                float[][] result = classifier.recognizeImage(rotatedBitmap);
                String message = Arrays.toString(result[0]);
                Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout), message,
                        Snackbar.LENGTH_SHORT);
                mySnackbar.show();
            }
        }
    }







    public static Bitmap rotateImage(Bitmap source, float angle) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
                matrix, true);
    }
}


public class Classifier extends CameraActivity {

    private int inputSize = 300;
    private int pixelSize = 3;
    private int imageMean = 0;
    private float imageStd = 255.0f;
    private int maxResult = 3;
    private float threshHold = 0.4f;

    private List<String> labelList;
    private Interpreter interpreter;

    public static final String PREFIX = "stream2file";
    public static final String SUFFIX = ".tmp";


    public File stream2file (InputStream in) throws IOException {
        final File tempFile = File.createTempFile(PREFIX, SUFFIX);
        tempFile.deleteOnExit();
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            IOUtils.copy(in, out);
        }
        return tempFile;
    }



    public void init() {
        Interpreter.Options options = new Interpreter.Options();
        options.setNumThreads(5);
        options.setUseNNAPI(true);

        // Obtain the model from assets folder
        final AssetManager assets = getApplicationContext().getAssets();
        try {
            InputStream in = assets.open("detect.tflite");
            File file = stream2file(in);
            interpreter = new Interpreter(file, options);
            labelList = loadLabels("labelmap.txt", assets);

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

    public List loadLabels(String labelPath, AssetManager assetManager) throws IOException {
        InputStream in = assetManager.open("labelmap.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        List outList = new ArrayList();
        String line;
        while( (line = br.readLine()) != null)
        {
            outList.add(line);
            }
        return outList;
    }




/*
Here is the recognizeImage method that I wish to call from the CameraActivity class.
-
-
-
*/
    public float[][] recognizeImage(final Bitmap bitmap) {
        // Scale the bitmap to the appropriate shape
        Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, inputSize, inputSize, false);
        ByteBuffer byteBuffer = convertBitmapToByteBuffer(scaledBitmap);
        final float[][] result = new float[1][labelList.size()];
        interpreter.run(byteBuffer, result);
        return result;

    }





    public ByteBuffer convertBitmapToByteBuffer(Bitmap bitmap) {
        //bitmap = Bit
        // Preallocate memory for bytebuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(4*inputSize*inputSize*pixelSize);
        byteBuffer.order(ByteOrder.nativeOrder());

        // Initialize pixel data array and populate from bitmap
        int [] intArray = new int[inputSize*inputSize];
        bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0 , 0,
                bitmap.getWidth(), bitmap.getHeight());

        int pixel = 0;      // pixel indexer
        for (int i=0; i<inputSize; i++) {
            for (int j=0; j<inputSize; j++) {
                int input = intArray[pixel++];

                byteBuffer.putFloat((((input >> 16 & 0x000000FF) - imageMean) / imageStd));
                byteBuffer.putFloat((((input >> 8 & 0x000000FF) - imageMean) / imageStd));
                byteBuffer.putFloat((((input & 0x000000FF) - imageMean) / imageStd));
            }
        }
        return byteBuffer;
    }


}
公共类CameraActivity扩展了AppCompatActivity{
私有静态最终int权限\ U代码=1000;
私有静态最终整数图像捕获编码=1001;
分类器;
按钮mCaptureBtn;
图像视图;
Uri图像;
公共位图旋转位图;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView=findviewbyd(R.id.image\u视图);
mCaptureBtn=findviewbyd(R.id.capture\u image\u btn);
mCaptureBtn.setOnClickListener(新视图.OnClickListener(){
//1:创建按钮
//2:创建OnClickListener的实例以等待单击
//3:重写onClick方法
@凌驾
公共void onClick(视图v){
//如果操作系统较新或与Marshmello相同
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.M){
//检查权限
if(checkSelfPermission(Manifest.permission.CAMERA)==
PackageManager.PERMISSION\u被拒绝||
checkSelfPermission(Manifest.permission.WRITE\u外部存储)==
PackageManager.权限(被拒绝){
//权限不允许,因此请求它
字符串[]权限={Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
请求权限(权限、权限代码);
}否则{
//已授予许可
openCamera();
}
}否则{
openCamera();
}
}
});
}
私有void openCamera(){
//ContentValues创建一个集合类型对象,该对象可以存储ContentResolver可以访问的值
ContentValues=新的ContentValues();
//存储值
value.put(MediaStore.Images.Media.TITLE,“新图片”);
value.put(MediaStore.Images.Media.DESCRIPTION,“来自照相机”);
//使用前面创建的ContentValues获取uri(统一资源标识符)
image\u uri=getContentResolver().insert(MediaStore.Images.Media.EXTERNAL\u CONTENT\u uri,值);
//摄像机意图
Intent cameraIntent=新的Intent(MediaStore.ACTION\u IMAGE\u CAPTURE);
//额外的_输出约束将完整大小的图像数据输出到uri
cameraIntent.putExtra(MediaStore.EXTRA\u输出,图像uri);
if(cameraIntent.resolveActivity(getPackageManager())!=null){
startActivityForResult(摄像机帐篷、图像捕获码);
}
}
//处理权限请求
@凌驾
public void onRequestPermissionsResult(int-requestCode,@NonNull-String[]permissions,@NonNull-int[]grantResults){
//每当用户在Perm Req提示符下按allow或deny时,就会调用此方法
开关(请求代码){
案例许可证代码:{
如果(grantResults.length>0&&grantResults[0]==
PackageManager.权限(已授予){
//已授予弹出窗口的权限
openCamera();
}
否则{
//来自弹出窗口的权限被拒绝
Toast.makeText(此“权限被拒绝…”,Toast.LENGTH_SHORT.show();
}
}
}
}
@RequiresApi(api=Build.VERSION\u code.N)
@凌驾
受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
super.onActivityResult(请求代码、结果代码、数据);
//从照相机捕获图像时调用
//从uri获取图像
位图=空;
智力定向;
//确保我们有一个图像uri
试一试{
//将uri转换为InputStream
InputStream in=getContentResolver().openInputStream(图像uri);
//从InputStream获取Exif信息
ExifInterface ei=新ExifInterface(in);
//根据版本获取位图
if(android.os.Build.VERSION.SDK\u INT>=android.os.Build.VERSION\u code.P){
试一试{
位图=ImageDecoder.decodeBitmap(ImageDecoder.createSource(getContentResolver(),image_uri));
}捕获(IOE异常){
e、 printStackTrace();
}
}否则{
试一试{
位图=MediaStore.Images.Media.getBitmap(getContentResolver(),image\u uri);
}捕获(IOE异常){
e、 printStackTrace();
}
}
//从图像中获取方向信息
方向=ei.getAttributeInt(ExifInterface.TAG_方向,
现有接口。方向(未定义);
//将图像旋转(如果需要)到纵向模式
开关(方向){
外壳出口接口。方向旋转90:
旋转位图=旋转图像(位图,90);
打破
外壳出口接口.方向旋转180:
Classifier classifier = new Classifier();
classifier.init();