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