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