how can we measure distance between object and android phone camera

Rats Tyagi picture Rats Tyagi · Apr 11, 2013 · Viewed 16.4k times · Source

I want to calculate the distance between the camera and the recognized object.For this I tried a lot of methods, I tried to find the angle between the object and the camera using accelerometer and then use

d = h * tan a

h is height of from from the base generally which is 1.4

and i tried to calculate the angle by using get orientation method. Kindly let me know where am I doing wrong. Its been more than 2 days I have been struggling with this requirement. We have looked into various Camera applications which are available on Android Store and have tried to understand the functionality of the same but nothing has been fruitful.

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

Answer

thiagolr picture thiagolr · May 20, 2013

Your getRotationMatrix is probably returning false! You should copy the values to your own vectors so they don't get mixed up! Use the clone() method to do so!

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

Using your code plus this change I was able to get the azimuth/pitch/roll values, without this change the success flag returns 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

You should use the PITCH value if you are holding the phone in portrait mode, if you are holding the phone in landscape mode you should use the ROLL value.

If you are holding the phone at a 1.4 height then you will have:

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

Please note that you should use RADIANS and not DEGREES on the Math.tan function.

I tested here and the values seem to be valid!