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"""Verifies settings latch on the correct frame.""" 15 16 17import logging 18import os.path 19import matplotlib 20from matplotlib import pylab 21from mobly import test_runner 22 23import its_base_test 24import camera_properties_utils 25import capture_request_utils 26import image_processing_utils 27import its_session_utils 28import target_exposure_utils 29 30_EXP_GAIN_FACTOR = 2 31_NAME = os.path.splitext(os.path.basename(__file__))[0] 32_PATCH_H = 0.1 # center 10% 33_PATCH_W = 0.1 34_PATCH_X = 0.5 - _PATCH_W/2 35_PATCH_Y = 0.5 - _PATCH_H/2 36_REQ_PATTERN = ['base', 'base', 'iso', 'iso', 'base', 'base', 'exp', 37 'base', 'iso', 'base', 'exp', 'base', 'exp', 'exp'] 38_PATTERN_CHECK = [r != 'base' for r in _REQ_PATTERN] 39 40 41class LatchingTest(its_base_test.ItsBaseTest): 42 """Test that settings latch on the right frame. 43 44 Takes a sequence of 14 shots using back-to-back requests, varying the capture 45 request gain and exp parameters between shots. Check images that come back 46 have the properties. 47 48 Pattern is described in EXP_GAIN_HIGH_PATTERN where False is NOM, True is High 49 """ 50 51 def test_latching(self): 52 logging.debug('Starting %s', _NAME) 53 with its_session_utils.ItsSession( 54 device_id=self.dut.serial, 55 camera_id=self.camera_id, 56 hidden_physical_id=self.hidden_physical_id) as cam: 57 props = cam.get_camera_properties() 58 props = cam.override_with_hidden_physical_camera_props(props) 59 log_path = self.log_path 60 name_with_log_path = os.path.join(log_path, _NAME) 61 62 # check SKIP conditions 63 camera_properties_utils.skip_unless( 64 camera_properties_utils.full_or_better(props)) 65 66 # Load chart for scene 67 its_session_utils.load_scene( 68 cam, props, self.scene, self.tablet, 69 its_session_utils.CHART_DISTANCE_NO_SCALING) 70 71 # Create requests, do captures and extract means for each image 72 _, fmt = capture_request_utils.get_fastest_manual_capture_settings(props) 73 e, s = target_exposure_utils.get_target_exposure_combos( 74 log_path, cam)['midExposureTime'] 75 76 e /= _EXP_GAIN_FACTOR 77 r_means = [] 78 g_means = [] 79 b_means = [] 80 reqs = [] 81 base_req = capture_request_utils.manual_capture_request( 82 s, e, 0.0, True, props) 83 iso_mult_req = capture_request_utils.manual_capture_request( 84 s * _EXP_GAIN_FACTOR, e, 0.0, True, props) 85 exp_mult_req = capture_request_utils.manual_capture_request( 86 s, e * _EXP_GAIN_FACTOR, 0.0, True, props) 87 for req_type in _REQ_PATTERN: 88 if req_type == 'base': 89 reqs.append(base_req) 90 elif req_type == 'exp': 91 reqs.append(exp_mult_req) 92 elif req_type == 'iso': 93 reqs.append(iso_mult_req) 94 else: 95 raise AssertionError(f'Incorrect capture request! {req_type}') 96 97 caps = cam.do_capture(reqs, fmt) 98 for i, cap in enumerate(caps): 99 img = image_processing_utils.convert_capture_to_rgb_image(cap) 100 image_processing_utils.write_image( 101 img, f'{name_with_log_path}_i={i:02d}.jpg') 102 patch = image_processing_utils.get_image_patch( 103 img, _PATCH_X, _PATCH_Y, _PATCH_W, _PATCH_H) 104 rgb_means = image_processing_utils.compute_image_means(patch) 105 r_means.append(rgb_means[0]) 106 g_means.append(rgb_means[1]) 107 b_means.append(rgb_means[2]) 108 logging.debug('G means: %s', str(g_means)) 109 110 # Plot results 111 idxs = range(len(r_means)) 112 pylab.figure(_NAME) 113 pylab.plot(idxs, r_means, '-ro') 114 pylab.plot(idxs, g_means, '-go') 115 pylab.plot(idxs, b_means, '-bo') 116 pylab.ylim([0, 1]) 117 pylab.title(_NAME) 118 pylab.xlabel('capture') 119 pylab.ylabel('RGB means') 120 matplotlib.pyplot.savefig(f'{name_with_log_path}_plot_means.png') 121 122 # check G mean pattern for correctness 123 g_avg_for_caps = sum(g_means) / len(g_means) 124 g_high = [g / g_avg_for_caps > 1 for g in g_means] 125 if g_high != _PATTERN_CHECK: 126 raise AssertionError(f'G means: {g_means}, TEMPLATE: {_REQ_PATTERN}') 127 128if __name__ == '__main__': 129 test_runner.main() 130 131