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