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 15 import its.image 16 import its.caps 17 import its.device 18 import its.objects 19 import its.target 20 import math 21 import matplotlib 22 import matplotlib.pyplot 23 import numpy 24 import os.path 25 import pylab 26 27 28 def 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 81 def 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 # If reprocessing is supported, ZSL EE mode must be avaiable. 105 assert(its.caps.edge_mode(props, 3)) 106 107 reprocess_formats = [] 108 if (its.caps.yuv_reprocess(props)): 109 reprocess_formats.append("yuv") 110 if (its.caps.private_reprocess(props)): 111 reprocess_formats.append("private") 112 113 size = its.objects.get_available_output_sizes("jpg", props)[0] 114 out_surface = {"width":size[0], "height":size[1], "format":"jpg"} 115 116 # Get proper sensitivity, exposure time, and focus distance. 117 s,e,_,_,fd = cam.do_3a(get_results=True) 118 119 # Get the sharpness for each edge mode for regular requests 120 sharpness_regular = [] 121 edge_mode_reported_regular = [] 122 for edge_mode in range(4): 123 # Skip unavailable modes 124 if not its.caps.edge_mode(props, edge_mode): 125 edge_mode_reported_regular.append(edge_mode) 126 sharpness_regular.append(0) 127 continue 128 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface) 129 edge_mode_reported_regular.append(ret["edge_mode"]) 130 sharpness_regular.append(ret["sharpness"]) 131 132 print "Reported edge modes:", edge_mode_reported_regular 133 print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular 134 135 # Get the sharpness for each reprocess format and edge mode for 136 # reprocess requests. 137 sharpnesses_reprocess = [] 138 edge_mode_reported_reprocess = [] 139 140 for reprocess_format in reprocess_formats: 141 # List of sharpness 142 sharpnesses = [] 143 edge_mode_reported = [] 144 for edge_mode in range(4): 145 # Skip unavailable modes 146 if not its.caps.edge_mode(props, edge_mode): 147 edge_mode_reported.append(edge_mode) 148 sharpnesses.append(0) 149 continue 150 151 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface, 152 reprocess_format) 153 edge_mode_reported.append(ret["edge_mode"]) 154 sharpnesses.append(ret["sharpness"]) 155 156 sharpnesses_reprocess.append(sharpnesses) 157 edge_mode_reported_reprocess.append(edge_mode_reported) 158 159 print "Reported edge modes:", edge_mode_reported 160 print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \ 161 (reprocess_format) , sharpnesses 162 163 164 # Verify HQ(2) is sharper than OFF(0) 165 assert(sharpness_regular[2] > sharpness_regular[0]) 166 167 # Verify ZSL(3) is similar to OFF(0) 168 assert(numpy.isclose(sharpness_regular[3], sharpness_regular[0], 169 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 170 171 # Verify OFF(0) is not sharper than FAST(1) 172 assert(sharpness_regular[1] > 173 sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 174 175 # Verify FAST(1) is not sharper than HQ(2) 176 assert(sharpness_regular[2] > 177 sharpness_regular[1] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 178 179 for reprocess_format in range(len(reprocess_formats)): 180 # Verify HQ(2) is sharper than OFF(0) 181 assert(sharpnesses_reprocess[reprocess_format][2] > 182 sharpnesses_reprocess[reprocess_format][0]) 183 184 # Verify ZSL(3) is similar to OFF(0) 185 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][3], 186 sharpnesses_reprocess[reprocess_format][0], 187 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 188 189 # Verify OFF(0) is not sharper than FAST(1) 190 assert(sharpnesses_reprocess[reprocess_format][1] > 191 sharpnesses_reprocess[reprocess_format][0] * 192 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 193 194 # Verify FAST(1) is not sharper than HQ(2) 195 assert(sharpnesses_reprocess[reprocess_format][2] > 196 sharpnesses_reprocess[reprocess_format][1] * 197 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 198 199 # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to 200 # OFF(0) 201 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] / 202 sharpnesses_reprocess[reprocess_format][0], 203 sharpness_regular[2] / sharpness_regular[0], 204 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 205 206 if __name__ == '__main__': 207 main() 208 209