从相机预览中的触摸事件中检索确切的RGB值 [英] Retrieve exact RGB value from touch event in camera preview

查看:255
本文介绍了从相机预览中的触摸事件中检索确切的RGB值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在开发一个Android应用,该应用仅需要在相机预览中检索并显示触摸事件的坐标和RGB值。我是这种编程语言的初学者,我只是想尝试一下,但是在触摸事件中该应用始终崩溃。这是我在Android中尝试的代码:

I've been working on an Android app that simply needs to retrieve and display the coordinates and RGB values of a touch event on the camera preview. I'm a beginner at this programming language and I just wanted to try this but the app keeps crashing during a touch event. Here is the code I tried in Android:

    /* When copying this code set Permissions: CAMERA
     * Do this by adding to AndroidManifest.xml:
     * <uses-permission
    android:name="android.permission.CAMERA" />
     */

    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.Color;
    import android.hardware.Camera;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Display;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.MotionEvent;
    import android.widget.FrameLayout;
    import android.widget.TextView;

    @SuppressWarnings("deprecation") 

    public class MainActivity extends Activity {
private static final String TAG = "HDMapp_MainActivity";    //ERROR Log tag
private Camera mCamera = null;
private CameraDisplay mCameraView = null;
static TextView touchView;
private Bitmap bmp;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //try-catch block to try accessing the Android camera
    try {
        mCamera = Camera.open();
    } catch(Exception e) {
        Log.d(TAG, "Failed to get camera" + e.getMessage());
    }

    if (mCamera != null) {
        mCameraView = new CameraDisplay(this, mCamera); //create SurfaceView to show camera data
        FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
        camera_view.addView(mCameraView); //add the SurfaceView to the layout
    }

    touchView = (TextView)findViewById(R.id.touchView);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

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

    Display display = getWindowManager().getDefaultDisplay();
    int width = display.getWidth();
    int height = display.getHeight();

    int pixelVal = bmp.getPixel(heightC,widthC);
    int r = (pixelVal>>16) & 0xFF;
    int g = Color.green(pixelVal);
    int b = Color.blue(pixelVal);

    touchView.setText("Touch coordinates--> " + "x: " +
            String.valueOf(event.getX()) + " y: " + String.valueOf(event.getY()) + 
            " \n" + r + " \n" + g + " \n" + b);

    return super.onTouchEvent(event);
}
    }

我收到NullPointerException错误:

I am getting NullPointerException error:


E / MessageQueue-JNI(14476):java.lang.NullPointerException:尝试
调用虚拟方法'int android.graphics.Bitmap.getPixel (int,int)'
在空对象引用上

E/MessageQueue-JNI(14476): java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getPixel(int, int)' on a null object reference

我也尝试过使用 OpenCV4Android 而我仍然得到相同的结果:

I also tried using OpenCV4Android and I still get the same result:

    import org.opencv.android.BaseLoaderCallback;
    import org.opencv.android.CameraBridgeViewBase;
    import org.opencv.android.OpenCVLoader;
    import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
    import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
    import org.opencv.android.LoaderCallbackInterface;
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;

    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Display;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.MotionEvent;
    import android.view.SurfaceView;
    import android.view.WindowManager;
    import android.widget.TextView;

    public class MainActivity extends Activity implements CvCameraViewListener2 {
private CameraBridgeViewBase mOpenCvCameraView;
private Mat mRgba;
TextView touchView;
int x, y;
double [] rgb;

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

@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.i("OnCreate", "called onCreate");
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.activity_main);

    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.surface_view);
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
    mOpenCvCameraView.setCvCameraViewListener(this);

    //touchView = (TextView)findViewById(R.id.touchView);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

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

@Override
public void onResume()
{
    super.onResume();
    if (!OpenCVLoader.initDebug()) {
        Log.d("onResume", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
    } else {
        Log.d("onResume", "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) {
    // TODO Auto-generated method stub
    mRgba = inputFrame.rgba();
    rgb = mRgba.get(x,y);

    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);
    }
    }

同样,错误是:


E / MessageQueue-JNI(15884):java.lang.NullPointerException:尝试
调用虚拟方法'void
android.widget。在空的
对象引用上的TextView.setText(java.lang.CharSequence)'

E/MessageQueue-JNI(15884): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

这两个应用均显示相机预览但是当我触摸Nexus 7的屏幕时,该应用将停止运行。有人可以告诉我我在做错什么并且可能纠正我吗?

Both these apps show the camera preview but when I touch the screen of my Nexus 7, the app stops working. Can someone please tell me what I'm doing wrong and possibly correct me?

推荐答案

第二个示例应该可以工作,问题是x和y未初始化,因此在方法 onCameraFrame 中,您在其中初始化 rgb = mRgba.get(x,y),此 rgb 仍然为 null ,因为 x y 未初始化。因此,当您尝试打印它时,您的 nullPointerException

the second example should work, the problem is that x and y are not initialized, so in method onCameraFrame, where you initialize rgb = mRgba.get(x,y), after this rgb is still null, since x and y are not initialized. Hence, your nullPointerException when you try to print it.

我建议您只是初始化 x y 到开始的 -1

What I would suggest is that you just initialize x and y to -1 in the beginning:

int x=-1, y=-1;

,然后在触摸处理程序方法中,像这样更新x和y:

and then in touch handler method you update x and y like so:

public boolean onTouchEvent(MotionEvent event) {
    x = (int)event.getX();
    y = (int)event.getY();
    return super.onTouchEvent(event);
}

,然后在 onCameraFrame 方法中执行类似的操作

and in the onCameraFrame method you do something like this:

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);
    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;
}

希望这会有所帮助

这篇关于从相机预览中的触摸事件中检索确切的RGB值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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