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 25import 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 57 req = its.objects.manual_capture_request(sensitivity, exp) 58 req["android.lens.focusDistance"] = fd 59 req["android.edge.mode"] = edge_mode 60 if (reprocess_format != None): 61 req["android.reprocess.effectiveExposureFactor"] = 1.0 62 cap = cam.do_capture(req, out_surface, reprocess_format) 63 64 img = its.image.decompress_jpeg_to_rgb_image(cap["data"]) 65 its.image.write_image(img, "%s_edge=%d_reprocess_fmt_%s.jpg" % 66 (NAME, edge_mode, reprocess_format)) 67 tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1) 68 69 ret = {} 70 ret["edge_mode"] = cap["metadata"]["android.edge.mode"] 71 ret["sharpness"] = its.image.compute_image_sharpness(tile) 72 73 return ret 74 75def main(): 76 """Test that the android.edge.mode param is applied when set for 77 reprocessing requests. 78 79 Capture non-reprocess images for each edge mode and calculate their 80 sharpness as a baseline. 81 82 Capture reprocessed images for each supported reprocess format and edge_mode 83 mode. Calculate the sharpness of reprocessed images and compare them against 84 the sharpess of non-reprocess images. 85 """ 86 87 THRESHOLD_RELATIVE_SHARPNESS_DIFF = 0.1 88 89 with its.device.ItsSession() as cam: 90 props = cam.get_camera_properties() 91 92 its.caps.skip_unless(its.caps.read_3a(props) and 93 its.caps.per_frame_control(props) and 94 its.caps.edge_mode(props, 0) and 95 (its.caps.yuv_reprocess(props) or 96 its.caps.private_reprocess(props))) 97 98 # If reprocessing is supported, ZSL EE mode must be avaiable. 99 assert(its.caps.edge_mode(props, 3)) 100 101 reprocess_formats = [] 102 if (its.caps.yuv_reprocess(props)): 103 reprocess_formats.append("yuv") 104 if (its.caps.private_reprocess(props)): 105 reprocess_formats.append("private") 106 107 size = its.objects.get_available_output_sizes("jpg", props)[0] 108 out_surface = {"width":size[0], "height":size[1], "format":"jpg"} 109 110 # Get proper sensitivity, exposure time, and focus distance. 111 s,e,_,_,fd = cam.do_3a(get_results=True) 112 113 # Get the sharpness for each edge mode for regular requests 114 sharpness_regular = [] 115 edge_mode_reported_regular = [] 116 for edge_mode in range(4): 117 # Skip unavailable modes 118 if not its.caps.edge_mode(props, edge_mode): 119 edge_mode_reported_regular.append(edge_mode) 120 sharpness_regular.append(0) 121 continue 122 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface) 123 edge_mode_reported_regular.append(ret["edge_mode"]) 124 sharpness_regular.append(ret["sharpness"]) 125 126 print "Reported edge modes:", edge_mode_reported_regular 127 print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular 128 129 # Get the sharpness for each reprocess format and edge mode for 130 # reprocess requests. 131 sharpnesses_reprocess = [] 132 edge_mode_reported_reprocess = [] 133 134 for reprocess_format in reprocess_formats: 135 # List of sharpness 136 sharpnesses = [] 137 edge_mode_reported = [] 138 for edge_mode in range(4): 139 # Skip unavailable modes 140 if not its.caps.edge_mode(props, edge_mode): 141 edge_mode_reported.append(edge_mode) 142 sharpnesses.append(0) 143 continue 144 145 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface, 146 reprocess_format) 147 edge_mode_reported.append(ret["edge_mode"]) 148 sharpnesses.append(ret["sharpness"]) 149 150 sharpnesses_reprocess.append(sharpnesses) 151 edge_mode_reported_reprocess.append(edge_mode_reported) 152 153 print "Reported edge modes:", edge_mode_reported 154 print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \ 155 (reprocess_format) , sharpnesses 156 157 158 # Verify HQ(2) is sharper than OFF(0) 159 assert(sharpness_regular[2] > sharpness_regular[0]) 160 161 # Verify ZSL(3) is similar to OFF(0) 162 assert(numpy.isclose(sharpness_regular[3], sharpness_regular[0], 163 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 164 165 # Verify OFF(0) is not sharper than FAST(1) 166 assert(sharpness_regular[1] > 167 sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 168 169 # Verify FAST(1) is not sharper than HQ(2) 170 assert(sharpness_regular[2] > 171 sharpness_regular[1] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 172 173 for reprocess_format in range(len(reprocess_formats)): 174 # Verify HQ(2) is sharper than OFF(0) 175 assert(sharpnesses_reprocess[reprocess_format][2] > 176 sharpnesses_reprocess[reprocess_format][0]) 177 178 # Verify ZSL(3) is similar to OFF(0) 179 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][3], 180 sharpnesses_reprocess[reprocess_format][0], 181 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 182 183 # Verify OFF(0) is not sharper than FAST(1) 184 assert(sharpnesses_reprocess[reprocess_format][1] > 185 sharpnesses_reprocess[reprocess_format][0] * 186 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 187 188 # Verify FAST(1) is not sharper than HQ(2) 189 assert(sharpnesses_reprocess[reprocess_format][2] > 190 sharpnesses_reprocess[reprocess_format][1] * 191 (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 192 193 # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to 194 # OFF(0) 195 assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] / 196 sharpnesses_reprocess[reprocess_format][0], 197 sharpness_regular[2] / sharpness_regular[0], 198 THRESHOLD_RELATIVE_SHARPNESS_DIFF)) 199 200if __name__ == '__main__': 201 main() 202 203