| # Copyright 2018 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import os.path |
| import its.caps |
| import its.device |
| import its.image |
| import its.objects |
| import numpy as np |
| |
| # android.control.availableEffects |
| EFFECTS = {0: 'OFF', |
| 1: 'MONO', |
| 2: 'NEGATIVE', |
| 3: 'SOLARIZE', |
| 4: 'SEPIA', |
| 5: 'POSTERIZE', |
| 6: 'WHITEBOARD', |
| 7: 'BLACKBOARD', |
| 8: 'AQUA'} |
| MONO_UV_SPREAD_MAX = 2 # max spread for U & V channels [0:255] for mono image |
| NAME = os.path.basename(__file__).split('.')[0] |
| W, H = 640, 480 |
| YUV_MAX = 255.0 # normalization number for YUV images [0:1] --> [0:255] |
| YUV_UV_SPREAD_MIN = 10 # min spread for U & V channels [0:255] for color image |
| YUV_Y_SPREAD_MIN = 50 # min spread for Y channel [0:255] for color image |
| |
| |
| def main(): |
| """Test effects. |
| |
| Test: capture frame for supported camera effects and check if generated |
| correctly. Note we only check effects OFF and MONO currently, but save |
| images for all supported effects. |
| """ |
| |
| print '\nStarting %s' % NAME |
| with its.device.ItsSession() as cam: |
| props = cam.get_camera_properties() |
| mono_camera = its.caps.mono_camera(props) |
| effects = props['android.control.availableEffects'] |
| its.caps.skip_unless(effects != [0]) |
| cam.do_3a(mono_camera=mono_camera) |
| print 'Supported effects:', effects |
| failed = [] |
| for effect in effects: |
| req = its.objects.auto_capture_request() |
| req['android.control.effectMode'] = effect |
| fmt = {'format': 'yuv', 'width': W, 'height': H} |
| cap = cam.do_capture(req, fmt) |
| |
| # Save image |
| img = its.image.convert_capture_to_rgb_image(cap, props=props) |
| its.image.write_image(img, '%s_%s.jpg' % (NAME, EFFECTS[effect])) |
| |
| # Simple checks |
| if effect is 0: |
| print 'Checking effects OFF...' |
| y, u, v = its.image.convert_capture_to_planes(cap, props) |
| y_min, y_max = np.amin(y)*YUV_MAX, np.amax(y)*YUV_MAX |
| msg = 'Y_range:%.f,%.f THRESH:%d, ' % ( |
| y_min, y_max, YUV_Y_SPREAD_MIN) |
| if (y_max-y_min) < YUV_Y_SPREAD_MIN: |
| failed.append({'effect': EFFECTS[effect], 'error': msg}) |
| if not mono_camera: |
| u_min, u_max = np.amin(u)*YUV_MAX, np.amax(u)*YUV_MAX |
| v_min, v_max = np.amin(v)*YUV_MAX, np.amax(v)*YUV_MAX |
| msg += 'U_range:%.f,%.f THRESH:%d, ' % ( |
| u_min, u_max, YUV_UV_SPREAD_MIN) |
| msg += 'V_range:%.f,%.f THRESH:%d' % ( |
| v_min, v_max, YUV_UV_SPREAD_MIN) |
| if ((u_max-u_min) < YUV_UV_SPREAD_MIN or |
| (v_max-v_min) < YUV_UV_SPREAD_MIN): |
| failed.append({'effect': EFFECTS[effect], 'error': msg}) |
| if effect is 1: |
| print 'Checking MONO effect...' |
| _, u, v = its.image.convert_capture_to_planes(cap, props) |
| u_min, u_max = np.amin(u)*YUV_MAX, np.amax(u)*YUV_MAX |
| v_min, v_max = np.amin(v)*YUV_MAX, np.amax(v)*YUV_MAX |
| msg = 'U_range:%.f,%.f, ' % (u_min, u_max) |
| msg += 'V_range:%.f,%.f, TOL:%d' % ( |
| v_min, v_max, MONO_UV_SPREAD_MAX) |
| if ((u_max-u_min) > MONO_UV_SPREAD_MAX or |
| (v_max-v_min) > MONO_UV_SPREAD_MAX): |
| failed.append({'effect': EFFECTS[effect], 'error': msg}) |
| if failed: |
| print 'Failed effects:' |
| for fail in failed: |
| print ' %s: %s' % (fail['effect'], fail['error']) |
| assert not failed |
| |
| |
| if __name__ == '__main__': |
| main() |