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 os.path
     20 import numpy
     21 import matplotlib.pyplot
     22 
     23 # Required for 3d plot to work
     24 import mpl_toolkits.mplot3d
     25 
     26 def main():
     27     """Test that valid data comes back in CaptureResult objects.
     28     """
     29     global NAME, auto_req, manual_req, w_map, h_map
     30     global manual_tonemap, manual_transform, manual_gains, manual_region
     31     global manual_exp_time, manual_sensitivity, manual_gains_ok
     32 
     33     NAME = os.path.basename(__file__).split(".")[0]
     34 
     35     with its.device.ItsSession() as cam:
     36         props = cam.get_camera_properties()
     37         its.caps.skip_unless(its.caps.manual_sensor(props) and
     38                              its.caps.manual_post_proc(props) and
     39                              its.caps.per_frame_control(props))
     40 
     41         manual_tonemap = [0,0, 1,1] # Linear
     42         manual_transform = its.objects.int_to_rational([1,2,3, 4,5,6, 7,8,9])
     43         manual_gains = [1,2,3,4]
     44         manual_region = [{"x":8,"y":8,"width":128,"height":128,"weight":1}]
     45         manual_exp_time = min(props['android.sensor.info.exposureTimeRange'])
     46         manual_sensitivity = min(props['android.sensor.info.sensitivityRange'])
     47 
     48         # The camera HAL may not support different gains for two G channels.
     49         manual_gains_ok = [[1,2,3,4],[1,2,2,4],[1,3,3,4]]
     50 
     51         auto_req = its.objects.auto_capture_request()
     52         auto_req["android.statistics.lensShadingMapMode"] = 1
     53 
     54         manual_req = {
     55             "android.control.mode": 0,
     56             "android.control.aeMode": 0,
     57             "android.control.awbMode": 0,
     58             "android.control.afMode": 0,
     59             "android.sensor.frameDuration": 0,
     60             "android.sensor.sensitivity": manual_sensitivity,
     61             "android.sensor.exposureTime": manual_exp_time,
     62             "android.colorCorrection.mode": 0,
     63             "android.colorCorrection.transform": manual_transform,
     64             "android.colorCorrection.gains": manual_gains,
     65             "android.tonemap.mode": 0,
     66             "android.tonemap.curveRed": manual_tonemap,
     67             "android.tonemap.curveGreen": manual_tonemap,
     68             "android.tonemap.curveBlue": manual_tonemap,
     69             "android.control.aeRegions": manual_region,
     70             "android.control.afRegions": manual_region,
     71             "android.control.awbRegions": manual_region,
     72             "android.statistics.lensShadingMapMode":1
     73             }
     74 
     75         w_map = props["android.lens.info.shadingMapSize"]["width"]
     76         h_map = props["android.lens.info.shadingMapSize"]["height"]
     77 
     78         print "Testing auto capture results"
     79         lsc_map_auto = test_auto(cam, w_map, h_map)
     80         print "Testing manual capture results"
     81         test_manual(cam, w_map, h_map, lsc_map_auto)
     82         print "Testing auto capture results again"
     83         test_auto(cam, w_map, h_map)
     84 
     85 # A very loose definition for two floats being close to each other;
     86 # there may be different interpolation and rounding used to get the
     87 # two values, and all this test is looking at is whether there is
     88 # something obviously broken; it's not looking for a perfect match.
     89 def is_close_float(n1, n2):
     90     return abs(n1 - n2) < 0.05
     91 
     92 def is_close_rational(n1, n2):
     93     return is_close_float(its.objects.rational_to_float(n1),
     94                           its.objects.rational_to_float(n2))
     95 
     96 def draw_lsc_plot(w_map, h_map, lsc_map, name):
     97     for ch in range(4):
     98         fig = matplotlib.pyplot.figure()
     99         ax = fig.gca(projection='3d')
    100         xs = numpy.array([range(w_map)] * h_map).reshape(h_map, w_map)
    101         ys = numpy.array([[i]*w_map for i in range(h_map)]).reshape(
    102                 h_map, w_map)
    103         zs = numpy.array(lsc_map[ch::4]).reshape(h_map, w_map)
    104         ax.plot_wireframe(xs, ys, zs)
    105         matplotlib.pyplot.savefig("%s_plot_lsc_%s_ch%d.png"%(NAME,name,ch))
    106 
    107 def test_auto(cam, w_map, h_map):
    108     # Get 3A lock first, so the auto values in the capture result are
    109     # populated properly.
    110     rect = [[0,0,1,1,1]]
    111     cam.do_3a(rect, rect, rect, do_af=False)
    112 
    113     cap = cam.do_capture(auto_req)
    114     cap_res = cap["metadata"]
    115 
    116     gains = cap_res["android.colorCorrection.gains"]
    117     transform = cap_res["android.colorCorrection.transform"]
    118     exp_time = cap_res['android.sensor.exposureTime']
    119     lsc_map = cap_res["android.statistics.lensShadingMap"]
    120     ctrl_mode = cap_res["android.control.mode"]
    121 
    122     print "Control mode:", ctrl_mode
    123     print "Gains:", gains
    124     print "Transform:", [its.objects.rational_to_float(t)
    125                          for t in transform]
    126     print "AE region:", cap_res['android.control.aeRegions']
    127     print "AF region:", cap_res['android.control.afRegions']
    128     print "AWB region:", cap_res['android.control.awbRegions']
    129     print "LSC map:", w_map, h_map, lsc_map[:8]
    130 
    131     assert(ctrl_mode == 1)
    132 
    133     # Color correction gain and transform must be valid.
    134     assert(len(gains) == 4)
    135     assert(len(transform) == 9)
    136     assert(all([g > 0 for g in gains]))
    137     assert(all([t["denominator"] != 0 for t in transform]))
    138 
    139     # Color correction should not match the manual settings.
    140     assert(any([not is_close_float(gains[i], manual_gains[i])
    141                 for i in xrange(4)]))
    142     assert(any([not is_close_rational(transform[i], manual_transform[i])
    143                 for i in xrange(9)]))
    144 
    145     # Exposure time must be valid.
    146     assert(exp_time > 0)
    147 
    148     # Lens shading map must be valid.
    149     assert(w_map > 0 and h_map > 0 and w_map * h_map * 4 == len(lsc_map))
    150     assert(all([m >= 1 for m in lsc_map]))
    151 
    152     draw_lsc_plot(w_map, h_map, lsc_map, "auto")
    153 
    154     return lsc_map
    155 
    156 def test_manual(cam, w_map, h_map, lsc_map_auto):
    157     cap = cam.do_capture(manual_req)
    158     cap_res = cap["metadata"]
    159 
    160     gains = cap_res["android.colorCorrection.gains"]
    161     transform = cap_res["android.colorCorrection.transform"]
    162     curves = [cap_res["android.tonemap.curveRed"],
    163               cap_res["android.tonemap.curveGreen"],
    164               cap_res["android.tonemap.curveBlue"]]
    165     exp_time = cap_res['android.sensor.exposureTime']
    166     lsc_map = cap_res["android.statistics.lensShadingMap"]
    167     ctrl_mode = cap_res["android.control.mode"]
    168 
    169     print "Control mode:", ctrl_mode
    170     print "Gains:", gains
    171     print "Transform:", [its.objects.rational_to_float(t)
    172                          for t in transform]
    173     print "Tonemap:", curves[0][1::16]
    174     print "AE region:", cap_res['android.control.aeRegions']
    175     print "AF region:", cap_res['android.control.afRegions']
    176     print "AWB region:", cap_res['android.control.awbRegions']
    177     print "LSC map:", w_map, h_map, lsc_map[:8]
    178 
    179     assert(ctrl_mode == 0)
    180 
    181     # Color correction gain and transform must be valid.
    182     # Color correction gains and transform should be the same size and
    183     # values as the manually set values.
    184     assert(len(gains) == 4)
    185     assert(len(transform) == 9)
    186     assert( all([is_close_float(gains[i], manual_gains_ok[0][i])
    187                  for i in xrange(4)]) or
    188             all([is_close_float(gains[i], manual_gains_ok[1][i])
    189                  for i in xrange(4)]) or
    190             all([is_close_float(gains[i], manual_gains_ok[2][i])
    191                  for i in xrange(4)]))
    192     assert(all([is_close_rational(transform[i], manual_transform[i])
    193                 for i in xrange(9)]))
    194 
    195     # Tonemap must be valid.
    196     # The returned tonemap must be linear.
    197     for c in curves:
    198         assert(len(c) > 0)
    199         assert(all([is_close_float(c[i], c[i+1])
    200                     for i in xrange(0,len(c),2)]))
    201 
    202     # Exposure time must be close to the requested exposure time.
    203     assert(is_close_float(exp_time/1000000.0, manual_exp_time/1000000.0))
    204 
    205     # Lens shading map must be valid.
    206     assert(w_map > 0 and h_map > 0 and w_map * h_map * 4 == len(lsc_map))
    207     assert(all([m >= 1 for m in lsc_map]))
    208 
    209     draw_lsc_plot(w_map, h_map, lsc_map, "manual")
    210 
    211 if __name__ == '__main__':
    212     main()
    213 
    214