【问题标题】:OpenCV JavaCameraView shows a blank/black screen [duplicate]OpenCV JavaCameraView显示空白/黑屏[重复]
【发布时间】:2020-05-28 19:39:58
【问题描述】:

第一次 Android 开发人员,过去几个月我一直在努力使用 OpenCV 的 JavaCameraView,它总是显示空白/黑屏。我在网上关注了很多教程,但是跟随它们到发球台带来了 0 个结果。我知道我的代码正在正确加载 OpenCV 并且 Logcat 描述该代码尝试启动相机视图,但无济于事。我需要帮助。代码有问题的部分是这样的:

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
//Activate Camera
private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback (this) {
    @Override
    public void onManagerConnected(int status) {
        if (status == BaseLoaderCallback.SUCCESS) {
            OpenCVCamView.enableView();                                //Enable Cam View
            Log.d(TAG, "Tried enabling Camera View!");
        } else { super.onManagerConnected(status); }
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d(TAG, "on Create");
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.activity_main);                                     //UI Layout loaded
    OpenCVCamView = findViewById(R.id.cam_view);                                    
    textView = findViewById(R.id.arduino_log);                                  
    textView.setVisibility(SurfaceView.INVISIBLE);                                
    OpenCVCamView.setVisibility(SurfaceView.VISIBLE);                              
    OpenCVCamView.setCvCameraViewListener(this);                                   
@Override
public void onCameraViewStarted(int width, int height) {
    Log.d(TAG, "on Camera view Started");
    rgba = new Mat (height, width, CvType.CV_8UC4);                         
    rgbaF = new Mat (height, width, CvType.CV_8UC4);                        
    rgbaT = new Mat (height, width, CvType.CV_8UC4);                        
    intMat = new Mat(height, width, CvType.CV_8UC4);                        
    gray = new Mat (height, width, CvType.CV_8UC1);                         
}
@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    rgba = inputFrame.rgba();                                               
    Log.d(TAG, "on Camera Frame");
    Core.transpose(rgba,rgbaT);
    Imgproc.resize(rgbaT,rgbaF,rgbaF.size(),0,0,0);
    Core.flip(rgbaF,rgba,1);
    return rgba;
    }
}

我的 activity_main XML 文件是这样的:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:opencv="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <org.opencv.android.JavaCameraView
        android:id="@+id/cam_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible"
        opencv:camera_id="any"/>
        <TextView
        android:id="@+id/arduino_log"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="0dp"
        android:visibility="invisible" />
</RelativeLayout>

我正在使用适用于 Android 的 OpenCV 4.3 版。

【问题讨论】:

    标签: android opencv


    【解决方案1】:

    今天发现自己在同一个兔子洞里,然后了解了mOpenCvCameraView.setCameraPermissionGranted() 方法,但不太确定该放在哪里。幸运的是,已经有你的问题和另一个答案,描述了如何请求使用相机的权限以及何时调用该方法:Android OpenCV camera example is just showing black screen

    这是我对这个主题的看法:

    class MainActivity : AppCompatActivity(), CameraBridgeViewBase.CvCameraViewListener2 {
    
        companion object {
            private const val REQUEST_CODE_CAMERA_PERMISSION = 101
        }
    
        private lateinit var mOpenCvCameraView: CameraBridgeViewBase
        private lateinit var mIntermediateMat: Mat
        private lateinit var binding: ActivityMainBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            // this is ViewBinding for Android
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            // check for necessary camera permission
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                when {
                    ContextCompat.checkSelfPermission(
                        this,
                        Manifest.permission.CAMERA
                    ) == PackageManager.PERMISSION_GRANTED -> {
                        // camera permission granted
                        activateOpenCVCameraView()
                    }
                    shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
                        // In an educational UI, explain to the user why your app requires this
                        // permission for a specific feature to behave as expected. In this UI,
                        // include a "cancel" or "no thanks" button that allows the user to
                        // continue using your app without granting the permission.
                    }
                    else -> {
                        // directly ask for the permission.
                        requestPermissions(
                            arrayOf(Manifest.permission.CAMERA),
                            REQUEST_CODE_CAMERA_PERMISSION
                        )
                    }
                }
            }
        }
    
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray
        ) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            // overengineered check for if permission with our request code and permission name was granted
            if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {
                val indexOfCameraPermission = permissions.indexOf(Manifest.permission.CAMERA)
                if (indexOfCameraPermission != -1) {
                    if (grantResults.isNotEmpty()) {
                        if (grantResults[indexOfCameraPermission] == PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(
                                applicationContext,
                                "Camera permission granted!",
                                Toast.LENGTH_LONG
                            ).show()
                            activateOpenCVCameraView()
                        } else {
                            Toast.makeText(
                                applicationContext,
                                "Camera permission is required to run this app!",
                                Toast.LENGTH_LONG
                            ).show()
                        }
                    }
                }
            }
        }
    
        private fun activateOpenCVCameraView() {
            // everything needed to start a camera preview
            mOpenCvCameraView = binding.cameraView
            mOpenCvCameraView.setCameraPermissionGranted()
            mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_ANY)
            mOpenCvCameraView.visibility = SurfaceView.VISIBLE
            mOpenCvCameraView.setCvCameraViewListener(this)
            mOpenCvCameraView.enableView()
        }
    
    
        override fun onResume() {
            super.onResume()
            // there's no need to load the opencv library if there is no camera preview (I think that sounds reasonable (?))
            if (ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.CAMERA
                ) == PackageManager.PERMISSION_GRANTED
            ) {
                if (!OpenCVLoader.initDebug()) {
                    log("Internal OpenCV library not found. Using OpenCV Manager for initialization");
                    OpenCVLoader.initAsync(
                        OpenCVLoader.OPENCV_VERSION_3_0_0, this,
                        mLoaderCallback
                    )
                } else {
                    log("OpenCV library found inside package. Using it!");
                    mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
                }
            }
        }
    
        private val mLoaderCallback: BaseLoaderCallback = object : BaseLoaderCallback(this) {
            override fun onManagerConnected(status: Int) {
                when (status) {
                    LoaderCallbackInterface.SUCCESS -> {
                        log("OpenCV loaded successfully")
                        activateOpenCVCameraView()
                    }
                    else -> super.onManagerConnected(status)
                }
            }
        }
    
        override fun onCameraViewStarted(width: Int, height: Int) {
            log("onCameraViewStarted")
            mIntermediateMat = Mat()
        }
    
        override fun onCameraViewStopped() {
            log("onCameraViewStopped")
            // Explicitly deallocate Mats
            mIntermediateMat.release()
        }
    
        override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat {
            log("onCameraFrame")
            val rgba = inputFrame!!.rgba()
    
            return rgba
        }
    
        override fun onDestroy() {
            mOpenCvCameraView.disableView()
            super.onDestroy()
        }
    
        private fun log(message: String) {
            Log.i("MainActivity", message)
        }
    }
    

    【讨论】:

    • 非常感谢!我也很幸运地发现了 PermissionsGranted 函数,它成功了。大多数教程和文档都忽略了 Android 进程的这个关键部分,这很令人讨厌。
    • 无法使用 opencv 341 解析“CameraBridgeViewBase”中的“setCameraPermissionGranted”方法。请问有什么解决方案吗?
    • @AmbeshTiwari 在 OpenCV 4.x 中添加了权限辅助方法; see this commit。不知道在那个版本之前是如何处理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多