blob: 72c791d0902a4c30a554e9ddcce1c5150adbd2b4 [file] [log] [blame]
# Copyright 2014 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.
"""Verifies auto and manual captures are similar with same scene."""
import logging
import math
import os.path
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
AWB_AUTO_ATOL = 0.10
AWB_AUTO_RTOL = 0.25
AWB_MANUAL_ATOL = 0.05
NAME = os.path.splitext(os.path.basename(__file__))[0]
TONEMAP_GAMMA = sum([[t/63.0, math.pow(t/63.0, 1/2.2)] for t in range(64)], [])
def extract_awb_gains_and_xform(cap, cap_name, log_path):
"""Extract the AWB transform and gains, save image, and log info.
Args:
cap: camera capture
cap_name: text string to identify cap type
log_path: location to save images
Returns:
awb_gains, awb_xform
"""
img = image_processing_utils.convert_capture_to_rgb_image(cap)
image_processing_utils.write_image(img, '%s_%s.jpg' % (
os.path.join(log_path, NAME), cap_name))
awb_gains = cap['metadata']['android.colorCorrection.gains']
awb_xform = capture_request_utils.rational_to_float(
cap['metadata']['android.colorCorrection.transform'])
logging.debug('%s gains: %s', cap_name, str(awb_gains))
logging.debug('%s transform: %s', cap_name, str(awb_xform))
return awb_gains, awb_xform
class AutoVsManualTest(its_base_test.ItsBaseTest):
"""Capture auto and manual shots that should look the same.
Manual shots taken with just manual WB, and also with manual WB+tonemap.
In all cases, the general color/look of the shots should be the same,
however there can be variations in brightness/contrast due to different
'auto' ISP blocks that may be disabled in the manual flows.
"""
def test_auto_vs_manual(self):
logging.debug('Starting %s', NAME)
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)
mono_camera = camera_properties_utils.mono_camera(props)
log_path = self.log_path
# check SKIP conditions
camera_properties_utils.skip_unless(
camera_properties_utils.read_3a(props) and
camera_properties_utils.per_frame_control(props))
# Load chart for scene
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance)
# Converge 3A and get the estimates
largest_yuv = capture_request_utils.get_largest_yuv_format(props)
match_ar = (largest_yuv['width'], largest_yuv['height'])
fmt = capture_request_utils.get_smallest_yuv_format(
props, match_ar=match_ar)
s, e, awb_gains, awb_xform, fd = cam.do_3a(get_results=True,
mono_camera=mono_camera)
awb_xform_rat = capture_request_utils.float_to_rational(awb_xform)
logging.debug('AE sensitivity: %d, exposure: %dms', s, e/1000000.0)
logging.debug('AWB gains: %s', str(awb_gains))
logging.debug('AWB transform: %s', str(awb_xform))
logging.debug('AF distance: %.3f', fd)
# Auto capture
req = capture_request_utils.auto_capture_request()
cap_auto = cam.do_capture(req, fmt)
awb_gains_a, awb_xform_a = extract_awb_gains_and_xform(
cap_auto, 'auto', log_path)
# Manual capture 1: WB
req = capture_request_utils.manual_capture_request(s, e, fd)
req['android.colorCorrection.transform'] = awb_xform_rat
req['android.colorCorrection.gains'] = awb_gains
cap_man1 = cam.do_capture(req, fmt)
awb_gains_m1, awb_xform_m1 = extract_awb_gains_and_xform(
cap_man1, 'manual_wb', log_path)
# Manual capture 2: WB + tonemap
req['android.tonemap.mode'] = 0
req['android.tonemap.curve'] = {'red': TONEMAP_GAMMA,
'green': TONEMAP_GAMMA,
'blue': TONEMAP_GAMMA}
cap_man2 = cam.do_capture(req, fmt)
awb_gains_m2, awb_xform_m2 = extract_awb_gains_and_xform(
cap_man2, 'manual_wb_tm', log_path)
# Check AWB gains & transform in manual results match values from do_3a
for g, x in [(awb_gains_m1, awb_xform_m1), (awb_gains_m2, awb_xform_m2)]:
e_msg = 'awb_xform 3A: %s, manual: %s, ATOL=%.2f' % (
str(awb_xform), str(x), AWB_MANUAL_ATOL)
assert np.allclose(awb_xform, x, atol=AWB_MANUAL_ATOL, rtol=0), e_msg
e_msg = 'awb_gains 3A: %s, manual: %s, ATOL=%.2f' % (
str(awb_gains), str(g), AWB_MANUAL_ATOL)
assert np.allclose(awb_gains, g, atol=AWB_MANUAL_ATOL, rtol=0), e_msg
# Check AWB gains & transform in auto results match values from do_3a
e_msg = 'awb_xform 3A: %s, auto: %s, RTOL=%.2f, ATOL=%.2f' % (
str(awb_xform), str(awb_xform_a), AWB_AUTO_RTOL, AWB_AUTO_ATOL)
assert np.allclose(awb_xform_a, awb_xform, atol=AWB_AUTO_ATOL,
rtol=AWB_AUTO_RTOL), e_msg
e_msg = 'awb_gains 3A: %s, auto: %s, RTOL=%.2f, ATOL=%.2f' % (
str(awb_gains), str(awb_gains_a), AWB_AUTO_RTOL, AWB_AUTO_ATOL)
assert np.allclose(awb_gains_a, awb_gains, atol=AWB_AUTO_ATOL,
rtol=AWB_AUTO_RTOL), e_msg
if __name__ == '__main__':
test_runner.main()