1# Copyright 2015 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.caps 17import its.device 18import its.objects 19import its.target 20import math 21import matplotlib 22import matplotlib.pyplot 23import numpy 24import os.path 25from matplotlib import pylab 26 27 28def test_edge_mode(cam, edge_mode, sensitivity, exp, fd, out_surface, 29 reprocess_format=None): 30 """Return sharpness of the output image and the capture result metadata 31 for a capture request with the given edge mode, sensitivity, exposure 32 time, focus distance, output surface parameter, and reprocess format 33 (None for a regular request.) 34 35 Args: 36 cam: An open device session. 37 edge_mode: Edge mode for the request as defined in android.edge.mode 38 sensitivity: Sensitivity for the request as defined in 39 android.sensor.sensitivity 40 exp: Exposure time for the request as defined in 41 android.sensor.exposureTime. 42 fd: Focus distance for the request as defined in 43 android.lens.focusDistance 44 output_surface: Specifications of the output image format and size. 45 reprocess_format: (Optional) The reprocessing format. If not None, 46 reprocessing will be enabled. 47 48 Returns: 49 Object containing reported edge mode and the sharpness of the output 50 image, keyed by the following strings: 51 "edge_mode" 52 "sharpness" 53 """ 54 55 NAME = os.path.basename(__file__).split(".")[0] 56 NUM_SAMPLES = 4 57 58 req = its.objects.manual_capture_request(sensitivity, exp) 59 req["android.lens.focusDistance"] = fd 60 req["android.edge.mode"] = edge_mode 61 if (reprocess_format != None): 62 req["android.reprocess.effectiveExposureFactor"] = 1.0 63 64 sharpness_list = [] 65 for n in range(NUM_SAMPLES): 66 cap = cam.do_capture(req, out_surface, reprocess_format) 67 img = its.image.convert_capture_to_rgb_image(cap) 68 if n == 0: 69 its.image.write_image(img, "%s_reprocess_fmt_%s_edge=%d.jpg" % 70 (NAME, reprocess_format, edge_mode)) 71 res_edge_mode = cap["metadata"]["android.edge.mode"] 72 tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1) 73 sharpness_list.append(its.image.compute_image_sharpness(tile)) 74 75 ret = {} 76 ret["edge_mode"] = res_edge_mode 77 ret["sharpness"] = numpy.mean(sharpness_list) 78 79 return ret 80 81def main(): 82 """Test that the android.edge.mode param is applied when set for 83 reprocessing requests. 84 85 Capture non-reprocess images for each edge mode and calculate their 86 sharpness as a baseline. 87 88 Capture reprocessed images for each supported reprocess format and edge_mode 89 mode. Calculate the sharpness of reprocessed images and compare them against 90 the sharpess of non-reprocess images. 91 """ 92 93 THRESHOLD_RELATIVE_SHARPNESS_DIFF = 0.15 94 95 with its.device.ItsSession() as cam: 96 props = cam.get_camera_properties() 97 98 its.caps.skip_unless(its.caps.read_3a(props) and 99 its.caps.per_frame_control(props) and 100 its.caps.edge_mode(props, 0) and 101 (its.caps.yuv_reprocess(props) or 102 its.caps.private_reprocess(props))) 103 104 mono_camera = its.caps.mono_camera(props) 105 # If reprocessing is supported, ZSL EE mode must be avaiable. 106 assert(its.caps.edge_mode(props, 3)) 107 108 reprocess_formats = [] 109 if (its.caps.yuv_reprocess(props)): 110 reprocess_formats.append("yuv") 111 if (its.caps.private_reprocess(props)): 112 reprocess_formats.append("private") 113 114 size = its.objects.get_available_output_sizes("jpg", props)[0] 115 out_surface = {"width":size[0], "height":size[1], "format":"jpg"} 116 117 # Get proper sensitivity, exposure time, and focus distance. 118 s,e,_,_,fd = cam.do_3a(get_results=True, mono_camera=mono_camera) 119 120 # Get the sharpness for each edge mode for regular requests 121 sharpness_regular = [] 122 edge_mode_reported_regular = [] 123 for edge_mode in range(4): 124 # Skip unavailable modes 125 if not its.caps.edge_mode(props, edge_mode): 126 edge_mode_reported_regular.append(edge_mode) 127 sharpness_regular.append(0) 128 continue 129 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface) 130 edge_mode_reported_regular.append(ret["edge_mode"]) 131 sharpness_regular.append(ret["sharpness"]) 132 133 print "Reported edge modes:", edge_mode_reported_regular 134 print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular 135 136 # Get the sharpness for each reprocess format and edge mode for 137 # reprocess requests. 138 sharpnesses_reprocess = [] 139 edge_mode_reported_reprocess = [] 140 141 for reprocess_format in reprocess_formats: 142 # List of sharpness 143 sharpnesses = [] 144 edge_mode_reported = [] 145 for edge_mode in range(4): 146 # Skip unavailable modes 147 if not its.caps.edge_mode(props, edge_mode): 148 edge_mode_reported.append(edge_mode) 149 sharpnesses.append(0) 150 continue 151 152 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface, 153 reprocess_format) 154 edge_mode_reported.append(ret["edge_mode"]) 155 sharpnesses.append(ret["sharpness"]) 156 157 sharpnesses_reprocess.append(sharpnesses) 158 edge_mode_reported_reprocess.append(edge_mode_reported) 159 160 print "Reported edge modes:", edge_mode_reported 161 print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \ 162 (reprocess_format) , sharpnesses 163 164 165 # Verify HQ(2) is sharper than OFF(0) 166 assert(sharpness_regular[2] > sharpness_regular[0]) 167 168 # Verify ZSL(3) is similar to OFF(0) 169 assert(numpy.isclose(sharpness_regular[3], sharpness_regular[0], 170 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 171 172 # Verify OFF(0) is not sharper than FAST(1) 173 assert(sharpness_regular[1] > 174 sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 175 176 # Verify FAST(1) is not sharper than HQ(2) 177 assert(sharpness_regular[2] > 178 sharpness_regular[1] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 179 180 for reprocess_format in range(len(reprocess_formats)): 181 # Verify HQ(2) is sharper than OFF(0) 182 assert(sharpnesses_reprocess[reprocess_format][2] > 183 sharpnesses_reprocess[reprocess_format][0]) 184 185 # Verify ZSL(3) is similar to OFF(0) 186 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][3], 187 sharpnesses_reprocess[reprocess_format][0], 188 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 189 190 # Verify OFF(0) is not sharper than FAST(1) 191 assert(sharpnesses_reprocess[reprocess_format][1] > 192 sharpnesses_reprocess[reprocess_format][0] * 193 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 194 195 # Verify FAST(1) is not sharper than HQ(2) 196 assert(sharpnesses_reprocess[reprocess_format][2] > 197 sharpnesses_reprocess[reprocess_format][1] * 198 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 199 200 # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to 201 # OFF(0) 202 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] / 203 sharpnesses_reprocess[reprocess_format][0], 204 sharpness_regular[2] / sharpness_regular[0], 205 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 206 207if __name__ == '__main__': 208 main() 209 210