blob: b953f4eff9b780d9c99475eccd47aa7a26746a12 [file] [log] [blame]
# Copyright 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""CameraITS test to check solid color test pattern generation."""
import logging
import os
from mobly import test_runner
import numpy as np
import its_base_test
import camera_properties_utils
import capture_request_utils
import image_processing_utils
import its_session_utils
_CH_TOL = 4E-3 # ~1/255 DN in [0:1]
_OFF = 0x00000000
_SAT = 0xFFFFFFFF
_NAME = os.path.basename(__file__).split('.')[0]
_SHARPNESS_TOL = 0.1
_NUM_FRAMES = 4 # buffer a few frames to eliminate need for PER_FRAME_CONTROL
# frozendict not used below as it requires import on host after port to AOSP
_BLACK = {'color': 'BLACK', 'RGGB': (_OFF, _OFF, _OFF, _OFF), 'RGB': (0, 0, 0)}
_WHITE = {'color': 'WHITE', 'RGGB': (_SAT, _SAT, _SAT, _SAT), 'RGB': (1, 1, 1)}
_RED = {'color': 'RED', 'RGGB': (_SAT, _OFF, _OFF, _OFF), 'RGB': (1, 0, 0)}
_GREEN = {'color': 'GREEN', 'RGGB': (_OFF, _SAT, _SAT, _OFF), 'RGB': (0, 1, 0)}
_BLUE = {'color': 'BLUE', 'RGGB': (_OFF, _OFF, _OFF, _SAT), 'RGB': (0, 0, 1)}
_COLORS_CHECKED_RGB = (_BLACK, _WHITE, _RED, _GREEN, _BLUE)
_COLORS_CHECKED_MONO = (_BLACK, _WHITE)
_COLORS_CHECKED_UPGRADE = (_BLACK,)
_FULL_CHECK_FIRST_API_LEVEL = 31
_SOLID_COLOR_TEST_PATTERN = 1
def check_solid_color(img, exp_values):
"""Checks solid color test pattern image matches expected values.
Args:
img: capture converted to RGB image
exp_values: list of RGB [0:1] expected values
"""
logging.debug('Checking solid test pattern w/ RGB values %s', str(exp_values))
rgb_means = image_processing_utils.compute_image_means(img)
logging.debug('Captured frame averages: %s', str(rgb_means))
rgb_vars = image_processing_utils.compute_image_variances(img)
logging.debug('Capture frame variances: %s', str(rgb_vars))
if not np.allclose(rgb_means, exp_values, atol=_CH_TOL):
raise AssertionError('Image not expected value. '
f'RGB means: {rgb_means}, expected: {exp_values}, '
f'ATOL: {_CH_TOL}')
if not all(i < _CH_TOL for i in rgb_vars):
raise AssertionError(f'Image has too much variance. '
f'RGB variances: {rgb_vars}, ATOL: {_CH_TOL}')
class SolidColorTestPattern(its_base_test.ItsBaseTest):
"""Solid Color test pattern generation test.
Test: Capture frame for the SOLID_COLOR test pattern with the values set
and check YUV image matches request.
android.sensor.testPatternMode
0: OFF
1: SOLID_COLOR
2: COLOR_BARS
3: COLOR_BARS_FADE_TO_GREY
4: PN9
"""
def test_solid_color_test_pattern(self):
with its_session_utils.ItsSession(
device_id=self.dut.serial,
camera_id=self.camera_id,
hidden_physical_id=self.hidden_physical_id) as cam:
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
# Determine patterns to check based on API level
first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
if first_api_level >= _FULL_CHECK_FIRST_API_LEVEL:
if camera_properties_utils.mono_camera(props):
colors_checked = _COLORS_CHECKED_MONO
else:
colors_checked = _COLORS_CHECKED_RGB
else:
colors_checked = _COLORS_CHECKED_UPGRADE
# Determine if test is run or skipped
available_patterns = props['android.sensor.availableTestPatternModes']
if cam.is_camera_privacy_mode_supported():
if _SOLID_COLOR_TEST_PATTERN not in available_patterns:
raise AssertionError(
'SOLID_COLOR not in android.sensor.availableTestPatternModes.')
else:
camera_properties_utils.skip_unless(
_SOLID_COLOR_TEST_PATTERN in available_patterns)
# Take extra frames if no per-frame control
if camera_properties_utils.per_frame_control(props):
num_frames = 1
else:
num_frames = _NUM_FRAMES
# Start checking patterns
for color in colors_checked:
logging.debug('Assigned RGGB values %s',
str([int(c/_SAT) for c in color['RGGB']]))
req = capture_request_utils.auto_capture_request()
req['android.sensor.testPatternMode'] = camera_properties_utils.SOLID_COLOR_TEST_PATTERN
req['android.sensor.testPatternData'] = color['RGGB']
fmt = {'format': 'yuv'}
caps = cam.do_capture([req]*num_frames, fmt)
cap = caps[-1]
logging.debug('Capture metadata RGGB testPatternData: %s',
str(cap['metadata']['android.sensor.testPatternData']))
# Save test pattern image
img = image_processing_utils.convert_capture_to_rgb_image(
cap, props=props)
image_processing_utils.write_image(
img, f'{os.path.join(self.log_path, _NAME)}.jpg', True)
# Check solid pattern for correctness
check_solid_color(img, color['RGB'])
logging.debug('Solid color test pattern %s is a PASS', color['color'])
if __name__ == '__main__':
test_runner.main()