Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 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.path |
| 16 | |
| 17 | import its.caps |
| 18 | import its.device |
| 19 | import its.image |
| 20 | import its.objects |
| 21 | import its.target |
| 22 | |
| 23 | import numpy as np |
| 24 | NAME = os.path.basename(__file__).split('.')[0] |
Clemenz Portmann | 8156814 | 2018-05-16 13:12:50 -0700 | [diff] [blame] | 25 | PATCH_SIZE = 0.0625 # 1/16 x 1/16 in center of image |
| 26 | PATCH_LOC = (1-PATCH_SIZE)/2 |
| 27 | THRESH_DIFF = 0.06 |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 28 | THRESH_GAIN = 0.1 |
| 29 | THRESH_EXP = 0.05 |
| 30 | |
| 31 | |
| 32 | def main(): |
| 33 | """Test both cameras give similar RBG values for gray patch.""" |
| 34 | |
| 35 | yuv_sizes = {} |
| 36 | with its.device.ItsSession() as cam: |
| 37 | props = cam.get_camera_properties() |
Clemenz Portmann | 9d1f0d3 | 2018-09-25 17:50:23 -0700 | [diff] [blame] | 38 | its.caps.skip_unless(its.caps.per_frame_control(props) and |
Clemenz Portmann | 9d1f0d3 | 2018-09-25 17:50:23 -0700 | [diff] [blame] | 39 | its.caps.logical_multi_camera(props)) |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 40 | ids = its.caps.logical_multi_camera_physical_ids(props) |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 41 | for i in ids: |
| 42 | physical_props = cam.get_camera_properties_by_id(i) |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 43 | its.caps.skip_unless(not its.caps.mono_camera(physical_props)) |
Takumi Yoshida | 83a9e73 | 2020-04-17 20:27:48 +0900 | [diff] [blame^] | 44 | its.caps.skip_unless(its.caps.backward_compatible(physical_props)) |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 45 | yuv_sizes[i] = its.objects.get_available_output_sizes( |
Clemenz Portmann | 642ed5f | 2019-03-13 17:13:09 -0700 | [diff] [blame] | 46 | 'yuv', physical_props) |
| 47 | if i == ids[0]: # get_available_output_sizes returns sorted list |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 48 | yuv_match_sizes = yuv_sizes[i] |
| 49 | else: |
Clemenz Portmann | 8582f0b | 2020-03-26 12:14:29 -0700 | [diff] [blame] | 50 | yuv_match_sizes = list( |
| 51 | set(yuv_sizes[i]).intersection(yuv_match_sizes)) |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 52 | |
| 53 | # find matched size for captures |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 54 | yuv_match_sizes.sort() |
| 55 | w = yuv_match_sizes[-1][0] |
| 56 | h = yuv_match_sizes[-1][1] |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 57 | print 'Matched YUV size: (%d, %d)' % (w, h) |
| 58 | |
| 59 | # do 3a and create requests |
Clemenz Portmann | ee5058b | 2019-03-27 16:47:26 -0700 | [diff] [blame] | 60 | avail_fls = sorted(props['android.lens.info.availableFocalLengths'], |
| 61 | reverse=True) |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 62 | cam.do_3a() |
| 63 | reqs = [] |
| 64 | for i, fl in enumerate(avail_fls): |
| 65 | reqs.append(its.objects.auto_capture_request()) |
| 66 | reqs[i]['android.lens.focalLength'] = fl |
Clemenz Portmann | ee5058b | 2019-03-27 16:47:26 -0700 | [diff] [blame] | 67 | if i > 0: |
| 68 | # Calculate the active sensor region for a non-cropped image |
| 69 | zoom = avail_fls[0] / fl |
| 70 | a = props['android.sensor.info.activeArraySize'] |
| 71 | ax, ay = a['left'], a['top'] |
| 72 | aw, ah = a['right'] - a['left'], a['bottom'] - a['top'] |
| 73 | |
| 74 | # Calculate a center crop region. |
| 75 | assert zoom >= 1 |
| 76 | cropw = aw / zoom |
| 77 | croph = ah / zoom |
| 78 | crop_region = { |
| 79 | 'left': aw / 2 - cropw / 2, |
| 80 | 'top': ah / 2 - croph / 2, |
| 81 | 'right': aw / 2 + cropw / 2, |
| 82 | 'bottom': ah / 2 + croph / 2 |
| 83 | } |
| 84 | reqs[i]['android.scaler.cropRegion'] = crop_region |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 85 | |
| 86 | # capture YUVs |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 87 | y_means = {} |
| 88 | msg = '' |
| 89 | fmt = [{'format': 'yuv', 'width': w, 'height': h}] |
| 90 | caps = cam.do_capture(reqs, fmt) |
Clemenz Portmann | 7b8ab0b | 2019-03-27 14:11:16 -0700 | [diff] [blame] | 91 | if not isinstance(caps, list): |
| 92 | caps = [caps] # handle canonical case where caps is not list |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 93 | |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 94 | for i, fl in enumerate(avail_fls): |
| 95 | img = its.image.convert_capture_to_rgb_image(caps[i], props=props) |
| 96 | its.image.write_image(img, '%s_yuv_fl=%s.jpg' % (NAME, fl)) |
| 97 | y, _, _ = its.image.convert_capture_to_planes(caps[i], props=props) |
| 98 | y_mean = its.image.compute_image_means( |
| 99 | its.image.get_image_patch(y, PATCH_LOC, PATCH_LOC, |
| 100 | PATCH_SIZE, PATCH_SIZE))[0] |
| 101 | print 'y[%s]: %.3f' % (fl, y_mean) |
| 102 | msg += 'y[%s]: %.3f, ' % (fl, y_mean) |
| 103 | y_means[fl] = y_mean |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 104 | |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 105 | # compare YUVs |
Clemenz Portmann | 32754b7 | 2018-07-10 11:47:01 -0700 | [diff] [blame] | 106 | msg += 'TOL=%.5f' % THRESH_DIFF |
| 107 | assert np.isclose(max(y_means.values()), min(y_means.values()), |
| 108 | rtol=THRESH_DIFF), msg |
Clemenz Portmann | ac8a085 | 2017-11-30 16:54:28 -0800 | [diff] [blame] | 109 | |
| 110 | |
| 111 | if __name__ == '__main__': |
| 112 | main() |