Android OpenCV相机示例仅显示黑屏 [英] Android OpenCV camera example is just showing black screen

查看:851
本文介绍了Android OpenCV相机示例仅显示黑屏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了好几天(好,晚上)来解决这个问题.在线上有如此多的示例涉及不同版本的Android Studio,不同版本的Android,不同版本的OpenCV,但我无法将其中任何一个带入最终的正常工作"阶段.

I've spent days (well, nights) trying to work this out. So many examples online are for different versions of Android Studio, different versions of Android, different versions of OpenCV and I can't get any of them to the final 'working' stage.

此示例(基于 youtube教程,我需要权限.很好,我在其中添加了内容并进行了检查,然后弹出询问用户相机权限.但是屏幕仍然空白.我已经输入了logcat debug,所有正确的方法似乎都在请致电.

This example (based on a youtube tutorial, I got to the point where I needed permissions. That's fine, I added that in and a check for them, and it pops up asking the user for camera permissions. But the screen stays blank. I've put in logcat debug, all the right methods seem to be getting called. Would appreciate any assistance.

代码:

Manifest.xml

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

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


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

MainActivity.java

MainActivity.java

package com.example.mytestopencvapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.JavaCamera2View;
import org.opencv.android.JavaCameraView;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {

    private static String TAG = "MainActivity";

    JavaCameraView javaCameraView;
    Mat mRGBA, mRGBAT;

    private final int PERMISSIONS_READ_CAMERA=1;

    BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(MainActivity.this) {
        @Override
        public void onManagerConnected(int status) {
            Log.d(TAG, "callbacksuccess");
            switch (status)
            {
                case BaseLoaderCallback.SUCCESS:
                {
                    Log.d(TAG, "case success");
                    javaCameraView.enableView();
                    break;
                }
                default:
                {
                    Log.d(TAG, "case default");
                    super.onManagerConnected(status);
                    break;
                }

            }

        }
    };

    static
    {
        if (OpenCVLoader.initDebug())
        {
            Log.d(TAG, "OpenCV is intialised");
        }
        else
        {
            Log.d(TAG, "OpenCV is not initialised");
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_main);
        javaCameraView = (JavaCameraView)findViewById(R.id.my_camera_view);
        javaCameraView.setVisibility(SurfaceView.VISIBLE);
        javaCameraView.setCvCameraViewListener(MainActivity.this);

// Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {

            // Permission is not granted
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.CAMERA)) {
                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CAMERA},
                PERMISSIONS_READ_CAMERA);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        } else {
            Log.d(TAG, "PERMISSIOns granted");
            // Permission has already been granted
        }


    }

    @Override
    public void onCameraViewStarted(int width, int height) {
        Log.d(TAG, "onCameraViewStarted");
        mRGBA = new Mat(height, width, CvType.CV_8UC4);
    }

    @Override
    public void onCameraViewStopped() {
        Log.d(TAG, "onCameraViewStopped");
        mRGBA.release();
    }

    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
    {
        Log.d(TAG, "onCameraFrame");
/*        mRGBA = inputFrame.rgba();
        mRGBAT = mRGBA.t();
        Core.flip(mRGBA.t(), mRGBAT, 1);
        Imgproc.resize(mRGBAT, mRGBAT, mRGBA.size());
        return mRGBAT;*/

        mRGBA = inputFrame.rgba();
        Core.transpose(mRGBA, mRGBAT);
        Imgproc.resize(mRGBAT, mRGBAT, mRGBAT.size(),0,0,0);
        Core.flip(mRGBA.t(), mRGBA, 1);
        return mRGBA;
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        if (javaCameraView != null)
        {
            javaCameraView.disableView();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
        if (javaCameraView != null)
        {
            javaCameraView.disableView();
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
        if (OpenCVLoader.initDebug())
        {
            Log.d(TAG, "OpenCV is intialised again");
            baseLoaderCallback.onManagerConnected((BaseLoaderCallback.SUCCESS));
        }
        else
        {
            Log.d(TAG, "OpenCV is not working");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, baseLoaderCallback);
        }
    }
}

我的res布局activity_main.xml文件:

And my res layout activity_main.xml file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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=".MainActivity">

    <org.opencv.android.JavaCameraView
        android:id="@+id/my_camera_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />


</RelativeLayout>

据我所知,我已经正确链接了它们,可以确认OpenCV的初始化,检查并授予了权限,但是然后... JavaCameraView只是黑色的.

As far as I can tell, I've linked them all correctly, I can confirm OpenCV initialises, permissions are checked and granted, but then...the JavaCameraView is just black.

推荐答案

您需要告诉CameraView相机权限已被授予.您可以通过调用setCameraPermissionGranted()函数来实现.此函数调用应进入onCreate方法中的权限授予"块,如下所示:

You need to tell the CameraView that the camera permission was granted. You can do so by calling the setCameraPermissionGranted() function. This function call should go into the 'permission granted' block in your onCreate method as shown below:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED) {
    // More code here ...
} else {
    Log.d(TAG, "Permissions granted");
    javaCameraView.setCameraPermissionGranted();
}

此外,对于尚未授予许可的情况,您可能想在onRequestPermissionsResult()中调用此函数. onRequestPermissionsResult()函数位于您的Activity类中.当授予或拒绝该权限的用户请求应用程序发出时,将调用此方法. 可能如下所示:

In addition you propably want call this function in onRequestPermissionsResult() for the case where the permission is not granted already. The onRequestPermissionsResult() function is located in your Activity class. It is called when the user granted or denied on of the permission requests the app made. This could look as follows:

@Override
public void onRequestPermissionsResult(
        int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    // Ensure that this result is for the camera permission request
    if (requestCode == PERMISSIONS_READ_CAMERA) {
        // Check if the request was granted or denied
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // The request was granted -> tell the camera view
            javaCameraView.setCameraPermissionGranted();
        } else {
            // The request was denied -> tell the user and exit the application
            Toast.makeText(this, "Camera permission required.",
                    Toast.LENGTH_LONG).show();
            this.finish();
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

有关Android权限系统的更多信息,请查看以下资源:

For more information about the permission system on Android have a look at the following resources:

  • 请求应用权限本网站介绍了所有请求权限的过程必要的步骤.
  • 权限概述此站点在清单中包含有关uses-feature的信息文件.您可能想在清单文件中添加以下行:<uses-feature android:name="android.hardware.camera" android:required="true" />以防止在没有摄像头的设备上安装.
  • Request App Permissions This site describes the process of requesting permissions with all necessary steps.
  • Permissions Overview This site has information about uses-feature in the manifest file. You probably want to add the following line to your manifest file: <uses-feature android:name="android.hardware.camera" android:required="true" /> to prevent the installation on devices without camera.

现在您将看到,实际上已经调用了onCameraFrame回调函数.这将导致NullPointerException,因为mRGBAT未初始化.要仅查看摄像机图像,您可以直接在此功能中返回inputFrame.rgba().这将至少显示摄像机图像.所有其他步骤都是正常的图像处理,以旋转/镜像图像.

Now you'll see, that the onCameraFrame callback function is actually invoked. This will lead to a NullPointerException because mRGBAT is not initialized. To just see the camera image you can return inputFrame.rgba() directly in this function. This will at least show the camera image. All further steps are normal image processing to rotate / mirror the image.

这篇关于Android OpenCV相机示例仅显示黑屏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