Java 正在获取实时摄影机的RGB值,错误NullPointerException

Java 正在获取实时摄影机的RGB值,错误NullPointerException,java,android,opencv,opencv4android,Java,Android,Opencv,Opencv4android,[更新]:已添加屏幕截图 我在学习《基础教程》tutorial-1-camerapreviewfrom。 我想在屏幕上点击并获得该xy位置的RGB颜色。 我得到了以下方面的帮助(从相机预览中的触摸事件中检索精确的RGB值): 获取x-y坐标: @SuppressWarnings("deprecation") @Override public boolean onTouchEvent(MotionEvent event) { x = (int)event.getX(

[更新]:已添加屏幕截图

我在学习《基础教程》
tutorial-1-camerapreview
from。 我想在屏幕上点击并获得该
x
y
位置的RGB颜色。 我得到了以下方面的帮助(从相机预览中的触摸事件中检索精确的RGB值):

获取x-y坐标:

@SuppressWarnings("deprecation")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int)event.getX();
        y = (int)event.getY();
        return super.onTouchEvent(event);
    }
onCameraFrame作为:

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        if(x != -1 && y != -1) { //if this is true, you've touched something
            rgb = mRgba.get(x,y);

            Log.d(TAG, "Touch coordinates--> " + "x: " + String.valueOf(x)
                    + " y: " + String.valueOf(y) + " \n"
                    + "RGB values--> "
                    + " Red: "   + rgb[0]
                    + " Green: " + rgb[1]
                    + " Blue: "  + rgb[2]);


            x = -1;
            y = -1;
        }

        return mRgba;
    }
我发现以下错误:

E/AndroidRuntime:致命异常:线程-904

java.lang.NullPointerException

位于test.com.imagecolortest.MainActivity.onCameraFrame(MainActivity.java:104)

位于org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:392)

位于org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:373)

运行(Thread.java:838)

注意:

@SuppressWarnings("deprecation")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int)event.getX();
        y = (int)event.getY();
        return super.onTouchEvent(event);
    }
第104行(MainActivity.java:104)是:

  • y:“+String.valueOf(y)+”\n
同时

有时,当我点击屏幕左上角附近时,它就会运行。但当我点击其他地方时,它崩溃了

有时,当它通过触摸屏幕上的一个点击来运行时,它会给出两个日志(触发两次):(用相机扫描图像)

有时当红色
rgb[0]
值为
0
时,
Log.d
会触发三次。不知道为什么

[编辑]:我们可以在稍后返回
super.onTouchEvent(event)
时解决此问题,而不是返回
true
。我稍后会补充

我的代码:
MainActivity.java

package test.com.imagecolortest;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements CvCameraViewListener2 {
    private static final String TAG = "OCVSample::Activity";
    private CameraBridgeViewBase mOpenCvCameraView;
    private boolean              mIsJavaCamera = true;
    private MenuItem mItemSwitchCamera = null;
    private Mat mRgba;
    int x = -1, y = -1;
    double [] rgb;
    TextView touchView;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: {
                    Log.i(TAG, "OpenCV loaded successfully");
                    mOpenCvCameraView.enableView();
                } break;
                default: {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    public MainActivity() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_main);

        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.activity_main);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        touchView = (TextView)findViewById(R.id.textView);
    }

    @Override
    public void onPause(){
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume(){
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height) {
        mRgba = new Mat(height, width, CvType.CV_8UC4);
    }

    public void onCameraViewStopped() {
        mRgba.release();
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        if(x != -1 && y != -1) { //if this is true, you've touched something
            rgb = mRgba.get(x,y);

            Log.d(TAG, "Touch coordinates--> " + "x: " + String.valueOf(x)
                    + " y: " + String.valueOf(y) + " \n"
                    + "RGB values--> "
                    + "Red: " + rgb[0]
                    + " Green: " + rgb[1]
                    + " Blue: " + rgb[2]);

// touchView.setText("Touch coordinates--> " + "x: " + String.valueOf(x)
//                    + " y: " + String.valueOf(y) + " \n" + "RGB values--> " + "Red: " + rgb[0]
//                    + " Green: " + rgb[1] + " Blue: " + rgb[2]);
            x = -1;
            y = -1;
        }

        return mRgba;
    }

    //detects touches on screen
    @SuppressWarnings("deprecation")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = (int)event.getX();
        y = (int)event.getY();

        //Display display = getWindowManager().getDefaultDisplay();
        //int width = display.getWidth();
        //int height = display.getHeight();
        //double [] rgb = mRgba.get(width,height);


//        touchView.setText("Touch coordinates--> " + "x: " + String.valueOf(x)
//                + " y: " + String.valueOf(y) + " \n" + "RGB values--> " + "Red: " + rgb[0]
//                + " Green: " + rgb[1] + " Blue: " + rgb[2]);

        return super.onTouchEvent(event);
    }
}
活动\u main.xml

