Android OpenCV相机的例子只是显示黑屏



我花了好几天(好吧,晚上(的时间试图解决这个问题。网上有很多例子是针对不同版本的Android Studio、不同版本的安卓、不同版本OpenCV的,我无法将其中任何一个进入最后的"工作"阶段。

这个例子(基于youtube教程,我已经到了需要权限的地步。没关系,我添加了权限并检查了它们,它会弹出询问用户相机权限。但屏幕保持空白。我已经进行了logcat调试,所有正确的方法似乎都被调用了。如果有任何帮助,我将不胜感激。

代码:

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>

主要活动.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文件:

<?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只是黑色的。

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

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

此外,对于尚未授予权限的情况,您可能希望在onRequestPermissionsResult()中调用此函数。onRequestPermissionsResult()函数位于Activity类中。当用户授予或拒绝应用程序发出的权限请求时,会调用它。这可能看起来如下:

@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许可系统的更多信息,请查看以下资源:

  • 请求应用程序权限本网站介绍了请求权限的过程以及所有必要的步骤
  • 权限概述此网站在清单文件中包含有关uses-feature的信息。您可能想在清单文件中添加以下行:<uses-feature android:name="android.hardware.camera" android:required="true" />,以防止在没有摄像头的设备上安装

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

我在android 10中遇到了同样的问题。经过大量的尝试和错误,我发现以下方法必须在主要活动中实施:

@Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}

我只有在发布模式apk时才遇到这个问题解决方案是在"活动"中添加Manifest.permission.READ_MEDIA_VIDEO的权限。希望它能在我使用两天后帮助别人

最新更新