Home | History | Annotate | Download | only in scene0
      1 # Copyright 2018 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 
     15 import os
     16 
     17 import its.caps
     18 import its.device
     19 import its.image
     20 import its.objects
     21 import numpy as np
     22 
     23 NAME = os.path.basename(__file__).split('.')[0]
     24 PATTERN = 2  # Note scene0/test_test_patterns must PASS
     25 COLOR_BARS = ['WHITE', 'YELLOW', 'CYAN', 'GREEN', 'MAGENTA', 'RED',
     26               'BLUE', 'BLACK']
     27 COLOR_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]}
     30 DELTA = 0.0005  # crop on edge of color bars
     31 RAW_TOL = 0.001  # 1 DN in [0:1] (1/(1023-64)
     32 RGB_VAR_TOL = 0.0039  # 1/255
     33 RGB_MEAN_TOL = 0.1
     34 TONEMAP_MAX = 0.5
     35 
     36 
     37 def check_raw_pattern(img_raw):
     38     """Check for RAW capture matches color bar pattern.
     39 
     40     Args:
     41         img_raw: RAW image
     42     """
     43 
     44     print 'Checking RAW/PATTERN match'
     45     n_bars = len(COLOR_BARS)
     46     color_match = []
     47     for i in range(n_bars):
     48         print 'patch:', i,
     49         raw_patch = its.image.get_image_patch(
     50                 img_raw, float(i)/n_bars+DELTA, 0.0, 1.0/n_bars-2*DELTA, 1.0)
     51         raw_means = its.image.compute_image_means(raw_patch)
     52         for color in COLOR_BARS:
     53             if np.allclose(COLOR_CHECKER[color], raw_means, atol=RAW_TOL):
     54                 color_match.append(color)
     55                 print '%s' % color
     56     assert set(color_match) == set(COLOR_BARS), 'RAW does not have all colors'
     57 
     58 
     59 def check_yuv_vs_raw(img_raw, img_yuv):
     60     """Check for YUV vs RAW match in 8 patches.
     61 
     62     Check for correct values and color consistency
     63 
     64     Args:
     65         img_raw: RAW image
     66         img_yuv: YUV image
     67     """
     68 
     69     print 'Checking YUV/RAW match'
     70     n_bars = len(COLOR_BARS)
     71     color_match_errs = []
     72     color_variance_errs = []
     73     for i in range(n_bars):
     74         raw_patch = its.image.get_image_patch(
     75                 img_raw, float(i)/n_bars+DELTA, 0.0, 1.0/n_bars-2*DELTA, 1.0)
     76         yuv_patch = its.image.get_image_patch(
     77                 img_yuv, float(i)/n_bars+DELTA, 0.0, 1.0/n_bars-2*DELTA, 1.0)
     78         raw_means = np.array(its.image.compute_image_means(raw_patch))
     79         raw_vars = np.array(its.image.compute_image_variances(raw_patch))
     80         yuv_means = np.array(its.image.compute_image_means(yuv_patch))
     81         yuv_means /= TONEMAP_MAX  # Normalize to tonemap max
     82         yuv_vars = np.array(its.image.compute_image_variances(yuv_patch))
     83         if not np.allclose(raw_means, yuv_means, atol=RGB_MEAN_TOL):
     84             color_match_errs.append('RAW: %s, RGB(norm): %s, ATOL: %.2f' % (
     85                     str(raw_means), str(np.round(yuv_means, 3)), RGB_MEAN_TOL))
     86         if not np.allclose(raw_vars, yuv_vars, atol=RGB_VAR_TOL):
     87             color_variance_errs.append('RAW: %s, RGB: %s, ATOL: %.4f' % (
     88                     str(raw_vars), str(yuv_vars), RGB_VAR_TOL))
     89     if color_match_errs:
     90         print '\nColor match errors'
     91         for err in color_match_errs:
     92             print err
     93     if color_variance_errs:
     94         print '\nColor variance errors'
     95         for err in color_variance_errs:
     96             print err
     97     assert not color_match_errs
     98     assert not color_variance_errs
     99 
    100 
    101 def test_tonemap_curve(cam, props):
    102     """test tonemap curve with sensor test pattern.
    103 
    104     Args:
    105         cam: An open device session.
    106         props: Properties of cam
    107     """
    108 
    109     avail_patterns = props['android.sensor.availableTestPatternModes']
    110     print 'avail_patterns: ', avail_patterns
    111     sens_min, _ = props['android.sensor.info.sensitivityRange']
    112     exp = min(props['android.sensor.info.exposureTimeRange'])
    113 
    114     # Linear tonemap with maximum of 0.5
    115     tmap = sum([[i/63.0, i/126.0] for i in range(64)], [])
    116 
    117     if PATTERN in avail_patterns:
    118         # RAW image
    119         req_raw = its.objects.manual_capture_request(int(sens_min), exp)
    120         req_raw['android.sensor.testPatternMode'] = PATTERN
    121         fmt_raw = {'format': 'raw'}
    122         cap_raw = cam.do_capture(req_raw, fmt_raw)
    123         img_raw = its.image.convert_capture_to_rgb_image(
    124                 cap_raw, props=props)
    125 
    126         # Save RAW pattern
    127         its.image.write_image(img_raw, '%s_raw_%d.jpg' % (
    128                 NAME, PATTERN), True)
    129         check_raw_pattern(img_raw)
    130 
    131         # YUV image
    132         req_yuv = its.objects.manual_capture_request(int(sens_min), exp)
    133         req_yuv['android.sensor.testPatternMode'] = PATTERN
    134         req_yuv['android.distortionCorrection.mode'] = 0
    135         req_yuv['android.tonemap.mode'] = 0
    136         req_yuv['android.tonemap.curve'] = {
    137                 'red': tmap, 'green': tmap, 'blue': tmap}
    138         fmt_yuv = {'format': 'yuv', 'width': 640, 'height': 480}
    139         cap_yuv = cam.do_capture(req_yuv, fmt_yuv)
    140         img_yuv = its.image.convert_capture_to_rgb_image(cap_yuv, True)
    141 
    142         # Save YUV pattern
    143         its.image.write_image(img_yuv, '%s_yuv_%d.jpg' % (
    144                 NAME, PATTERN), True)
    145 
    146         # Check pattern for correctness
    147         check_yuv_vs_raw(img_raw, img_yuv)
    148     else:
    149         print 'Pattern not in android.sensor.availableTestPatternModes.'
    150         assert 0
    151 
    152 
    153 def main():
    154     """Test conversion of test pattern from RAW to YUV.
    155 
    156     android.sensor.testPatternMode
    157     2: COLOR_BARS
    158     """
    159 
    160     print '\nStarting %s' % NAME
    161     with its.device.ItsSession() as cam:
    162         props = cam.get_camera_properties()
    163         its.caps.skip_unless(its.caps.raw16(props) and
    164                              its.caps.manual_sensor(props) and
    165                              its.caps.per_frame_control(props) and
    166                              its.caps.manual_post_proc(props))
    167 
    168         test_tonemap_curve(cam, props)
    169 
    170 if __name__ == '__main__':
    171     main()
    172