• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15import its.image
16import its.caps
17import its.device
18import its.objects
19import its.target
20import matplotlib
21import matplotlib.pyplot
22import numpy
23import os.path
24import pylab
25
26def 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
143if __name__ == '__main__':
144    main()
145
146