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 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 216if __name__ == '__main__': 217 main() 218 219