Home | History | Annotate | Download | only in scene1
      1 # Copyright 2013 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #      http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 import its.image
     16 import its.caps
     17 import its.device
     18 import its.objects
     19 import its.target
     20 import numpy
     21 import math
     22 from matplotlib import pylab
     23 import os.path
     24 import matplotlib
     25 import matplotlib.pyplot
     26 
     27 NAME = os.path.basename(__file__).split('.')[0]
     28 RESIDUAL_THRESHOLD = 0.0003  # approximately each sample is off by 2/255
     29 # The HAL3.2 spec requires that curves up to 64 control points in length
     30 # must be supported.
     31 L = 64
     32 LM1 = float(L-1)
     33 
     34 
     35 def main():
     36     """Test that device processing can be inverted to linear pixels.
     37 
     38     Captures a sequence of shots with the device pointed at a uniform
     39     target. Attempts to invert all the ISP processing to get back to
     40     linear R,G,B pixel data.
     41     """
     42     gamma_lut = numpy.array(
     43         sum([[i/LM1, math.pow(i/LM1, 1/2.2)] for i in xrange(L)], []))
     44     inv_gamma_lut = numpy.array(
     45         sum([[i/LM1, math.pow(i/LM1, 2.2)] for i in xrange(L)], []))
     46 
     47     with its.device.ItsSession() as cam:
     48         props = cam.get_camera_properties()
     49         its.caps.skip_unless(its.caps.compute_target_exposure(props) and
     50                              its.caps.per_frame_control(props))
     51 
     52         debug = its.caps.debug_mode()
     53         largest_yuv = its.objects.get_largest_yuv_format(props)
     54         if debug:
     55             fmt = largest_yuv
     56         else:
     57             match_ar = (largest_yuv['width'], largest_yuv['height'])
     58             fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
     59 
     60         e,s = its.target.get_target_exposure_combos(cam)["midSensitivity"]
     61         s /= 2
     62         sens_range = props['android.sensor.info.sensitivityRange']
     63         sensitivities = [s*1.0/3.0, s*2.0/3.0, s, s*4.0/3.0, s*5.0/3.0]
     64         sensitivities = [s for s in sensitivities
     65                          if s > sens_range[0] and s < sens_range[1]]
     66 
     67         req = its.objects.manual_capture_request(0, e)
     68         req['android.blackLevel.lock'] = True
     69         req['android.tonemap.mode'] = 0
     70         req['android.tonemap.curve'] = {
     71             'red': gamma_lut.tolist(),
     72             'green': gamma_lut.tolist(),
     73             'blue': gamma_lut.tolist()}
     74 
     75         r_means = []
     76         g_means = []
     77         b_means = []
     78 
     79         for sens in sensitivities:
     80             req["android.sensor.sensitivity"] = sens
     81             cap = cam.do_capture(req, fmt)
     82             img = its.image.convert_capture_to_rgb_image(cap)
     83             its.image.write_image(
     84                 img, '%s_sens=%04d.jpg' % (NAME, sens))
     85             img = its.image.apply_lut_to_image(img, inv_gamma_lut[1::2] * LM1)
     86             tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
     87             rgb_means = its.image.compute_image_means(tile)
     88             r_means.append(rgb_means[0])
     89             g_means.append(rgb_means[1])
     90             b_means.append(rgb_means[2])
     91 
     92         pylab.title(NAME)
     93         pylab.plot(sensitivities, r_means, '-ro')
     94         pylab.plot(sensitivities, g_means, '-go')
     95         pylab.plot(sensitivities, b_means, '-bo')
     96         pylab.xlim([sens_range[0], sens_range[1]/2])
     97         pylab.ylim([0, 1])
     98         pylab.xlabel('sensitivity(ISO)')
     99         pylab.ylabel('RGB avg [0, 1]')
    100         matplotlib.pyplot.savefig('%s_plot_means.png' % (NAME))
    101 
    102         # Check that each plot is actually linear.
    103         for means in [r_means, g_means, b_means]:
    104             line, residuals, _, _, _ = numpy.polyfit(range(len(sensitivities)),
    105                                                      means, 1, full=True)
    106             print 'Line: m=%f, b=%f, resid=%f'%(line[0], line[1], residuals[0])
    107             assert residuals[0] < RESIDUAL_THRESHOLD
    108 
    109 if __name__ == '__main__':
    110     main()
    111 
    112