1# Copyright 2016 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 os 16import cv2 17 18import its.caps 19import its.cv2image 20import its.device 21import its.image 22import its.objects 23import numpy as np 24 25NAME = os.path.basename(__file__).split('.')[0] 26CHART_FILE = os.path.join(os.environ['CAMERA_ITS_TOP'], 'pymodules', 'its', 27 'test_images', 'ISO12233.png') 28CHART_HEIGHT = 13.5 # cm 29CHART_DISTANCE = 30.0 # cm 30CHART_SCALE_START = 0.65 31CHART_SCALE_STOP = 1.35 32CHART_SCALE_STEP = 0.025 33CHART_ORIENTATIONS = ['nominal', 'flip', 'mirror', 'rotate'] 34VGA_WIDTH = 640 35VGA_HEIGHT = 480 36(X_CROP, Y_CROP) = (0.5, 0.5) # crop center area of ISO12233 chart 37 38 39def test_flip_mirror(cam, props, fmt, chart): 40 """Return if image is flipped or mirrored. 41 42 Args: 43 cam (class): An open device session 44 props (class): Properties of cam 45 fmt (dict): Capture format 46 chart (class): Object with chart properties 47 48 Returns: 49 boolean: True if flipped, False if not 50 """ 51 52 # determine if monochrome camera 53 mono_camera = its.caps.mono_camera(props) 54 55 # determine if in debug mode 56 debug = its.caps.debug_mode() 57 58 # get a local copy of the chart template 59 template = cv2.imread(CHART_FILE, cv2.IMREAD_ANYDEPTH) 60 61 # take img, crop chart, scale and prep for cv2 template match 62 s, e, _, _, fd = cam.do_3a(get_results=True, mono_camera=mono_camera) 63 req = its.objects.manual_capture_request(s, e, fd) 64 cap = cam.do_capture(req, fmt) 65 y, _, _ = its.image.convert_capture_to_planes(cap, props) 66 y = its.image.rotate_img_per_argv(y) 67 patch = its.image.get_image_patch(y, chart.xnorm, chart.ynorm, 68 chart.wnorm, chart.hnorm) 69 patch = 255 * its.cv2image.gray_scale_img(patch) 70 patch = its.cv2image.scale_img(patch.astype(np.uint8), chart.scale) 71 72 # sanity check on image 73 assert np.max(patch)-np.min(patch) > 255/8 74 75 # save full images if in debug 76 if debug: 77 its.image.write_image(template[:, :, np.newaxis]/255.0, 78 '%s_template.jpg' % NAME) 79 80 # save patch 81 its.image.write_image(patch[:, :, np.newaxis]/255.0, 82 '%s_scene_patch.jpg' % NAME) 83 84 # crop center areas and strip off any extra rows/columns 85 template = its.image.get_image_patch(template, (1-X_CROP)/2, (1-Y_CROP)/2, 86 X_CROP, Y_CROP) 87 patch = its.image.get_image_patch(patch, (1-X_CROP)/2, 88 (1-Y_CROP)/2, X_CROP, Y_CROP) 89 patch = patch[0:min(patch.shape[0], template.shape[0]), 90 0:min(patch.shape[1], template.shape[1])] 91 comp_chart = patch 92 93 # determine optimum orientation 94 opts = [] 95 for orientation in CHART_ORIENTATIONS: 96 if orientation == 'flip': 97 comp_chart = np.flipud(patch) 98 elif orientation == 'mirror': 99 comp_chart = np.fliplr(patch) 100 elif orientation == 'rotate': 101 comp_chart = np.flipud(np.fliplr(patch)) 102 correlation = cv2.matchTemplate(comp_chart, template, cv2.TM_CCOEFF) 103 _, opt_val, _, _ = cv2.minMaxLoc(correlation) 104 if debug: 105 cv2.imwrite('%s_%s.jpg' % (NAME, orientation), comp_chart) 106 print ' %s correlation value: %d' % (orientation, opt_val) 107 opts.append(opt_val) 108 109 # determine if 'nominal' or 'rotated' is best orientation 110 assert_flag = (opts[0] == max(opts) or opts[3] == max(opts)) 111 assert assert_flag, ('Optimum orientation is %s' % 112 CHART_ORIENTATIONS[np.argmax(opts)]) 113 # print warning if rotated 114 if opts[3] == max(opts): 115 print 'Image is rotated 180 degrees. Try "rotate" flag.' 116 117 118def main(): 119 """Test if image is properly oriented.""" 120 121 print '\nStarting test_flip_mirror.py' 122 123 # check skip conditions 124 with its.device.ItsSession() as cam: 125 props = cam.get_camera_properties() 126 its.caps.skip_unless(its.caps.read_3a(props)) 127 # initialize chart class and locate chart in scene 128 chart = its.cv2image.Chart(CHART_FILE, CHART_HEIGHT, CHART_DISTANCE, 129 CHART_SCALE_START, CHART_SCALE_STOP, 130 CHART_SCALE_STEP) 131 132 with its.device.ItsSession() as cam: 133 fmt = {'format': 'yuv', 'width': VGA_WIDTH, 'height': VGA_HEIGHT} 134 135 # test that image is not flipped, mirrored, or rotated 136 test_flip_mirror(cam, props, fmt, chart) 137 138 139if __name__ == '__main__': 140 main() 141