• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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
15import its.image
16import its.caps
17import its.device
18import its.objects
19import its.target
20import math
21import matplotlib
22import matplotlib.pyplot
23import numpy
24import os.path
25from matplotlib import pylab
26
27
28def test_edge_mode(cam, edge_mode, sensitivity, exp, fd, out_surface,
29                   reprocess_format=None):
30    """Return sharpness of the output image and the capture result metadata
31       for a capture request with the given edge mode, sensitivity, exposure
32       time, focus distance, output surface parameter, and reprocess format
33       (None for a regular request.)
34
35    Args:
36        cam: An open device session.
37        edge_mode: Edge mode for the request as defined in android.edge.mode
38        sensitivity: Sensitivity for the request as defined in
39            android.sensor.sensitivity
40        exp: Exposure time for the request as defined in
41            android.sensor.exposureTime.
42        fd: Focus distance for the request as defined in
43            android.lens.focusDistance
44        output_surface: Specifications of the output image format and size.
45        reprocess_format: (Optional) The reprocessing format. If not None,
46                reprocessing will be enabled.
47
48    Returns:
49        Object containing reported edge mode and the sharpness of the output
50        image, keyed by the following strings:
51            "edge_mode"
52            "sharpness"
53    """
54
55    NAME = os.path.basename(__file__).split(".")[0]
56    NUM_SAMPLES = 4
57
58    req = its.objects.manual_capture_request(sensitivity, exp)
59    req["android.lens.focusDistance"] = fd
60    req["android.edge.mode"] = edge_mode
61    if (reprocess_format != None):
62        req["android.reprocess.effectiveExposureFactor"] = 1.0
63
64    sharpness_list = []
65    for n in range(NUM_SAMPLES):
66        cap = cam.do_capture(req, out_surface, reprocess_format)
67        img = its.image.convert_capture_to_rgb_image(cap)
68        if n == 0:
69            its.image.write_image(img, "%s_reprocess_fmt_%s_edge=%d.jpg" %
70                (NAME, reprocess_format, edge_mode))
71            res_edge_mode = cap["metadata"]["android.edge.mode"]
72        tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
73        sharpness_list.append(its.image.compute_image_sharpness(tile))
74
75    ret = {}
76    ret["edge_mode"] = res_edge_mode
77    ret["sharpness"] = numpy.mean(sharpness_list)
78
79    return ret
80
81def main():
82    """Test that the android.edge.mode param is applied when set for
83       reprocessing requests.
84
85    Capture non-reprocess images for each edge mode and calculate their
86    sharpness as a baseline.
87
88    Capture reprocessed images for each supported reprocess format and edge_mode
89    mode. Calculate the sharpness of reprocessed images and compare them against
90    the sharpess of non-reprocess images.
91    """
92
93    THRESHOLD_RELATIVE_SHARPNESS_DIFF = 0.15
94
95    with its.device.ItsSession() as cam:
96        props = cam.get_camera_properties()
97
98        its.caps.skip_unless(its.caps.read_3a(props) and
99                             its.caps.per_frame_control(props) and
100                             its.caps.edge_mode(props, 0) and
101                             (its.caps.yuv_reprocess(props) or
102                              its.caps.private_reprocess(props)))
103
104        mono_camera = its.caps.mono_camera(props)
105        # If reprocessing is supported, ZSL EE mode must be avaiable.
106        assert(its.caps.edge_mode(props, 3))
107
108        reprocess_formats = []
109        if (its.caps.yuv_reprocess(props)):
110            reprocess_formats.append("yuv")
111        if (its.caps.private_reprocess(props)):
112            reprocess_formats.append("private")
113
114        size = its.objects.get_available_output_sizes("jpg", props)[0]
115        out_surface = {"width":size[0], "height":size[1], "format":"jpg"}
116
117        # Get proper sensitivity, exposure time, and focus distance.
118        s,e,_,_,fd = cam.do_3a(get_results=True, mono_camera=mono_camera)
119
120        # Get the sharpness for each edge mode for regular requests
121        sharpness_regular = []
122        edge_mode_reported_regular = []
123        for edge_mode in range(4):
124            # Skip unavailable modes
125            if not its.caps.edge_mode(props, edge_mode):
126                edge_mode_reported_regular.append(edge_mode)
127                sharpness_regular.append(0)
128                continue
129            ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface)
130            edge_mode_reported_regular.append(ret["edge_mode"])
131            sharpness_regular.append(ret["sharpness"])
132
133        print "Reported edge modes:", edge_mode_reported_regular
134        print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular
135
136        # Get the sharpness for each reprocess format and edge mode for
137        # reprocess requests.
138        sharpnesses_reprocess = []
139        edge_mode_reported_reprocess = []
140
141        for reprocess_format in reprocess_formats:
142            # List of sharpness
143            sharpnesses = []
144            edge_mode_reported = []
145            for edge_mode in range(4):
146                # Skip unavailable modes
147                if not its.caps.edge_mode(props, edge_mode):
148                    edge_mode_reported.append(edge_mode)
149                    sharpnesses.append(0)
150                    continue
151
152                ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface,
153                    reprocess_format)
154                edge_mode_reported.append(ret["edge_mode"])
155                sharpnesses.append(ret["sharpness"])
156
157            sharpnesses_reprocess.append(sharpnesses)
158            edge_mode_reported_reprocess.append(edge_mode_reported)
159
160            print "Reported edge modes:", edge_mode_reported
161            print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \
162                (reprocess_format) , sharpnesses
163
164
165        # Verify HQ(2) is sharper than OFF(0)
166        assert(sharpness_regular[2] > sharpness_regular[0])
167
168        # Verify ZSL(3) is similar to OFF(0)
169        assert(numpy.isclose(sharpness_regular[3], sharpness_regular[0],
170                             THRESHOLD_RELATIVE_SHARPNESS_DIFF))
171
172        # Verify OFF(0) is not sharper than FAST(1)
173        assert(sharpness_regular[1] >
174               sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
175
176        # Verify FAST(1) is not sharper than HQ(2)
177        assert(sharpness_regular[2] >
178               sharpness_regular[1] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
179
180        for reprocess_format in range(len(reprocess_formats)):
181            # Verify HQ(2) is sharper than OFF(0)
182            assert(sharpnesses_reprocess[reprocess_format][2] >
183                   sharpnesses_reprocess[reprocess_format][0])
184
185            # Verify ZSL(3) is similar to OFF(0)
186            assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][3],
187                                 sharpnesses_reprocess[reprocess_format][0],
188                                 THRESHOLD_RELATIVE_SHARPNESS_DIFF))
189
190            # Verify OFF(0) is not sharper than FAST(1)
191            assert(sharpnesses_reprocess[reprocess_format][1] >
192                   sharpnesses_reprocess[reprocess_format][0] *
193                   (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
194
195            # Verify FAST(1) is not sharper than HQ(2)
196            assert(sharpnesses_reprocess[reprocess_format][2] >
197                   sharpnesses_reprocess[reprocess_format][1] *
198                   (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
199
200            # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to
201            # OFF(0)
202            assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] /
203                                    sharpnesses_reprocess[reprocess_format][0],
204                                 sharpness_regular[2] / sharpness_regular[0],
205                                 THRESHOLD_RELATIVE_SHARPNESS_DIFF))
206
207if __name__ == '__main__':
208    main()
209
210