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