• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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