OpenCV JavaCameraView显示空白/黑屏

3

作为一名首次接触Android开发的开发者,我在过去几个月中一直在努力解决OpenCV的JavaCameraView问题,该问题始终显示空白/黑屏。我已经遵循了许多在线教程,但是即使完全按照这些教程操作也没有取得任何结果。我知道我的代码正确加载了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版本。
1个回答

8

今天我也遇到了相同的问题,并了解到了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过程中这个关键部分。 - undefined
无法解决'CameraBridgeViewBase'中的'method 'setCameraPermissionGranted''。我正在使用OpenCV 341。请问有什么解决办法吗? - undefined
@AmbeshTiwari 这个权限辅助方法是在OpenCV 4.x中添加的;请参考此提交。不确定在那个版本之前是如何处理的。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接