2

I'm building an application on Android using a Samsung Galaxy Tab 10.1". I want to get the value of the scene luminance using the back camera of the device.

Unfortunately I could not find a way to access readings from the light sensor on the back of the device directly. I am therefore currently estimating luminance manually by calculating the mean of each grayscale frame. However, this method is inaccurate due to auto-correction of frame exposure and white balance. For example, if you point the camera at a very bright source the camera will darken the entire image and the mean of the grayscale frame will be too low (because the area outside the bright source will now be very dark).

I searched for methods that would allow me to disable the automatic corrections I mentioned, but didn't find anything.

Is there a method that will allow me to get the value of the scene luminance using the back camera?

stkent
  • 19,772
  • 14
  • 85
  • 111
3arbouch
  • 43
  • 9

2 Answers2

2

Unfortunately, you're correct that there is currently no way to obtain this data from the Android camera API.

Depending on your device, you may be able to capture a picture, then read the EXIF data off of it. This might let you see the exposure (ISO and shutter speed). This is the method that apps like Tiny Light Meter use. The problem is that some devices do not fully populate the EXIF data, so this method is hit-or-miss.

Nic Dahlquist
  • 1,005
  • 12
  • 15
0

In some devices (newer Androids only), spot metering is supported. You can use a JPEG callback triggered by a separate timer thread like an AsyncTask to then read the EXIF information which will meter to the select spot. To check whether this is available, you can use:

//on Event Touch callback on your SurfaceView
x=event.getX();
y=event.getY();
params=camera.getParameters();
... //check for rotation, calculate focus point (x, y: -1000, 1000)
if(params.getMaxNumMeteringAreas() > 0){
    //draw a meter area, however big you want, 1000 is weight (0-1000)
    Camera.Area ca=new Area(new Rect(x-25, y-25, x+25, y+25), 1000);
    List<Camera.Area> areas=new ArrayList<Area>();
    areas.add(ca);
    params.setFocusAreas(areas);
    params.setMeteringAreas(areas);
    camera.setParameters(params);
}else{
    //process the Bitmap and do the below...
}

On older devices (if you want backwards compatibility), you can still set a focus point (stored in your code) and then do an average of the pixels around that focus (I use 6% of width and height) compared to the EXIF value (if it's darker, lower the exposure, etc). For this you will likely want to use a push-to-meter button (since older devices lag when doing a JPEG callback).

average=((r+g+b)/3-128)/256
myEV=myEV+myEV*average

With both methods, just make sure that the image you're reading is correctly rotated (you can check by putting it into an ImageView and comparing it to the preview).

From EV you can convert to Lux or Foot Candles relatively easily (or whatever your preferred measurement is).

wblaschko
  • 3,252
  • 1
  • 18
  • 24