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 15import os 16 17import its.caps 18import its.device 19import its.image 20import its.objects 21import numpy as np 22 23NAME = os.path.basename(__file__).split('.')[0] 24PATTERNS = [1, 2] 25COLOR_BAR_ORDER = ['WHITE', 'YELLOW', 'CYAN', 'GREEN', 'MAGENTA', 'RED', 26 'BLUE', 'BLACK'] 27COLOR_CHECKER = {'BLACK': [0, 0, 0], 'RED': [1, 0, 0], 'GREEN': [0, 1, 0], 28 'BLUE': [0, 0, 1], 'MAGENTA': [1, 0, 1], 'CYAN': [0, 1, 1], 29 'YELLOW': [1, 1, 0], 'WHITE': [1, 1, 1]} 30CH_TOL = 2E-3 # 1/2 DN in [0:1] 31LSFR_COEFFS = 0b100010000 # PN9 32 33 34def check_solid_color(cap, props): 35 """Simple test for solid color. 36 37 Args: 38 cap: capture element 39 props: capture properties 40 Returns: 41 True/False 42 """ 43 print 'Checking solid TestPattern...' 44 r, gr, gb, b = its.image.convert_capture_to_planes(cap, props) 45 r_tile = its.image.get_image_patch(r, 0.0, 0.0, 1.0, 1.0) 46 gr_tile = its.image.get_image_patch(gr, 0.0, 0.0, 1.0, 1.0) 47 gb_tile = its.image.get_image_patch(gb, 0.0, 0.0, 1.0, 1.0) 48 b_tile = its.image.get_image_patch(b, 0.0, 0.0, 1.0, 1.0) 49 var_max = max(np.amax(r_tile), np.amax(gr_tile), np.amax(gb_tile), 50 np.amax(b_tile)) 51 var_min = min(np.amin(r_tile), np.amin(gr_tile), np.amin(gb_tile), 52 np.amin(b_tile)) 53 white_level = int(props['android.sensor.info.whiteLevel']) 54 print ' pixel min: %.f, pixel max: %.f' % (white_level*var_min, 55 white_level*var_max) 56 return np.isclose(var_max, var_min, atol=CH_TOL) 57 58 59def check_color_bars(cap, props, mirror=False): 60 """Test image for color bars. 61 62 Compute avg of bars and compare to ideal 63 64 Args: 65 cap: capture element 66 props: capture properties 67 mirror (bool): whether to mirror image or not 68 Returns: 69 True/False 70 """ 71 print 'Checking color bar TestPattern...' 72 delta = 0.0005 73 num_bars = len(COLOR_BAR_ORDER) 74 color_match = [] 75 img = its.image.convert_capture_to_rgb_image(cap, props=props) 76 if mirror: 77 print ' Image mirrored' 78 img = np.fliplr(img) 79 for i, color in enumerate(COLOR_BAR_ORDER): 80 tile = its.image.get_image_patch(img, float(i)/num_bars+delta, 81 0.0, 1.0/num_bars-2*delta, 1.0) 82 color_match.append(np.allclose(its.image.compute_image_means(tile), 83 COLOR_CHECKER[color], atol=CH_TOL)) 84 print COLOR_BAR_ORDER 85 print color_match 86 return all(color_match) 87 88 89def check_pattern(cap, props, pattern): 90 """Simple tests for pattern correctness. 91 92 Args: 93 cap: capture element 94 props: capture properties 95 pattern (int): valid number for pattern 96 Returns: 97 boolean 98 """ 99 100 # white_level = int(props['android.sensor.info.whiteLevel']) 101 if pattern == 1: # solid color 102 return check_solid_color(cap, props) 103 104 elif pattern == 2: # color bars 105 striped = check_color_bars(cap, props, mirror=False) 106 # check mirrored version in case image rotated from sensor orientation 107 if not striped: 108 striped = check_color_bars(cap, props, mirror=True) 109 return striped 110 111 else: 112 print 'No specific test for TestPattern %d' % pattern 113 return True 114 115 116def test_test_patterns(cam, props, af_fd): 117 """test image sensor test patterns. 118 119 Args: 120 cam: An open device session. 121 props: Properties of cam 122 af_fd: Focus distance 123 """ 124 125 avail_patterns = props['android.sensor.availableTestPatternModes'] 126 print 'avail_patterns: ', avail_patterns 127 sens_min, _ = props['android.sensor.info.sensitivityRange'] 128 exposure = min(props['android.sensor.info.exposureTimeRange']) 129 130 for pattern in PATTERNS: 131 if pattern in avail_patterns: 132 req = its.objects.manual_capture_request(int(sens_min), 133 exposure) 134 req['android.lens.focusDistance'] = af_fd 135 req['android.sensor.testPatternMode'] = pattern 136 fmt = {'format': 'raw'} 137 cap = cam.do_capture(req, fmt) 138 img = its.image.convert_capture_to_rgb_image(cap, props=props) 139 140 # Save pattern 141 its.image.write_image(img, '%s_%d.jpg' % (NAME, pattern), True) 142 143 # Check pattern for correctness 144 assert check_pattern(cap, props, pattern) 145 else: 146 print 'Pattern not in android.sensor.availableTestPatternModes.' 147 148 149def main(): 150 """Test pattern generation test. 151 152 Test: capture frames for each valid test pattern and check if 153 generated correctly. 154 android.sensor.testPatternMode 155 0: OFF 156 1: SOLID_COLOR 157 2: COLOR_BARS 158 3: COLOR_BARS_FADE_TO_GREY 159 4: PN9 160 """ 161 162 print '\nStarting %s' % NAME 163 with its.device.ItsSession() as cam: 164 props = cam.get_camera_properties() 165 its.caps.skip_unless(its.caps.raw16(props) and 166 its.caps.manual_sensor(props) and 167 its.caps.per_frame_control(props)) 168 169 # For test pattern, use min_fd 170 fd = props['android.lens.info.minimumFocusDistance'] 171 test_test_patterns(cam, props, fd) 172 173if __name__ == '__main__': 174 main() 175