# Copyright 2024 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. """Tool to check camera alignment to test chart.""" import logging import os.path import capture_request_utils import image_processing_utils import its_base_test import its_session_utils from mobly import test_runner import opencv_processing_utils _CIRCLE_COLOR = 0 # [0: black, 255: white] _CIRCLE_MIN_AREA = 0.01 # 1% of image size _FMT = 'JPEG' _NAME = os.path.basename(__file__).split('.')[0] _SCENE = 'scene4' # Using scene with circle def _circle_and_image_center_offset(cam, props, name_with_log_path): """Find offset between circle center and image center. Args: cam: its_session_utils.ItsSession object props: camera properties object name_with_log_path: path to saved data Returns: x_offset: circle center's x-position vs. image center y_offset: circle center's y-position vs. image center """ # Take a single JPEG capture logging.debug('Using %s for reference', _FMT) fmt = capture_request_utils.get_largest_format('jpeg', props) req = capture_request_utils.auto_capture_request() cap = cam.do_capture(req, fmt) logging.debug('Captured %s %dx%d', _FMT, cap['width'], cap['height']) img = image_processing_utils.convert_capture_to_rgb_image(cap, props) size = (cap['height'], cap['width']) # Get image size w = size[1] h = size[0] img_name = f'{name_with_log_path}_{_FMT}_w{w}_h{h}.png' image_processing_utils.write_image(img, img_name, True) # Find circle. img *= 255 # cv2 needs images between [0,255] circle = opencv_processing_utils.find_circle( img, img_name, _CIRCLE_MIN_AREA, _CIRCLE_COLOR) opencv_processing_utils.append_circle_center_to_img(circle, img, img_name) # Determine final return values. x_offset, y_offset = circle['x_offset'], circle['y_offset'] return x_offset, y_offset class CheckAlignmentTest(its_base_test.ItsBaseTest): """Create a single capture that checks for scene center vs. circle center. """ def test_check_alignment(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) name_with_log_path = os.path.join(self.log_path, _NAME) logging.info('Starting %s for camera %s', _NAME, cam.get_camera_name()) # Load chart for scene its_session_utils.copy_scenes_to_tablet(_SCENE, self.tablet.serial) its_session_utils.load_scene( cam, props, _SCENE, self.tablet, self.chart_distance) # Find offset between circle center and image center x_offset, y_offset = _circle_and_image_center_offset( cam, props, name_with_log_path) logging.info('Circle center position wrt to image center: %.3fx%.3f', x_offset, y_offset) if __name__ == '__main__': test_runner.main()