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