首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android摄像头影响传感器(加速度计和磁场),而手机面对用户

Android摄像头影响传感器(加速度计和磁场),而手机面对用户
EN

Stack Overflow用户
提问于 2016-12-21 19:21:08
回答 1查看 875关注 0票数 1

对于我提出的申请,我需要一个照相机和一个指南针。应用程序被设置为在清单中处于景观模式。

首先我实现了指南针。正如Android开发者所建议的那样,我使用了两个传感器--加速度计和磁场。我就是这样做的:

我的活动实现了SensorEventListener。在onCreate()中,我使用以下方法初始化sensorManager

代码语言:javascript
复制
sManager = (SensorManager) getSystemService(SENSOR_SERVICE);

我在onResume()中注册了听众,如下所示:

代码语言:javascript
复制
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_NORMAL);

当然,在onPause()中取消它们的注册。我不使用onAccuracyChanged()。这就是我在onSensorChanged()所做的

代码语言:javascript
复制
@Override
public void onSensorChanged(SensorEvent event) {
    switch (event.sensor.getType()) {
        case Sensor.TYPE_MAGNETIC_FIELD:
            mags = event.values.clone();
            break;
        case Sensor.TYPE_ACCELEROMETER:
            accels = event.values.clone();
            break;
    }

    if (mags != null && accels != null) {
        gravity = new float[9];
        magnetic = new float[9];
        SensorManager.getRotationMatrix(gravity, magnetic, accels, mags);
        float[] outGravity = new float[9];

        float inclination = (float) Math.acos(gravity[8]);
        if (inclination < Math.toRadians(25)
                || inclination > Math.toRadians(155)) {
            // device is close to flat. Remap for landscape.
            SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outGravity);
            SensorManager.getOrientation(outGravity, values);
        } else {
            // device is not flat. Remap for landscape and perpendicular
            SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_X,SensorManager.AXIS_Z, outGravity);
            SensorManager.getOrientation(outGravity, values);
        }
        azimuth =  Math.round(Math.toDegrees(values[0]));
    }
}

正如您所看到的,我区分了手机何时平躺在桌子上,以及用户持有它时(就像拍照时一样)。当我单独使用这段代码时,所有东西或多或少都能正常工作。我得到了正确的方位值,无论是当手机躺在桌子上,当它垂直于桌子时(大约相差5-10度,但我可以接受)。

当将摄像机预览添加到应用程序时,问题就开始了。我的活动实现了SurfaceHolder.Callback。我用onCreate()初始化我的相机

代码语言:javascript
复制
SurfaceView cameraView = (SurfaceView)findViewById(R.id.camera_view);
surfaceHolder = cameraView.getHolder();
surfaceHolder.addCallback(this);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

我就是这样实现接口的:

代码语言:javascript
复制
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    camera = Camera.open();
    camera.setDisplayOrientation(0);
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
    if (isCameraOn) {
        camera.stopPreview();
        isCameraOn = false;
    }

    if (camera != null) {
        try {
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
            isCameraOn = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    camera.stopPreview();
    camera.release();
    camera = null;
}

当我将相机代码添加到我的项目中,并在手机屏幕上显示相机时,当手机突然垂直时,我的感应器不能正常工作。如果手机平躺在桌子上,我得到的方位值是正确的。当手机垂直于桌子时,我的方位角值大约是40度(虽然稳定)。

我试图寻找一个解决方案(包括自己和在线),但到目前为止,我的努力是徒劳的。我很想就如何解决这个问题找到一些方向。

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2016-12-21 19:34:41

首先,TYPE_MAGNETIC_FIELD传感器不会在所有设备中使用。您可以单独使用TYPE_ACCELEROMETER传感器来完成您的需求。

恢复加速度计传感器

代码语言:javascript
复制
Sensor accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

当传感器更改事件调用时,只需比较和复制值。

代码语言:javascript
复制
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    mGravity = event.values;
}

然后,您可以使用下面的函数来获得所有轴的传感器值。

代码语言:javascript
复制
public int[] getDeviceAngles() {
  float[] g = mGravity.clone();
  double normOfG = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]);

  // Normalize the accelerometer vector
  g[0] = (float) (g[0] / normOfG);
  g[1] = (float) (g[1] / normOfG);
  g[2] = (float) (g[2] / normOfG);

  int x = (int) Math.round(Math.toDegrees(Math.atan2(g[1], g[0])));
  int pitch = (int) Math.round(Math.toDegrees(Math.atan2(g[1], g[2])));
  int rollValue = (int) Math.round(Math.toDegrees(Math.atan2(g[2], g[0])));
  int pitchValue = pitch * -1;
  int[] values = new int[3];
  values[0] = x;
  values[1] = pitchValue;
  values[2] = rollValue;
  //values contains: azimut, pitch and roll
  return values;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41270404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档