Home | History | Annotate | Download | only in scene1
      1 # Copyright 2013 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 matplotlib
     21 import matplotlib.pyplot
     22 import numpy
     23 import os.path
     24 import pylab
     25 
     26 def main():
     27     """Test that the android.noiseReduction.mode param is applied when set.
     28 
     29     Capture images with the camera dimly lit. Uses a high analog gain to
     30     ensure the captured image is noisy.
     31 
     32     Captures three images, for NR off, "fast", and "high quality".
     33     Also captures an image with low gain and NR off, and uses the variance
     34     of this as the baseline.
     35     """
     36     NAME = os.path.basename(__file__).split(".")[0]
     37 
     38     NUM_SAMPLES_PER_MODE = 4
     39     SNR_TOLERANCE = 3 # unit in db
     40     # List of SNRs for R,G,B.
     41     snrs = [[], [], []]
     42 
     43     # Reference (baseline) SNR for each of R,G,B.
     44     ref_snr = []
     45 
     46     nr_modes_reported = []
     47 
     48     with its.device.ItsSession() as cam:
     49         props = cam.get_camera_properties()
     50         its.caps.skip_unless(its.caps.compute_target_exposure(props) and
     51                              its.caps.per_frame_control(props) and
     52                              its.caps.noise_reduction_mode(props, 0))
     53 
     54         # NR mode 0 with low gain
     55         e, s = its.target.get_target_exposure_combos(cam)["minSensitivity"]
     56         req = its.objects.manual_capture_request(s, e)
     57         req["android.noiseReduction.mode"] = 0
     58         cap = cam.do_capture(req)
     59         rgb_image = its.image.convert_capture_to_rgb_image(cap)
     60         its.image.write_image(
     61                 rgb_image,
     62                 "%s_low_gain.jpg" % (NAME))
     63         rgb_tile = its.image.get_image_patch(rgb_image, 0.45, 0.45, 0.1, 0.1)
     64         ref_snr = its.image.compute_image_snrs(rgb_tile)
     65         print "Ref SNRs:", ref_snr
     66 
     67         e, s = its.target.get_target_exposure_combos(cam)["maxSensitivity"]
     68         # NR modes 0, 1, 2, 3, 4 with high gain
     69         for mode in range(5):
     70             # Skip unavailable modes
     71             if not its.caps.noise_reduction_mode(props, mode):
     72                 nr_modes_reported.append(mode)
     73                 for channel in range(3):
     74                     snrs[channel].append(0)
     75                 continue;
     76 
     77             rgb_snr_list = []
     78             # Capture several images to account for per frame noise variations
     79             for n in range(NUM_SAMPLES_PER_MODE):
     80                 req = its.objects.manual_capture_request(s, e)
     81                 req["android.noiseReduction.mode"] = mode
     82                 cap = cam.do_capture(req)
     83                 rgb_image = its.image.convert_capture_to_rgb_image(cap)
     84                 if n == 0:
     85                     nr_modes_reported.append(
     86                             cap["metadata"]["android.noiseReduction.mode"])
     87                     its.image.write_image(
     88                             rgb_image,
     89                             "%s_high_gain_nr=%d.jpg" % (NAME, mode))
     90                 rgb_tile = its.image.get_image_patch(
     91                         rgb_image, 0.45, 0.45, 0.1, 0.1)
     92                 rgb_snrs = its.image.compute_image_snrs(rgb_tile)
     93                 rgb_snr_list.append(rgb_snrs)
     94 
     95             r_snrs = [rgb[0] for rgb in rgb_snr_list]
     96             g_snrs = [rgb[1] for rgb in rgb_snr_list]
     97             b_snrs = [rgb[2] for rgb in rgb_snr_list]
     98             rgb_snrs = [numpy.mean(r_snrs), numpy.mean(g_snrs), numpy.mean(b_snrs)]
     99             print "NR mode", mode, "SNRs:"
    100             print "    R SNR:", rgb_snrs[0],\
    101                     "Min:", min(r_snrs), "Max:", max(r_snrs)
    102             print "    G SNR:", rgb_snrs[1],\
    103                     "Min:", min(g_snrs), "Max:", max(g_snrs)
    104             print "    B SNR:", rgb_snrs[2],\
    105                     "Min:", min(b_snrs), "Max:", max(b_snrs)
    106 
    107             for chan in range(3):
    108                 snrs[chan].append(rgb_snrs[chan])
    109 
    110     # Draw a plot.
    111     for j in range(3):
    112         pylab.plot(range(5), snrs[j], "rgb"[j])
    113     matplotlib.pyplot.savefig("%s_plot_SNRs.png" % (NAME))
    114 
    115     assert(nr_modes_reported == [0,1,2,3,4])
    116 
    117     for j in range(3):
    118         # Larger SNR is better
    119         # Verify OFF(0) is not better than FAST(1)
    120         assert(snrs[j][0] <
    121                snrs[j][1] + SNR_TOLERANCE)
    122         # Verify FAST(1) is not better than HQ(2)
    123         assert(snrs[j][1] <
    124                snrs[j][2] + SNR_TOLERANCE)
    125         # Verify HQ(2) is better than OFF(0)
    126         assert(snrs[j][0] < snrs[j][2])
    127         if its.caps.noise_reduction_mode(props, 3):
    128             # Verify OFF(0) is not better than MINIMAL(3)
    129             assert(snrs[j][0] <
    130                    snrs[j][3] + SNR_TOLERANCE)
    131             # Verify MINIMAL(3) is not better than HQ(2)
    132             assert(snrs[j][3] <
    133                    snrs[j][2] + SNR_TOLERANCE)
    134             if its.caps.noise_reduction_mode(props, 4):
    135                 # Verify ZSL(4) is close to MINIMAL(3)
    136                 assert(numpy.isclose(snrs[j][4], snrs[j][3],
    137                                      atol=SNR_TOLERANCE))
    138         elif its.caps.noise_reduction_mode(props, 4):
    139             # Verify ZSL(4) is close to OFF(0)
    140             assert(numpy.isclose(snrs[j][4], snrs[j][0],
    141                                  atol=SNR_TOLERANCE))
    142 
    143 if __name__ == '__main__':
    144     main()
    145 
    146