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