blob: e31d123df7a7d0ff0c8fee5fb70dbe6e723f687c [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Import guard for OpenCV.
try:
import cv
import cv2
except ImportError:
pass
import colorsys
import math
import numpy as np
# Color constants.
_COLORS = {
'important': (0, 0, 255),
'corner': (0, 255, 255),
'success': (0, 255, 0),
'deviation': (255, 0, 255),
}
_UPSAMPLING_SCALE = 8
_UPSAMPLING_BITS = 3
def _DrawLineByAngle(img, origin, length, angle, color,
thickness):
'''Draw a line by specifying the origin, length and angle.'''
dx1 = length * math.cos(angle)
dy1 = length * math.sin(angle)
cv2.line(img, origin, (origin[0] + dx1, origin[1] + dy1), color,
thickness, lineType=cv2.CV_AA)
def _DrawArrowTip(img, tip, direction, tip_length, tip_angle, color,
thickness):
'''Draw an arrow tip.'''
theta1 = math.radians(direction + 180 + tip_angle)
_DrawLineByAngle(img, tip, tip_length, theta1, color, thickness)
theta2 = math.radians(direction + 180 - tip_angle)
_DrawLineByAngle(img, tip, tip_length, theta2, color, thickness)
def _DrawArcWithArrow(img, center, radius, start_angle, delta_angle,
tip_length, tip_angle, color, thickness):
'''Draw an arc with an arrow tip on one end.'''
# Draw arc.
cv2.ellipse(img, center, (radius, radius), start_angle,
(0 if delta_angle > 0 else -delta_angle),
(-delta_angle if delta_angle > 0 else 0), color, thickness,
lineType=cv2.CV_AA)
# Draw arrow tip.
# The minus sign is because the y axis is reversed for the actual image.
tip_point_angle = -(start_angle + delta_angle)
tip = (center[0] + radius * math.cos(math.radians(tip_point_angle)),
center[1] + radius * math.sin(math.radians(tip_point_angle)))
_DrawArrowTip(img, tip,
tip_point_angle - (90 if delta_angle > 0 else -90),
tip_length, tip_angle, color, thickness)
def DrawVC(img, success, result):
'''Draw the result of the visual correctness test on the test image.'''
if hasattr(result, 'sample_corners'):
# Draw all corners.
for point in result.sample_corners:
cv2.circle(img, (point[0], point[1]), 2, _COLORS['corner'],
thickness=-1)
if hasattr(result, 'shift'):
# Draw the four corners of the corner grid.
for point in result.four_corners:
cv2.circle(img, (point[0], point[1]), 4,
_COLORS[('success' if success else 'important')],
thickness = -1, lineType=cv2.CV_AA)
# Draw the center and the shift vector.
center = ((img.shape[1] - 1) / 2.0, (img.shape[0] - 1) / 2.0)
tip = np.array(center) + result.v_shift
cv2.line(img, center, (tip[0], tip[1]),
_COLORS['deviation'], thickness=2, lineType=cv2.CV_AA)
diag_len = math.sqrt(img.shape[0] ** 2 + img.shape[1] ** 2)
angle = math.atan2(result.v_shift[1], result.v_shift[0])
_DrawArrowTip(img, (tip[0], tip[1]), math.degrees(angle),
result.shift * diag_len * 0.3, 60,
_COLORS['deviation'], thickness=2)
cv2.circle(img, center, 4,
_COLORS[('success' if success else 'important')],
thickness=-1, lineType=cv2.CV_AA)
# Draw the rotation indicator.
radius = max(img.shape) / 4
# Boost the amount so it is more easily visible.
angle = max(-90, min(90, result.tilt * 10))
tip_length = abs(math.radians(angle)) * radius * 0.3
tip_angle = 60
_DrawArcWithArrow(img, center, radius, 0, angle,
tip_length, tip_angle,
_COLORS['deviation'], thickness=2)
_DrawArcWithArrow(img, center, radius, 180, angle,
tip_length, tip_angle,
_COLORS['deviation'], thickness=2)
def _HSVToBGR(h, s, v, scale=255):
'''Convert from the HSV color space to BGR.'''
fc = colorsys.hsv_to_rgb(h, s, v)
return tuple([int(round(x * scale)) for x in fc[::-1]])
def _Up(x):
'''Encode floating point values in integers.'''
return np.floor(x * _UPSAMPLING_SCALE + 0.5)
def DrawMTF(img, edges, perm, mtfs, crop_ratio, color_map_range):
'''Draw the result of the image sharpness test on the test image.'''
# Map MTF values to hue values.
hues = ((mtfs - color_map_range[0]) /
(color_map_range[1] - color_map_range[0])) / 3.0
np.clip(hues, 0.0, 1.0/3, out=hues)
# Draw the edges.
for idx, edge_id in enumerate(perm):
edge = edges[edge_id]
start = (1 - crop_ratio) * edge[0:2] + crop_ratio * edge[2:4]
end = crop_ratio * edge[0:2] + (1 - crop_ratio) * edge[2:4]
cv2.line(img, tuple(_Up(start)), tuple(_Up(end)),
_HSVToBGR(hues[idx], 1.0, 1.0), thickness=2,
shift=_UPSAMPLING_BITS, lineType=cv2.CV_AA)