Home | History | Annotate | Download | only in scene3
      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 
     15 import its.image
     16 import its.caps
     17 import its.device
     18 import its.objects
     19 import its.target
     20 import math
     21 import matplotlib
     22 import matplotlib.pyplot
     23 import numpy
     24 import os.path
     25 import pylab
     26 
     27 
     28 def 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 
     81 def 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         # If reprocessing is supported, ZSL EE mode must be avaiable.
    105         assert(its.caps.edge_mode(props, 3))
    106 
    107         reprocess_formats = []
    108         if (its.caps.yuv_reprocess(props)):
    109             reprocess_formats.append("yuv")
    110         if (its.caps.private_reprocess(props)):
    111             reprocess_formats.append("private")
    112 
    113         size = its.objects.get_available_output_sizes("jpg", props)[0]
    114         out_surface = {"width":size[0], "height":size[1], "format":"jpg"}
    115 
    116         # Get proper sensitivity, exposure time, and focus distance.
    117         s,e,_,_,fd = cam.do_3a(get_results=True)
    118 
    119         # Get the sharpness for each edge mode for regular requests
    120         sharpness_regular = []
    121         edge_mode_reported_regular = []
    122         for edge_mode in range(4):
    123             # Skip unavailable modes
    124             if not its.caps.edge_mode(props, edge_mode):
    125                 edge_mode_reported_regular.append(edge_mode)
    126                 sharpness_regular.append(0)
    127                 continue
    128             ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface)
    129             edge_mode_reported_regular.append(ret["edge_mode"])
    130             sharpness_regular.append(ret["sharpness"])
    131 
    132         print "Reported edge modes:", edge_mode_reported_regular
    133         print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular
    134 
    135         # Get the sharpness for each reprocess format and edge mode for
    136         # reprocess requests.
    137         sharpnesses_reprocess = []
    138         edge_mode_reported_reprocess = []
    139 
    140         for reprocess_format in reprocess_formats:
    141             # List of sharpness
    142             sharpnesses = []
    143             edge_mode_reported = []
    144             for edge_mode in range(4):
    145                 # Skip unavailable modes
    146                 if not its.caps.edge_mode(props, edge_mode):
    147                     edge_mode_reported.append(edge_mode)
    148                     sharpnesses.append(0)
    149                     continue
    150 
    151                 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface,
    152                     reprocess_format)
    153                 edge_mode_reported.append(ret["edge_mode"])
    154                 sharpnesses.append(ret["sharpness"])
    155 
    156             sharpnesses_reprocess.append(sharpnesses)
    157             edge_mode_reported_reprocess.append(edge_mode_reported)
    158 
    159             print "Reported edge modes:", edge_mode_reported
    160             print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \
    161                 (reprocess_format) , sharpnesses
    162 
    163 
    164         # Verify HQ(2) is sharper than OFF(0)
    165         assert(sharpness_regular[2] > sharpness_regular[0])
    166 
    167         # Verify ZSL(3) is similar to OFF(0)
    168         assert(numpy.isclose(sharpness_regular[3], sharpness_regular[0],
    169                              THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    170 
    171         # Verify OFF(0) is not sharper than FAST(1)
    172         assert(sharpness_regular[1] >
    173                sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    174 
    175         # Verify FAST(1) is not sharper than HQ(2)
    176         assert(sharpness_regular[2] >
    177                sharpness_regular[1] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    178 
    179         for reprocess_format in range(len(reprocess_formats)):
    180             # Verify HQ(2) is sharper than OFF(0)
    181             assert(sharpnesses_reprocess[reprocess_format][2] >
    182                    sharpnesses_reprocess[reprocess_format][0])
    183 
    184             # Verify ZSL(3) is similar to OFF(0)
    185             assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][3],
    186                                  sharpnesses_reprocess[reprocess_format][0],
    187                                  THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    188 
    189             # Verify OFF(0) is not sharper than FAST(1)
    190             assert(sharpnesses_reprocess[reprocess_format][1] >
    191                    sharpnesses_reprocess[reprocess_format][0] *
    192                    (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    193 
    194             # Verify FAST(1) is not sharper than HQ(2)
    195             assert(sharpnesses_reprocess[reprocess_format][2] >
    196                    sharpnesses_reprocess[reprocess_format][1] *
    197                    (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    198 
    199             # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to
    200             # OFF(0)
    201             assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] /
    202                                     sharpnesses_reprocess[reprocess_format][0],
    203                                  sharpness_regular[2] / sharpness_regular[0],
    204                                  THRESHOLD_RELATIVE_SHARPNESS_DIFF))
    205 
    206 if __name__ == '__main__':
    207     main()
    208 
    209