xref: /aosp_15_r20/cts/apps/CameraITS/utils/image_fov_utils.py (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1*b7c941bbSAndroid Build Coastguard Worker# Copyright 2022 The Android Open Source Project
2*b7c941bbSAndroid Build Coastguard Worker#
3*b7c941bbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*b7c941bbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*b7c941bbSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*b7c941bbSAndroid Build Coastguard Worker#
7*b7c941bbSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*b7c941bbSAndroid Build Coastguard Worker#
9*b7c941bbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*b7c941bbSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*b7c941bbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*b7c941bbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*b7c941bbSAndroid Build Coastguard Worker# limitations under the License.
14*b7c941bbSAndroid Build Coastguard Worker"""Image Field-of-View utilities for aspect ratio, crop, and FoV tests."""
15*b7c941bbSAndroid Build Coastguard Worker
16*b7c941bbSAndroid Build Coastguard Worker
17*b7c941bbSAndroid Build Coastguard Workerimport logging
18*b7c941bbSAndroid Build Coastguard Workerimport math
19*b7c941bbSAndroid Build Coastguard Worker
20*b7c941bbSAndroid Build Coastguard Workerimport cv2
21*b7c941bbSAndroid Build Coastguard Workerimport numpy as np
22*b7c941bbSAndroid Build Coastguard Worker
23*b7c941bbSAndroid Build Coastguard Workerimport camera_properties_utils
24*b7c941bbSAndroid Build Coastguard Workerimport capture_request_utils
25*b7c941bbSAndroid Build Coastguard Workerimport image_processing_utils
26*b7c941bbSAndroid Build Coastguard Workerimport opencv_processing_utils
27*b7c941bbSAndroid Build Coastguard Worker
28*b7c941bbSAndroid Build Coastguard WorkerCIRCLE_COLOR = 0  # [0: black, 255: white]
29*b7c941bbSAndroid Build Coastguard WorkerCIRCLE_MIN_AREA = 0.01  # 1% of image size
30*b7c941bbSAndroid Build Coastguard WorkerFOV_PERCENT_RTOL = 0.15  # Relative tolerance on circle FoV % to expected.
31*b7c941bbSAndroid Build Coastguard WorkerLARGE_SIZE_IMAGE = 2000  # Size of a large image (compared against max(w, h))
32*b7c941bbSAndroid Build Coastguard WorkerTHRESH_AR_L = 0.02  # Aspect ratio test threshold of large images
33*b7c941bbSAndroid Build Coastguard WorkerTHRESH_AR_S = 0.075  # Aspect ratio test threshold of mini images
34*b7c941bbSAndroid Build Coastguard WorkerTHRESH_CROP_L = 0.02  # Crop test threshold of large images
35*b7c941bbSAndroid Build Coastguard WorkerTHRESH_CROP_S = 0.075  # Crop test threshold of mini images
36*b7c941bbSAndroid Build Coastguard WorkerTHRESH_MIN_PIXEL = 4  # Crop test allowed offset
37*b7c941bbSAndroid Build Coastguard Worker
38*b7c941bbSAndroid Build Coastguard Worker
39*b7c941bbSAndroid Build Coastguard Workerdef calc_scaler_crop_region_ratio(scaler_crop_region, props):
40*b7c941bbSAndroid Build Coastguard Worker  """Calculate ratio of scaler crop region area over active array area.
41*b7c941bbSAndroid Build Coastguard Worker
42*b7c941bbSAndroid Build Coastguard Worker  Args:
43*b7c941bbSAndroid Build Coastguard Worker    scaler_crop_region: Rect(left, top, right, bottom)
44*b7c941bbSAndroid Build Coastguard Worker    props: camera properties
45*b7c941bbSAndroid Build Coastguard Worker
46*b7c941bbSAndroid Build Coastguard Worker  Returns:
47*b7c941bbSAndroid Build Coastguard Worker    ratio of scaler crop region area over active array area
48*b7c941bbSAndroid Build Coastguard Worker  """
49*b7c941bbSAndroid Build Coastguard Worker  a = props['android.sensor.info.activeArraySize']
50*b7c941bbSAndroid Build Coastguard Worker  s = scaler_crop_region
51*b7c941bbSAndroid Build Coastguard Worker  logging.debug('Active array size: %s', a)
52*b7c941bbSAndroid Build Coastguard Worker  active_array_area = (a['right'] - a['left']) * (a['bottom'] - a['top'])
53*b7c941bbSAndroid Build Coastguard Worker  scaler_crop_region_area = (s['right'] - s['left']) * (s['bottom'] - s['top'])
54*b7c941bbSAndroid Build Coastguard Worker  crop_region_active_array_ratio = scaler_crop_region_area / active_array_area
55*b7c941bbSAndroid Build Coastguard Worker  return crop_region_active_array_ratio
56*b7c941bbSAndroid Build Coastguard Worker
57*b7c941bbSAndroid Build Coastguard Worker
58*b7c941bbSAndroid Build Coastguard Workerdef check_fov(circle, ref_fov, w, h):
59*b7c941bbSAndroid Build Coastguard Worker  """Check the FoV for correct size."""
60*b7c941bbSAndroid Build Coastguard Worker  fov_percent = calc_circle_image_ratio(circle['r'], w, h)
61*b7c941bbSAndroid Build Coastguard Worker  chk_percent = calc_expected_circle_image_ratio(ref_fov, w, h)
62*b7c941bbSAndroid Build Coastguard Worker  if not math.isclose(fov_percent, chk_percent, rel_tol=FOV_PERCENT_RTOL):
63*b7c941bbSAndroid Build Coastguard Worker    e_msg = (f'FoV %: {fov_percent:.2f}, Ref FoV %: {chk_percent:.2f}, '
64*b7c941bbSAndroid Build Coastguard Worker             f'TOL={FOV_PERCENT_RTOL*100}%, img: {w}x{h}, ref: '
65*b7c941bbSAndroid Build Coastguard Worker             f"{ref_fov['w']}x{ref_fov['h']}")
66*b7c941bbSAndroid Build Coastguard Worker    return e_msg
67*b7c941bbSAndroid Build Coastguard Worker
68*b7c941bbSAndroid Build Coastguard Worker
69*b7c941bbSAndroid Build Coastguard Workerdef check_ar(circle, ar_gt, w, h, e_msg_stem):
70*b7c941bbSAndroid Build Coastguard Worker  """Check the aspect ratio of the circle.
71*b7c941bbSAndroid Build Coastguard Worker
72*b7c941bbSAndroid Build Coastguard Worker  size is the larger of w or h.
73*b7c941bbSAndroid Build Coastguard Worker  if size >= LARGE_SIZE_IMAGE: use THRESH_AR_L
74*b7c941bbSAndroid Build Coastguard Worker  elif size == 0 (extreme case): THRESH_AR_S
75*b7c941bbSAndroid Build Coastguard Worker  elif 0 < image size < LARGE_SIZE_IMAGE: scale between THRESH_AR_S & AR_L
76*b7c941bbSAndroid Build Coastguard Worker
77*b7c941bbSAndroid Build Coastguard Worker  Args:
78*b7c941bbSAndroid Build Coastguard Worker    circle: dict with circle parameters
79*b7c941bbSAndroid Build Coastguard Worker    ar_gt: aspect ratio ground truth to compare against
80*b7c941bbSAndroid Build Coastguard Worker    w: width of image
81*b7c941bbSAndroid Build Coastguard Worker    h: height of image
82*b7c941bbSAndroid Build Coastguard Worker    e_msg_stem: customized string for error message
83*b7c941bbSAndroid Build Coastguard Worker
84*b7c941bbSAndroid Build Coastguard Worker  Returns:
85*b7c941bbSAndroid Build Coastguard Worker    error string if check fails
86*b7c941bbSAndroid Build Coastguard Worker  """
87*b7c941bbSAndroid Build Coastguard Worker  thresh_ar = max(THRESH_AR_L, THRESH_AR_S +
88*b7c941bbSAndroid Build Coastguard Worker                  max(w, h) * (THRESH_AR_L-THRESH_AR_S) / LARGE_SIZE_IMAGE)
89*b7c941bbSAndroid Build Coastguard Worker  ar = circle['w'] / circle['h']
90*b7c941bbSAndroid Build Coastguard Worker  if not math.isclose(ar, ar_gt, abs_tol=thresh_ar):
91*b7c941bbSAndroid Build Coastguard Worker    e_msg = (f'{e_msg_stem} {w}x{h}: aspect_ratio {ar:.3f}, '
92*b7c941bbSAndroid Build Coastguard Worker             f'thresh {thresh_ar:.3f}')
93*b7c941bbSAndroid Build Coastguard Worker    return e_msg
94*b7c941bbSAndroid Build Coastguard Worker
95*b7c941bbSAndroid Build Coastguard Worker
96*b7c941bbSAndroid Build Coastguard Workerdef check_crop(circle, cc_gt, w, h, e_msg_stem, crop_thresh_factor):
97*b7c941bbSAndroid Build Coastguard Worker  """Check cropping.
98*b7c941bbSAndroid Build Coastguard Worker
99*b7c941bbSAndroid Build Coastguard Worker  if size >= LARGE_SIZE_IMAGE: use thresh_crop_l
100*b7c941bbSAndroid Build Coastguard Worker  elif size == 0 (extreme case): thresh_crop_s
101*b7c941bbSAndroid Build Coastguard Worker  elif 0 < size < LARGE_SIZE_IMAGE: scale between thresh_crop_s & thresh_crop_l
102*b7c941bbSAndroid Build Coastguard Worker  Also allow at least THRESH_MIN_PIXEL to prevent threshold being too tight
103*b7c941bbSAndroid Build Coastguard Worker  for very small circle.
104*b7c941bbSAndroid Build Coastguard Worker
105*b7c941bbSAndroid Build Coastguard Worker  Args:
106*b7c941bbSAndroid Build Coastguard Worker    circle: dict of circle values
107*b7c941bbSAndroid Build Coastguard Worker    cc_gt: circle center {'hori', 'vert'}  ground truth (ref'd to img center)
108*b7c941bbSAndroid Build Coastguard Worker    w: width of image
109*b7c941bbSAndroid Build Coastguard Worker    h: height of image
110*b7c941bbSAndroid Build Coastguard Worker    e_msg_stem: text to customize error message
111*b7c941bbSAndroid Build Coastguard Worker    crop_thresh_factor: scaling factor for crop thresholds
112*b7c941bbSAndroid Build Coastguard Worker
113*b7c941bbSAndroid Build Coastguard Worker  Returns:
114*b7c941bbSAndroid Build Coastguard Worker    error string if check fails
115*b7c941bbSAndroid Build Coastguard Worker  """
116*b7c941bbSAndroid Build Coastguard Worker  thresh_crop_l = THRESH_CROP_L * crop_thresh_factor
117*b7c941bbSAndroid Build Coastguard Worker  thresh_crop_s = THRESH_CROP_S * crop_thresh_factor
118*b7c941bbSAndroid Build Coastguard Worker  thresh_crop_hori = max(
119*b7c941bbSAndroid Build Coastguard Worker      [thresh_crop_l,
120*b7c941bbSAndroid Build Coastguard Worker       thresh_crop_s + w * (thresh_crop_l - thresh_crop_s) / LARGE_SIZE_IMAGE,
121*b7c941bbSAndroid Build Coastguard Worker       THRESH_MIN_PIXEL / circle['w']])
122*b7c941bbSAndroid Build Coastguard Worker  thresh_crop_vert = max(
123*b7c941bbSAndroid Build Coastguard Worker      [thresh_crop_l,
124*b7c941bbSAndroid Build Coastguard Worker       thresh_crop_s + h * (thresh_crop_l - thresh_crop_s) / LARGE_SIZE_IMAGE,
125*b7c941bbSAndroid Build Coastguard Worker       THRESH_MIN_PIXEL / circle['h']])
126*b7c941bbSAndroid Build Coastguard Worker
127*b7c941bbSAndroid Build Coastguard Worker  if (not math.isclose(circle['x_offset'], cc_gt['hori'],
128*b7c941bbSAndroid Build Coastguard Worker                       abs_tol=thresh_crop_hori) or
129*b7c941bbSAndroid Build Coastguard Worker      not math.isclose(circle['y_offset'], cc_gt['vert'],
130*b7c941bbSAndroid Build Coastguard Worker                       abs_tol=thresh_crop_vert)):
131*b7c941bbSAndroid Build Coastguard Worker    valid_x_range = (cc_gt['hori'] - thresh_crop_hori,
132*b7c941bbSAndroid Build Coastguard Worker                     cc_gt['hori'] + thresh_crop_hori)
133*b7c941bbSAndroid Build Coastguard Worker    valid_y_range = (cc_gt['vert'] - thresh_crop_vert,
134*b7c941bbSAndroid Build Coastguard Worker                     cc_gt['vert'] + thresh_crop_vert)
135*b7c941bbSAndroid Build Coastguard Worker    e_msg = (f'{e_msg_stem} {w}x{h} '
136*b7c941bbSAndroid Build Coastguard Worker             f"offset X {circle['x_offset']:.3f}, Y {circle['y_offset']:.3f}, "
137*b7c941bbSAndroid Build Coastguard Worker             f'valid X range: {valid_x_range[0]:.3f} ~ {valid_x_range[1]:.3f}, '
138*b7c941bbSAndroid Build Coastguard Worker             f'valid Y range: {valid_y_range[0]:.3f} ~ {valid_y_range[1]:.3f}')
139*b7c941bbSAndroid Build Coastguard Worker    return e_msg
140*b7c941bbSAndroid Build Coastguard Worker
141*b7c941bbSAndroid Build Coastguard Worker
142*b7c941bbSAndroid Build Coastguard Workerdef calc_expected_circle_image_ratio(ref_fov, img_w, img_h):
143*b7c941bbSAndroid Build Coastguard Worker  """Determine the circle image area ratio in percentage for a given image size.
144*b7c941bbSAndroid Build Coastguard Worker
145*b7c941bbSAndroid Build Coastguard Worker  Cropping happens either horizontally or vertically. In both cases crop results
146*b7c941bbSAndroid Build Coastguard Worker  in the visble area reduced by a ratio r (r < 1) and the circle will in turn
147*b7c941bbSAndroid Build Coastguard Worker  occupy ref_pct/r (percent) on the target image size.
148*b7c941bbSAndroid Build Coastguard Worker
149*b7c941bbSAndroid Build Coastguard Worker  Args:
150*b7c941bbSAndroid Build Coastguard Worker    ref_fov: dict with {fmt, % coverage, w, h, circle_w, circle_h}
151*b7c941bbSAndroid Build Coastguard Worker    img_w: the image width
152*b7c941bbSAndroid Build Coastguard Worker    img_h: the image height
153*b7c941bbSAndroid Build Coastguard Worker
154*b7c941bbSAndroid Build Coastguard Worker  Returns:
155*b7c941bbSAndroid Build Coastguard Worker    chk_percent: the expected circle image area ratio in percentage
156*b7c941bbSAndroid Build Coastguard Worker  """
157*b7c941bbSAndroid Build Coastguard Worker  ar_ref = ref_fov['w'] / ref_fov['h']
158*b7c941bbSAndroid Build Coastguard Worker  ar_target = img_w / img_h
159*b7c941bbSAndroid Build Coastguard Worker
160*b7c941bbSAndroid Build Coastguard Worker  r = ar_ref / ar_target
161*b7c941bbSAndroid Build Coastguard Worker  if r < 1.0:
162*b7c941bbSAndroid Build Coastguard Worker    r = 1.0 / r
163*b7c941bbSAndroid Build Coastguard Worker  return ref_fov['percent'] * r
164*b7c941bbSAndroid Build Coastguard Worker
165*b7c941bbSAndroid Build Coastguard Worker
166*b7c941bbSAndroid Build Coastguard Workerdef calc_circle_image_ratio(radius, img_w, img_h):
167*b7c941bbSAndroid Build Coastguard Worker  """Calculate the percent of area the input circle covers in input image.
168*b7c941bbSAndroid Build Coastguard Worker
169*b7c941bbSAndroid Build Coastguard Worker  Args:
170*b7c941bbSAndroid Build Coastguard Worker    radius: radius of circle
171*b7c941bbSAndroid Build Coastguard Worker    img_w: int width of image
172*b7c941bbSAndroid Build Coastguard Worker    img_h: int height of image
173*b7c941bbSAndroid Build Coastguard Worker  Returns:
174*b7c941bbSAndroid Build Coastguard Worker    fov_percent: float % of image covered by circle
175*b7c941bbSAndroid Build Coastguard Worker  """
176*b7c941bbSAndroid Build Coastguard Worker  return 100 * math.pi * math.pow(radius, 2) / (img_w * img_h)
177*b7c941bbSAndroid Build Coastguard Worker
178*b7c941bbSAndroid Build Coastguard Worker
179*b7c941bbSAndroid Build Coastguard Workerdef find_fov_reference(cam, req, props, raw_bool, ref_img_name_stem):
180*b7c941bbSAndroid Build Coastguard Worker  """Determine the circle coverage of the image in reference image.
181*b7c941bbSAndroid Build Coastguard Worker
182*b7c941bbSAndroid Build Coastguard Worker  Captures a full-frame RAW or JPEG and uses its aspect ratio and circle center
183*b7c941bbSAndroid Build Coastguard Worker  location as ground truth for the other jpeg or yuv images.
184*b7c941bbSAndroid Build Coastguard Worker
185*b7c941bbSAndroid Build Coastguard Worker  The intrinsics and distortion coefficients are meant for full-sized RAW,
186*b7c941bbSAndroid Build Coastguard Worker  so convert_capture_to_rgb_image returns a 2x downsampled version, so resizes
187*b7c941bbSAndroid Build Coastguard Worker  RGB back to full size.
188*b7c941bbSAndroid Build Coastguard Worker
189*b7c941bbSAndroid Build Coastguard Worker  If the device supports lens distortion correction, applies the coefficients on
190*b7c941bbSAndroid Build Coastguard Worker  the RAW image so it can be compared to YUV/JPEG outputs which are subject
191*b7c941bbSAndroid Build Coastguard Worker  to the same correction via ISP.
192*b7c941bbSAndroid Build Coastguard Worker
193*b7c941bbSAndroid Build Coastguard Worker  Finds circle size and location for reference values in calculations for other
194*b7c941bbSAndroid Build Coastguard Worker  formats.
195*b7c941bbSAndroid Build Coastguard Worker
196*b7c941bbSAndroid Build Coastguard Worker  Args:
197*b7c941bbSAndroid Build Coastguard Worker    cam: camera object
198*b7c941bbSAndroid Build Coastguard Worker    req: camera request
199*b7c941bbSAndroid Build Coastguard Worker    props: camera properties
200*b7c941bbSAndroid Build Coastguard Worker    raw_bool: True if RAW available
201*b7c941bbSAndroid Build Coastguard Worker    ref_img_name_stem: test _NAME + location to save data
202*b7c941bbSAndroid Build Coastguard Worker
203*b7c941bbSAndroid Build Coastguard Worker  Returns:
204*b7c941bbSAndroid Build Coastguard Worker    ref_fov: dict with {fmt, % coverage, w, h, circle_w, circle_h}
205*b7c941bbSAndroid Build Coastguard Worker    cc_ct_gt: circle center position relative to the center of image.
206*b7c941bbSAndroid Build Coastguard Worker    aspect_ratio_gt: aspect ratio of the detected circle in float.
207*b7c941bbSAndroid Build Coastguard Worker  """
208*b7c941bbSAndroid Build Coastguard Worker  logging.debug('Creating references for fov_coverage')
209*b7c941bbSAndroid Build Coastguard Worker  if raw_bool:
210*b7c941bbSAndroid Build Coastguard Worker    logging.debug('Using RAW for reference')
211*b7c941bbSAndroid Build Coastguard Worker    fmt_type = 'RAW'
212*b7c941bbSAndroid Build Coastguard Worker    out_surface = {'format': 'raw'}
213*b7c941bbSAndroid Build Coastguard Worker    cap = cam.do_capture(req, out_surface)
214*b7c941bbSAndroid Build Coastguard Worker    logging.debug('Captured RAW %dx%d', cap['width'], cap['height'])
215*b7c941bbSAndroid Build Coastguard Worker    img = image_processing_utils.convert_capture_to_rgb_image(
216*b7c941bbSAndroid Build Coastguard Worker        cap, props=props)
217*b7c941bbSAndroid Build Coastguard Worker    # Resize back up to full scale.
218*b7c941bbSAndroid Build Coastguard Worker    img = cv2.resize(img, (0, 0), fx=2.0, fy=2.0)
219*b7c941bbSAndroid Build Coastguard Worker
220*b7c941bbSAndroid Build Coastguard Worker    fd = float(cap['metadata']['android.lens.focalLength'])
221*b7c941bbSAndroid Build Coastguard Worker    k = camera_properties_utils.get_intrinsic_calibration(
222*b7c941bbSAndroid Build Coastguard Worker        props, cap['metadata'], True, fd
223*b7c941bbSAndroid Build Coastguard Worker    )
224*b7c941bbSAndroid Build Coastguard Worker    if (camera_properties_utils.distortion_correction(props) and
225*b7c941bbSAndroid Build Coastguard Worker        isinstance(k, np.ndarray)):
226*b7c941bbSAndroid Build Coastguard Worker      logging.debug('Applying intrinsic calibration and distortion params')
227*b7c941bbSAndroid Build Coastguard Worker      opencv_dist = camera_properties_utils.get_distortion_matrix(props)
228*b7c941bbSAndroid Build Coastguard Worker      k_new = cv2.getOptimalNewCameraMatrix(
229*b7c941bbSAndroid Build Coastguard Worker          k, opencv_dist, (img.shape[1], img.shape[0]), 0)[0]
230*b7c941bbSAndroid Build Coastguard Worker      scale = max(k_new[0][0] / k[0][0], k_new[1][1] / k[1][1])
231*b7c941bbSAndroid Build Coastguard Worker      if scale > 1:
232*b7c941bbSAndroid Build Coastguard Worker        k_new[0][0] = k[0][0] * scale
233*b7c941bbSAndroid Build Coastguard Worker        k_new[1][1] = k[1][1] * scale
234*b7c941bbSAndroid Build Coastguard Worker        img = cv2.undistort(img, k, opencv_dist, None, k_new)
235*b7c941bbSAndroid Build Coastguard Worker      else:
236*b7c941bbSAndroid Build Coastguard Worker        img = cv2.undistort(img, k, opencv_dist)
237*b7c941bbSAndroid Build Coastguard Worker    size = img.shape
238*b7c941bbSAndroid Build Coastguard Worker
239*b7c941bbSAndroid Build Coastguard Worker  else:
240*b7c941bbSAndroid Build Coastguard Worker    logging.debug('Using JPEG for reference')
241*b7c941bbSAndroid Build Coastguard Worker    fmt_type = 'JPEG'
242*b7c941bbSAndroid Build Coastguard Worker    ref_fov = {}
243*b7c941bbSAndroid Build Coastguard Worker    fmt = capture_request_utils.get_largest_format('jpeg', props)
244*b7c941bbSAndroid Build Coastguard Worker    cap = cam.do_capture(req, fmt)
245*b7c941bbSAndroid Build Coastguard Worker    logging.debug('Captured JPEG %dx%d', cap['width'], cap['height'])
246*b7c941bbSAndroid Build Coastguard Worker    img = image_processing_utils.convert_capture_to_rgb_image(cap, props)
247*b7c941bbSAndroid Build Coastguard Worker    size = (cap['height'], cap['width'])
248*b7c941bbSAndroid Build Coastguard Worker
249*b7c941bbSAndroid Build Coastguard Worker  # Get image size.
250*b7c941bbSAndroid Build Coastguard Worker  w = size[1]
251*b7c941bbSAndroid Build Coastguard Worker  h = size[0]
252*b7c941bbSAndroid Build Coastguard Worker  img_name = f'{ref_img_name_stem}_{fmt_type}_w{w}_h{h}.png'
253*b7c941bbSAndroid Build Coastguard Worker  image_processing_utils.write_image(img, img_name, True)
254*b7c941bbSAndroid Build Coastguard Worker
255*b7c941bbSAndroid Build Coastguard Worker  # Find circle.
256*b7c941bbSAndroid Build Coastguard Worker  img *= 255  # cv2 needs images between [0,255].
257*b7c941bbSAndroid Build Coastguard Worker  circle = opencv_processing_utils.find_circle(
258*b7c941bbSAndroid Build Coastguard Worker      img, img_name, CIRCLE_MIN_AREA, CIRCLE_COLOR)
259*b7c941bbSAndroid Build Coastguard Worker  opencv_processing_utils.append_circle_center_to_img(circle, img, img_name)
260*b7c941bbSAndroid Build Coastguard Worker
261*b7c941bbSAndroid Build Coastguard Worker  # Determine final return values.
262*b7c941bbSAndroid Build Coastguard Worker  if fmt_type == 'RAW':
263*b7c941bbSAndroid Build Coastguard Worker    aspect_ratio_gt = circle['w'] / circle['h']
264*b7c941bbSAndroid Build Coastguard Worker  else:
265*b7c941bbSAndroid Build Coastguard Worker    aspect_ratio_gt = 1.0
266*b7c941bbSAndroid Build Coastguard Worker  cc_ct_gt = {'hori': circle['x_offset'], 'vert': circle['y_offset']}
267*b7c941bbSAndroid Build Coastguard Worker  fov_percent = calc_circle_image_ratio(circle['r'], w, h)
268*b7c941bbSAndroid Build Coastguard Worker  ref_fov = {}
269*b7c941bbSAndroid Build Coastguard Worker  ref_fov['fmt'] = fmt_type
270*b7c941bbSAndroid Build Coastguard Worker  ref_fov['percent'] = fov_percent
271*b7c941bbSAndroid Build Coastguard Worker  ref_fov['w'] = w
272*b7c941bbSAndroid Build Coastguard Worker  ref_fov['h'] = h
273*b7c941bbSAndroid Build Coastguard Worker  ref_fov['circle_w'] = circle['w']
274*b7c941bbSAndroid Build Coastguard Worker  ref_fov['circle_h'] = circle['h']
275*b7c941bbSAndroid Build Coastguard Worker  logging.debug('Using %s reference: %s', fmt_type, str(ref_fov))
276*b7c941bbSAndroid Build Coastguard Worker  return ref_fov, cc_ct_gt, aspect_ratio_gt
277