1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 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"""Python layer for distort_image_ops.""" 16from __future__ import absolute_import 17from __future__ import division 18from __future__ import print_function 19 20from tensorflow.contrib.image.ops import gen_distort_image_ops 21from tensorflow.contrib.util import loader 22from tensorflow.python.framework import dtypes 23from tensorflow.python.framework import ops 24from tensorflow.python.ops import image_ops 25from tensorflow.python.ops import random_ops 26from tensorflow.python.platform import resource_loader 27 28_distort_image_ops = loader.load_op_library( 29 resource_loader.get_path_to_datafile('_distort_image_ops.so')) 30 31 32# pylint: disable=invalid-name 33def random_hsv_in_yiq(image, 34 max_delta_hue=0, 35 lower_saturation=1, 36 upper_saturation=1, 37 lower_value=1, 38 upper_value=1, 39 seed=None): 40 """Adjust hue, saturation, value of an RGB image randomly in YIQ color space. 41 42 Equivalent to `adjust_yiq_hsv()` but uses a `delta_h` randomly 43 picked in the interval `[-max_delta_hue, max_delta_hue]`, a `scale_saturation` 44 randomly picked in the interval `[lower_saturation, upper_saturation]`, and 45 a `scale_value` randomly picked in the interval 46 `[lower_saturation, upper_saturation]`. 47 48 Args: 49 image: RGB image or images. Size of the last dimension must be 3. 50 max_delta_hue: float. Maximum value for the random delta_hue. Passing 0 51 disables adjusting hue. 52 lower_saturation: float. Lower bound for the random scale_saturation. 53 upper_saturation: float. Upper bound for the random scale_saturation. 54 lower_value: float. Lower bound for the random scale_value. 55 upper_value: float. Upper bound for the random scale_value. 56 seed: An operation-specific seed. It will be used in conjunction 57 with the graph-level seed to determine the real seeds that will be 58 used in this operation. Please see the documentation of 59 set_random_seed for its interaction with the graph-level random seed. 60 61 Returns: 62 3-D float tensor of shape `[height, width, channels]`. 63 64 Raises: 65 ValueError: if `max_delta`, `lower_saturation`, `upper_saturation`, 66 `lower_value`, or `upper_Value` is invalid. 67 """ 68 if max_delta_hue < 0: 69 raise ValueError('max_delta must be non-negative.') 70 71 if lower_saturation < 0: 72 raise ValueError('lower_saturation must be non-negative.') 73 74 if lower_value < 0: 75 raise ValueError('lower_value must be non-negative.') 76 77 if lower_saturation > upper_saturation: 78 raise ValueError('lower_saturation must be < upper_saturation.') 79 80 if lower_value > upper_value: 81 raise ValueError('lower_value must be < upper_value.') 82 83 if max_delta_hue == 0: 84 delta_hue = 0 85 else: 86 delta_hue = random_ops.random_uniform( 87 [], -max_delta_hue, max_delta_hue, seed=seed) 88 if lower_saturation == upper_saturation: 89 scale_saturation = lower_saturation 90 else: 91 scale_saturation = random_ops.random_uniform( 92 [], lower_saturation, upper_saturation, seed=seed) 93 if lower_value == upper_value: 94 scale_value = lower_value 95 else: 96 scale_value = random_ops.random_uniform( 97 [], lower_value, upper_value, seed=seed) 98 return adjust_hsv_in_yiq(image, delta_hue, scale_saturation, scale_value) 99 100 101def adjust_hsv_in_yiq(image, 102 delta_hue=0, 103 scale_saturation=1, 104 scale_value=1, 105 name=None): 106 """Adjust hue, saturation, value of an RGB image in YIQ color space. 107 108 This is a convenience method that converts an RGB image to float 109 representation, converts it to YIQ, rotates the color around the Y channel by 110 delta_hue in radians, scales the chrominance channels (I, Q) by 111 scale_saturation, scales all channels (Y, I, Q) by scale_value, 112 converts back to RGB, and then back to the original data type. 113 114 `image` is an RGB image. The image hue is adjusted by converting the 115 image to YIQ, rotating around the luminance channel (Y) by 116 `delta_hue` in radians, multiplying the chrominance channels (I, Q) by 117 `scale_saturation`, and multiplying all channels (Y, I, Q) by 118 `scale_value`. The image is then converted back to RGB. 119 120 Args: 121 image: RGB image or images. Size of the last dimension must be 3. 122 delta_hue: float, the hue rotation amount, in radians. 123 scale_saturation: float, factor to multiply the saturation by. 124 scale_value: float, factor to multiply the value by. 125 name: A name for this operation (optional). 126 127 Returns: 128 Adjusted image(s), same shape and DType as `image`. 129 """ 130 with ops.name_scope(name, 'adjust_hsv_in_yiq', [image]) as name: 131 image = ops.convert_to_tensor(image, name='image') 132 # Remember original dtype to so we can convert back if needed 133 orig_dtype = image.dtype 134 flt_image = image_ops.convert_image_dtype(image, dtypes.float32) 135 136 rgb_altered = gen_distort_image_ops.adjust_hsv_in_yiq( 137 flt_image, delta_hue, scale_saturation, scale_value) 138 139 return image_ops.convert_image_dtype(rgb_altered, orig_dtype) 140