11

我想计算相机和识别物体之间的距离。为此我尝试了很多方法,我尝试使用加速度计找到物体和相机之间的角度,然后使用

d = h * tan a

h 是距底座的高度,通常为 1.4

我试图通过使用获取方向方法来计算角度。请让我知道我在哪里做错了。我一直在努力满足这个要求已经超过 2 天了。我们研究了 Android Store 上提供的各种相机应用程序,并试图了解它们的功能,但没有任何成果。

 mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            accSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            magnetSensor = mSensorManager
                    .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            gravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            geoMagnetic = event.values;
        if (gravity != null && geoMagnetic != null) {
            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, gravity,
                    geoMagnetic);
            if (success) {
                /* Orientation has azimuth, pitch and roll */
                float orientation[] = new float[3];
                //SensorManager.remapCoordinateSystem(R, 1, 3, orientation);
                SensorManager.getOrientation(R, orientation);
                azimut = 57.29578F * orientation[0];
                pitch = 57.29578F * orientation[1];
                roll = 57.29578F * orientation[2];
            }
        }
    }


        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get an image from the camera

                double d = (Math.tan(Math.toRadians(Math.abs(pitch))) * sensorHeight);
                Toast.makeText(
                        getApplicationContext(),
                        "Distance = "
                                + String.valueOf(d)
                                        + "m  Angle = "
                                        + String.valueOf(Math.toRadians(Math.abs(pitch))),
                        Toast.LENGTH_LONG).show();


            }
        });



protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, accSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, magnetSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
    }
4

2 回答 2

8

您的 getRotationMatrix 可能返回错误!您应该将这些值复制到您自己的向量中,以免它们混淆!使用 clone() 方法来做到这一点!

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        gravity = event.values.clone();
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        geoMagnetic = event.values.clone();

使用您的代码加上此更改,我能够获得方位角/俯仰角/滚动值,如果没有此更改,成功标志将返回 false:

Log.d("a", "orientation values: " + azimut + " / " + pitch + " / " + roll);
05-21 16:07:55.743: D/a(29429): orientation values: 77.71578 / 43.352722 / -152.39603
05-21 16:07:55.883: D/a(29429): orientation values: 175.26134 / 23.031355 / -148.72844
05-21 16:07:56.793: D/a(29429): orientation values: -146.3089 / 4.1098075 / -14.46417

如果您以纵向模式握住手机,则应使用 PITCH 值,如果您以横向模式握住手机,则应使用 ROLL 值。

如果您将手机保持在 1.4 的高度,那么您将拥有:

float dist = Math.abs((float) (1.4f * Math.tan(pitch * Math.PI / 180)));

请注意,您应该在 Math.tan 函数上使用 RADIANS 而不是 DEGREES。

我在这里测试过,这些值似乎是有效的!

于 2013-05-20T17:04:35.007 回答
4

最终代码是

mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            accSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            magnetSensor = mSensorManager
                    .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            gravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            geoMagnetic = event.values;
        if (gravity != null && geoMagnetic != null) {
            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, gravity,
                    geoMagnetic);
            if (success) {
                /* Orientation has azimuth, pitch and roll */
                float orientation[] = new float[3];
                //SensorManager.remapCoordinateSystem(R, 1, 3, orientation);
                SensorManager.getOrientation(R, orientation);
                azimut = 57.29578F * orientation[0];
                pitch = 57.29578F * orientation[1];
                roll = 57.29578F * orientation[2];
            }
        }
    }


        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get an image from the camera

                float d = Math.abs((float) (1.4f * Math.tan(pitch * Math.PI / 180)));
                Toast.makeText(
                        getApplicationContext(),
                        "Distance = "
                                + String.valueOf(d)
                                        + "m  Angle = "
                                        + String.valueOf(Math.toRadians(Math.abs(pitch))),
                        Toast.LENGTH_LONG).show();


            }
        });



protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, accSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, magnetSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
    }
于 2013-05-30T06:43:24.423 回答