Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 1 | # Copyright 2014 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. |
Clemenz Portmann | 4a73274 | 2021-03-22 13:41:42 -0700 | [diff] [blame] | 14 | """Verifies manual burst capture consistency.""" |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 15 | |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 16 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 17 | import logging |
| 18 | import os.path |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 19 | from matplotlib import pylab |
| 20 | import matplotlib.pyplot |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 21 | from mobly import test_runner |
| 22 | import numpy as np |
| 23 | |
| 24 | import its_base_test |
| 25 | import camera_properties_utils |
| 26 | import capture_request_utils |
| 27 | import image_processing_utils |
| 28 | import its_session_utils |
| 29 | import target_exposure_utils |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 30 | |
Clemenz Portmann | 1d5fab5 | 2019-11-14 10:51:26 -0800 | [diff] [blame] | 31 | API_LEVEL_30 = 30 |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 32 | BURST_LEN = 50 |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 33 | COLORS = ['R', 'G', 'B'] |
| 34 | NAME = os.path.splitext(os.path.basename(__file__))[0] |
| 35 | NUM_BURSTS = 5 |
| 36 | PATCH_H = 0.1 # center 10% |
| 37 | PATCH_W = 0.1 |
| 38 | PATCH_X = 0.5 - PATCH_W/2 |
| 39 | PATCH_Y = 0.5 - PATCH_H/2 |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 40 | SPREAD_THRESH = 0.03 |
Clemenz Portmann | 1d5fab5 | 2019-11-14 10:51:26 -0800 | [diff] [blame] | 41 | SPREAD_THRESH_API_LEVEL_30 = 0.02 |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 42 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 43 | NUM_FRAMES = BURST_LEN * NUM_BURSTS |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 44 | |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 45 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 46 | class BurstSamenessManualTest(its_base_test.ItsBaseTest): |
| 47 | """Take long bursts of images and check that they're all identical. |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 48 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 49 | Assumes a static scene. Can be used to idenfity if there are sporadic |
| 50 | frames that are processed differently or have artifacts. Uses manual |
| 51 | capture settings. |
| 52 | """ |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 53 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 54 | def test_burst_sameness_manual(self): |
| 55 | logging.debug('Starting %s', NAME) |
| 56 | with its_session_utils.ItsSession( |
| 57 | device_id=self.dut.serial, |
| 58 | camera_id=self.camera_id, |
| 59 | hidden_physical_id=self.hidden_physical_id) as cam: |
| 60 | props = cam.get_camera_properties() |
| 61 | props = cam.override_with_hidden_physical_camera_props(props) |
| 62 | log_path = self.log_path |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 63 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 64 | # check SKIP conditions |
| 65 | camera_properties_utils.skip_unless( |
| 66 | camera_properties_utils.compute_target_exposure(props) and |
| 67 | camera_properties_utils.per_frame_control(props)) |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 68 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 69 | # Load chart for scene |
| 70 | its_session_utils.load_scene( |
| 71 | cam, props, self.scene, self.tablet, self.chart_distance) |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 72 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 73 | # Capture at the smallest resolution |
| 74 | _, fmt = capture_request_utils.get_fastest_manual_capture_settings(props) |
| 75 | e, s = target_exposure_utils.get_target_exposure_combos( |
| 76 | log_path, cam)['minSensitivity'] |
| 77 | req = capture_request_utils.manual_capture_request(s, e) |
| 78 | w, h = fmt['width'], fmt['height'] |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 79 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 80 | # Capture bursts of YUV shots. |
| 81 | # Get the mean values of a center patch for each. |
| 82 | # Also build a 4D array, imgs, which is an array of all RGB images. |
| 83 | r_means = [] |
| 84 | g_means = [] |
| 85 | b_means = [] |
| 86 | imgs = np.empty([NUM_FRAMES, h, w, 3]) |
| 87 | for j in range(NUM_BURSTS): |
| 88 | caps = cam.do_capture([req]*BURST_LEN, [fmt]) |
| 89 | for i, cap in enumerate(caps): |
| 90 | n = j*BURST_LEN + i |
| 91 | imgs[n] = image_processing_utils.convert_capture_to_rgb_image(cap) |
| 92 | patch = image_processing_utils.get_image_patch( |
| 93 | imgs[n], PATCH_X, PATCH_Y, PATCH_W, PATCH_H) |
| 94 | means = image_processing_utils.compute_image_means(patch) |
| 95 | r_means.append(means[0]) |
| 96 | g_means.append(means[1]) |
| 97 | b_means.append(means[2]) |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 98 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 99 | # Save first frame for setup debug |
| 100 | image_processing_utils.write_image( |
| 101 | imgs[0], '%s_frame000.jpg' % os.path.join(log_path, NAME)) |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 102 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 103 | # Save all frames if debug |
| 104 | if self.debug_mode: |
| 105 | logging.debug('Dumping all images') |
| 106 | for i in range(1, NUM_FRAMES): |
| 107 | image_processing_utils.write_image( |
| 108 | imgs[i], '%s_frame%03d.jpg'%(os.path.join(log_path, NAME), i)) |
Clemenz Portmann | 1d5fab5 | 2019-11-14 10:51:26 -0800 | [diff] [blame] | 109 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 110 | # Plot RGB means vs frames |
| 111 | frames = range(NUM_FRAMES) |
| 112 | pylab.figure(NAME) |
| 113 | pylab.title(NAME) |
| 114 | pylab.plot(frames, r_means, '-ro') |
| 115 | pylab.plot(frames, g_means, '-go') |
| 116 | pylab.plot(frames, b_means, '-bo') |
| 117 | pylab.ylim([0, 1]) |
| 118 | pylab.xlabel('frame number') |
| 119 | pylab.ylabel('RGB avg [0, 1]') |
| 120 | matplotlib.pyplot.savefig( |
| 121 | '%s_plot_means.png' % os.path.join(log_path, NAME)) |
Clemenz Portmann | f76f9ab | 2018-07-18 13:11:54 -0700 | [diff] [blame] | 122 | |
Clemenz Portmann | 6816c02 | 2021-03-01 13:00:12 -0800 | [diff] [blame] | 123 | # determine spread_thresh |
| 124 | spread_thresh = SPREAD_THRESH |
| 125 | if its_session_utils.get_first_api_level(self.dut.serial) >= API_LEVEL_30: |
| 126 | spread_thresh = SPREAD_THRESH_API_LEVEL_30 |
| 127 | |
| 128 | # PASS/FAIL based on center patch similarity. |
| 129 | for plane, means in enumerate([r_means, g_means, b_means]): |
| 130 | spread = max(means) - min(means) |
| 131 | msg = '%s spread: %.5f, spread_thresh: %.2f' % ( |
| 132 | COLORS[plane], spread, spread_thresh) |
| 133 | logging.debug('%s', msg) |
| 134 | assert spread < spread_thresh, msg |
| 135 | |
| 136 | if __name__ == '__main__': |
| 137 | test_runner.main() |
Ruben Brunk | 370e243 | 2014-10-14 18:33:23 -0700 | [diff] [blame] | 138 | |