<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent" >

    <org.opencv.android.JavaCameraView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"
        android:id="@+id/activity_main"
        opencv:show_fps="true"
        opencv:camera_id="any" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Medium Text"
        android:id="@+id/textView"
        android:layout_gravity="left|bottom" />


</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="test.com.imagecolortest">
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        >
        <activity   android:name=".MainActivity"
                    android:screenOrientation="landscape"
                    android:configChanges="keyboardHidden|orientation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <supports-screens android:resizeable="true"
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:anyDensity="true" />

</manifest>
我注意到一些非常奇怪的行为。
y
(垂直)值正常。但当我将手指从左向右滑动时,
x
值在
0-599
范围内工作良好,当它触及
600
值时,应用程序突然崩溃。 请参阅附件照片:

14.93FPS@800x600
R:134.0g:155.0b:151.0
x:371 y:488

  • 红点显示,我的手指现在在哪里
  • 红色的矩形(实际上是正方形)显示,当我在这里面触摸时,我的应用程序工作,但当它超出(最右边)时,它崩溃了
CvCameraViewFrame.rgba()返回一个Mat,OpenCV Mat索引首先获取行,然后获取列。您正在调用
rgb=mRgba.get(x,y)因此您将x作为行传递,y作为列传递,当x>=600时,这将超出800x600显示的范围


)

为什么需要
String.valueOf
?只需将
x
y
直接添加到字符串中,我怀疑
inputFrame.rgba()
为null或
inputFrame==null
。你能检查两个吗?嗨@cricket\u 007
如果(inputFrame==null)
Android Studio给我这个警告:
条件“inputFrame==null”总是“false”
。在我的例子中,
if(inputFrame.rgba()==null)
给出了
false
非null
。通过这样做:
if(null!=y)
AndroidStudio v2.1.2给出了这个错误
Operator'!='无法应用于“null”、“int”
。抄送:@Khanal,我不认为
x
&
y
为空或存在问题。我可以
Log.d(标记“x:+x+”y:+y)通过触摸屏幕上的任意位置。我只是把这些注释掉:
rgb[0]、rgb[1]、rgb[2]
似乎有一些问题:
rgb=mRgba.get(x,y)我再次感觉到,我没有为应用程序定义屏幕大小。我使用的是华为荣誉h30-u10,当我在上面的应用程序中打开时,我的屏幕上只显示了部分摄像头预览,屏幕左右两侧都有黑条(横向)。这迫使我认为屏幕上可见的摄像头具有
x
i-e:width等于
600
。我可能错了。但当我点击黑屏的左上角(前摄像头的正下方)时,我可以得到
x
y
的值。我相信这是一个积极的发现。非常感谢您的回答,我会检查并很快回来@Chungzuwalla有一个问题。如果我的屏幕处于
横向
模式(如图所示,我在清单中将其强制为:
android:screenOrientation=“横向”
),那么在这种情况下,我的
x
,而
y
,我附加的图片显示
像素是:
800
。那我为什么会出错呢?我的
x
800
。我说的对吗?我不知道Android开发,只知道OpenCV。所以我不知道屏幕方向对代码有什么影响。但是,显示分辨率通常表示为宽度x高(例如,对于HD,为1920x1080,而不是1080x1920),并且在2D图形中通常使用x、y顺序,而矩阵尺寸通常写为行×列,并以行第一()为索引。在代码中适当的位置切换这两个符号是使用OpenCV编程图形系统的一部分。在C++中,避免这种错误的一种方法是总是用CV::点来索引CV::MAT,因为点构造函数采用通常的2D图形顺序(x,y):<代码> uCHAR Val= Mat。AT(CV::点(x,y));
Hello我将
public void onCameraViewStarted(int-width,int-height){mRgba=new Mat(height,width,CvType.CV_8UC4);}
更改为
public void onCameraViewStarted(int-width,int-height){mRgba=new Mat(width,height,CvType.CV_8UC4);}
因此这使得垂直
y
完美,但
x
没有超出
599
。还改变了
rgb=mRgba.get(x,y)中
x
y
的顺序但它不起作用;int width2=display.getWidth();int h
Imgproc.putText() as: Imgproc.putText(mRgba,"R:"+rgb[0] + " G:"+rgb[1] +" B:"+rgb[2] + "x: " + x + " y: " + y, new Point(10,52), Core.FONT_HERSHEY_COMPLEX,.7, new Scalar(5,255,255),2,8,false );