image_ops_test.cc revision 9d56f419cf3a92fb4c66943f216d3632c940b9db
1/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 3Licensed under the Apache License, Version 2.0 (the "License"); 4 5You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9Unless required by applicable law or agreed to in writing, software 10distributed under the License is distributed on an "AS IS" BASIS, 11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12See the License for the specific language governing permissions and 13limitations under the License. 14==============================================================================*/ 15 16#include "tensorflow/core/framework/node_def_builder.h" 17#include "tensorflow/core/framework/op.h" 18#include "tensorflow/core/framework/shape_inference_testutil.h" 19#include "tensorflow/core/framework/tensor_testutil.h" 20#include "tensorflow/core/lib/core/status_test_util.h" 21#include "tensorflow/core/platform/test.h" 22 23namespace tensorflow { 24 25TEST(ImageOpsTest, SampleDistortedBoundingBox_ShapeFn) { 26 ShapeInferenceTestOp op("SampleDistortedBoundingBox"); 27 INFER_OK(op, "?;?", "[3];[3];[1,1,4]"); 28} 29 30TEST(ImageOpsTest, Resize_ShapeFn) { 31 for (const char* op_name : {"ResizeArea", "ResizeBicubic", "ResizeBilinear", 32 "ResizeNearestNeighbor"}) { 33 ShapeInferenceTestOp op(op_name); 34 op.input_tensors.resize(2); 35 36 // Inputs are images and size. 37 38 // Rank and size checks. 39 INFER_ERROR("Shape must be rank 4 but is rank 5", op, "[1,2,3,4,5];?"); 40 INFER_ERROR("Shape must be rank 4 but is rank 3", op, "[1,2,3];?"); 41 INFER_ERROR("Shape must be rank 1 but is rank 0", op, "?;[]"); 42 INFER_ERROR("Dimension must be 2 but is 3", op, "?;[3]"); 43 44 // When the size tensor is not a constant, the middle dims are unknown. 45 INFER_OK(op, "[1,?,3,?];[2]", "[d0_0,?,?,d0_3]"); 46 47 Tensor size_tensor = test::AsTensor<int32>({20, 30}); 48 op.input_tensors[1] = &size_tensor; 49 INFER_OK(op, "[1,?,3,?];[2]", "[d0_0,20,30,d0_3]"); 50 } 51} 52 53TEST(ImageOpsTest, DecodeGif) { 54 ShapeInferenceTestOp op("DecodeGif"); 55 56 // Rank check. 57 INFER_ERROR("Shape must be rank 0 but is rank 1", op, "[1]"); 58 59 // Output is always ?,?,?,3. 60 INFER_OK(op, "?", "[?,?,?,3]"); 61 INFER_OK(op, "[]", "[?,?,?,3]"); 62} 63 64TEST(ImageOpsTest, DecodeImage_ShapeFn) { 65 for (const char* op_name : {"DecodeJpeg", "DecodePng"}) { 66 ShapeInferenceTestOp op(op_name); 67 68 // Rank check. 69 INFER_ERROR("Shape must be rank 0 but is rank 1", op, "[1]"); 70 71 // Set the channel to zero - output is not known. 72 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 73 .Input({"a", 0, DT_STRING}) 74 .Finalize(&op.node_def)); 75 INFER_OK(op, "[]", "[?,?,?]"); 76 77 // Set the channel and so that part of output shape is known. 78 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 79 .Input({"a", 0, DT_STRING}) 80 .Attr("channels", 4) 81 .Finalize(&op.node_def)); 82 INFER_OK(op, "[]", "[?,?,4]"); 83 84 // Negative channel value is rejected. 85 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 86 .Input({"a", 0, DT_STRING}) 87 .Attr("channels", -1) 88 .Finalize(&op.node_def)); 89 INFER_ERROR("channels must be non-negative, got -1", op, "[]"); 90 } 91} 92 93TEST(ImageOpsTest, DecodeAndCropJpeg_ShapeFn) { 94 const char* op_name = "DecodeAndCropJpeg"; 95 ShapeInferenceTestOp op(op_name); 96 97 // Check the number of inputs. 98 INFER_ERROR("Wrong number of inputs passed: 1 while 2 expected", op, "[1]"); 99 100 // Rank check. 101 INFER_ERROR("Shape must be rank 0 but is rank 1", op, "[1];?"); 102 103 // Set the channel to zero - output is not known. 104 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 105 .Input({"img", 0, DT_STRING}) 106 .Input({"crop_window", 1, DT_INT32}) 107 .Finalize(&op.node_def)); 108 INFER_OK(op, "[];[]", "[?,?,?]"); 109 110 // Set the channel, so that part of output shape is known. 111 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 112 .Input({"img", 0, DT_STRING}) 113 .Input({"crop_window", 1, DT_INT32}) 114 .Attr("channels", 4) 115 .Finalize(&op.node_def)); 116 INFER_OK(op, "[];[]", "[?,?,4]"); 117 118 // Negative channel value is rejected. 119 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 120 .Input({"img", 0, DT_STRING}) 121 .Input({"crop_window", 1, DT_INT32}) 122 .Attr("channels", -1) 123 .Finalize(&op.node_def)); 124 INFER_ERROR("channels must be non-negative, got -1", op, "[];[]"); 125} 126 127TEST(ImageOpsTest, DecodeAndCropJpeg_InvalidCropWindow) { 128 const char* op_name = "DecodeAndCropJpeg"; 129 ShapeInferenceTestOp op(op_name); 130 131 // Check the number of inputs. 132 INFER_ERROR("Wrong number of inputs passed: 1 while 2 expected", op, "[1]"); 133 134 // Rank check. 135 INFER_ERROR("Shape must be rank 0 but is rank 1", op, "[1];?"); 136 137 // Set the channel to zero - output is not known. 138 TF_ASSERT_OK(NodeDefBuilder("test", op_name) 139 .Input({"img", 0, DT_STRING}) 140 .Input({"crop_window", 1, DT_INT32}) 141 .Finalize(&op.node_def)); 142 INFER_OK(op, "[];[]", "[?,?,?]"); 143} 144 145TEST(ImageOpsTest, EncodeImage_ShapeFn) { 146 for (const char* op_name : {"EncodeJpeg", "EncodePng"}) { 147 ShapeInferenceTestOp op(op_name); 148 149 // Rank check. 150 INFER_ERROR("Shape must be rank 3 but is rank 2", op, "[1,2]"); 151 152 INFER_OK(op, "[1,?,3]", "[]"); // output is always scalar. 153 } 154} 155 156TEST(ImageOpsTest, ExtractJpegShape_ShapeFn) { 157 ShapeInferenceTestOp op("ExtractJpegShape"); 158 159 // Rank check. 160 INFER_ERROR("Shape must be rank 0 but is rank 1", op, "[1]"); 161 162 // Only specify input data. Output must be a 1-D tensor with 3 elements. 163 INFER_OK(op, "?", "[3]"); 164} 165 166TEST(ImageOpsTest, Colorspace_ShapeFn) { 167 for (const char* op_name : {"HSVToRGB", "RGBToHSV"}) { 168 ShapeInferenceTestOp op(op_name); 169 170 // Rank check. 171 INFER_ERROR("Shape must be at least rank 1 but is rank 0", op, "[]"); 172 173 // Input's last dim is required to be 3. 174 INFER_ERROR("Dimension must be 3 but is 4", op, "[1,2,4]"); 175 INFER_OK(op, "[1,2,3]", "[d0_0,d0_1,d0_2]"); 176 INFER_OK(op, "[1,2,?]", "[d0_0,d0_1,3]"); 177 INFER_OK(op, "?", "?"); 178 } 179} 180 181TEST(ImageOpsTest, ExtractGlimpse_ShapeFn) { 182 ShapeInferenceTestOp op("ExtractGlimpse"); 183 op.input_tensors.resize(2); 184 185 // Inputs are input, size, offsets. 186 187 // Rank and size checks. 188 INFER_ERROR("Shape must be rank 4 but is rank 5", op, "[1,2,3,4,5];?;?"); 189 INFER_ERROR("Shape must be rank 4 but is rank 3", op, "[1,2,3];?;?"); 190 INFER_ERROR("Shape must be rank 1 but is rank 0", op, "?;[];?"); 191 INFER_ERROR("Dimension must be 2 but is 3", op, "?;[3];?"); 192 INFER_ERROR("Shape must be rank 2 but is rank 3", op, "?;?;[1,2,3]"); 193 194 // When the size tensor is not a constant, the middle dims are unknown. 195 INFER_OK(op, "[1,?,3,?];[2];?", "[d0_0,?,?,d0_3]"); 196 197 Tensor size_tensor = test::AsTensor<int32>({20, 30}); 198 op.input_tensors[1] = &size_tensor; 199 INFER_OK(op, "[1,?,3,?];[2];?", "[d0_0,20,30,d0_3]"); 200 201 // input.dim(0) and offsets.dim(0) are both the batch dimension. 202 INFER_OK(op, "[?,?,3,?];[2];[1,?]", "[d2_0,20,30,d0_3]"); 203 INFER_OK(op, "[1,?,3,?];[2];[1,?]", "[d0_0|d2_0,20,30,d_0|d0_3]"); 204 INFER_ERROR("Dimensions must be equal, but are 10 and 1", op, 205 "[10,?,?,?];?;[1,2]"); 206} 207 208TEST(ImageOpsTest, CropAndResize_ShapeFn) { 209 ShapeInferenceTestOp op("CropAndResize"); 210 op.input_tensors.resize(4); 211 212 // Inputs are: input, boxes, box_ind, and crop_size. 213 214 // Rank and size checks. 215 INFER_ERROR("Shape must be rank 4 but is rank 5", op, "[1,2,3,4,5];?;?;?"); 216 INFER_ERROR("Shape must be rank 4 but is rank 3", op, "[1,2,3];?;?;?"); 217 INFER_ERROR("Shape must be rank 2 but is rank 3", op, "?;[1,2,3];?;?"); 218 INFER_ERROR("Shape must be rank 1 but is rank 2", op, "?;?;[1,2];?"); 219 INFER_ERROR("Shape must be rank 1 but is rank 2", op, "?;?;?;[1,2]"); 220 INFER_ERROR("Dimension must be 2 but is 1", op, "?;?;?;[1]"); 221 222 // When the size tensor is not a constant, the middle dims are unknown. 223 INFER_OK(op, "[1,?,3,?];?;?;[2]", "[?,?,?,d0_3]"); 224 225 Tensor size_tensor = test::AsTensor<int32>({20, 30}); 226 op.input_tensors[3] = &size_tensor; 227 INFER_OK(op, "[1,?,3,?];?;?;[2]", "[?,20,30,d0_3]"); 228 229 // boxes.dim(0) and box_ind.dim(0) are both the num_boxes dim. 230 INFER_OK(op, "[1,?,3,?];[2,4];?;[2]", "[d1_0,20,30,d0_3]"); 231 INFER_OK(op, "[1,?,3,?];?;[2];[2]", "[d2_0,20,30,d0_3]"); 232 INFER_OK(op, "[1,?,3,?];[?,4];[?];[2]", "[d1_0|d3_0,20,30,d0_3]"); 233 INFER_ERROR("Dimensions must be equal, but are 2 and 1", op, "?;[2,?];[1];?"); 234 235 // boxes.dim(1) must be 4. 236 INFER_ERROR("Dimension must be 4 but is 3", op, "?;[?,3];?;?"); 237} 238 239TEST(ImageOpsTest, ResizeNearestNeighborGrad_ShapeFn) { 240 ShapeInferenceTestOp op("ResizeNearestNeighborGrad"); 241 op.input_tensors.resize(2); 242 243 // Rank and size checks. 244 INFER_ERROR("Shape must be rank 4 but is rank 3", op, "[1,2,3];?"); 245 INFER_ERROR("Shape must be rank 1 but is rank 2", op, "?;[1,2]") 246 INFER_ERROR("Dimension must be 2 but is 1", op, "?;[1]"); 247 248 // When the size tensor is not a constant, the middle dims are unknown. 249 INFER_OK(op, "[1,?,3,?];[2]", "[d0_0,?,?,d0_3]"); 250 251 Tensor size_tensor = test::AsTensor<int32>({20, 30}); 252 op.input_tensors[1] = &size_tensor; 253 INFER_OK(op, "[1,?,3,?];[2]", "[d0_0,20,30,d0_3]"); 254} 255 256TEST(ImageOpsTest, CropAndResizeGradImage_ShapeFn) { 257 ShapeInferenceTestOp op("CropAndResizeGradImage"); 258 op.input_tensors.resize(4); 259 260 // Rank checks. 261 INFER_ERROR("Shape must be rank 1 but is rank 2", op, "?;?;?;[1,2]"); 262 263 // Unknown image_size should result in output of rank 4 with unknown dims. 264 INFER_OK(op, "?;?;?;?", "[?,?,?,?]"); 265 266 // Known image_size should result in full shape information. 267 Tensor image_size = test::AsTensor<int32>({10, 20, 30, 40}); 268 op.input_tensors[3] = &image_size; 269 INFER_OK(op, "?;?;?;[1]", "[10, 20, 30, 40]"); 270} 271 272TEST(ImageOpsTest, RandomCrop_ShapeFn) { 273 ShapeInferenceTestOp op("RandomCrop"); 274 op.input_tensors.resize(2); 275 276 // Rank checks. 277 INFER_ERROR("must be rank 3", op, "[1,2];?"); 278 INFER_ERROR("must be equal", op, "?;[3]"); 279 INFER_ERROR("must be equal", op, "?;[1,2]"); 280 281 // Unknown size tensor values. 282 INFER_OK(op, "[?,?,?];[2]", "[?,?,d0_2]"); 283 284 // Known size should result in full shape information. 285 Tensor size = test::AsTensor<int64>({10, 20}); 286 op.input_tensors[1] = &size; 287 INFER_OK(op, "[?,?,?];[2]", "[10,20,d0_2]"); 288} 289 290TEST(ImageOpsTest, QuantizedResizeBilinear_ShapeFn) { 291 ShapeInferenceTestOp op("QuantizedResizeBilinear"); 292 op.input_tensors.resize(4); 293 294 NodeDefBuilder builder = 295 NodeDefBuilder("test", "QuantizedResizeBilinear") 296 .Input(NodeDefBuilder::NodeOut{"images", 0, DT_QINT32}) 297 .Input(NodeDefBuilder::NodeOut{"size", 0, DT_INT32}) 298 .Input(NodeDefBuilder::NodeOut{"min", 0, DT_FLOAT}) 299 .Input(NodeDefBuilder::NodeOut{"max", 0, DT_FLOAT}) 300 .Attr("T", DT_QINT32) 301 .Attr("Toutput", DT_QINT32); 302 TF_ASSERT_OK(builder.Finalize(&op.node_def)); 303 304 // When the size tensor is not a constant, the middle dims are unknown. 305 INFER_OK(op, "[1,?,3,?];[2];[];[]", 306 "[d0_0,?,?,d0_3];[];[]"); // output rank unknown 307 INFER_ERROR("must be rank 0", op, "[1,?,3,?];[2];[?];[]"); 308 INFER_ERROR("must be rank 0", op, "[1,?,3,?];[2];[];[?]"); 309 310 const Tensor size_tensor = test::AsTensor<int32>({20, 30}); 311 op.input_tensors.at(1) = &size_tensor; 312 INFER_OK(op, "[1,?,3,?];[2];[];[]", "[d0_0,20,30,d0_3];[];[]"); 313} 314 315} // end namespace tensorflow 316