cxx11_tensor_image_patch.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #include "main.h"
11 
12 #include <Eigen/CXX11/Tensor>
13 
14 using Eigen::Tensor;
15 
17 {
18  Tensor<float, 4> tensor(2,3,5,7);
19  tensor.setRandom();
20  Tensor<float, 4, RowMajor> tensor_row_major = tensor.swap_layout();
21  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(3));
22  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(2));
23  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(1));
24  VERIFY_IS_EQUAL(tensor.dimension(3), tensor_row_major.dimension(0));
25 
26  // Single pixel patch: ColMajor
27  Tensor<float, 5> single_pixel_patch;
28  single_pixel_patch = tensor.extract_image_patches(1, 1);
29  VERIFY_IS_EQUAL(single_pixel_patch.dimension(0), 2);
30  VERIFY_IS_EQUAL(single_pixel_patch.dimension(1), 1);
31  VERIFY_IS_EQUAL(single_pixel_patch.dimension(2), 1);
32  VERIFY_IS_EQUAL(single_pixel_patch.dimension(3), 3*5);
33  VERIFY_IS_EQUAL(single_pixel_patch.dimension(4), 7);
34 
35  // Single pixel patch: RowMajor
36  Tensor<float, 5, RowMajor> single_pixel_patch_row_major;
37  single_pixel_patch_row_major = tensor_row_major.extract_image_patches(1, 1);
38  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(0), 7);
39  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(1), 3*5);
40  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(2), 1);
41  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(3), 1);
42  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(4), 2);
43 
44  for (int i = 0; i < tensor.size(); ++i) {
45  // ColMajor
46  if (tensor.data()[i] != single_pixel_patch.data()[i]) {
47  std::cout << "Mismatch detected at index " << i << " : "
48  << tensor.data()[i] << " vs " << single_pixel_patch.data()[i]
49  << std::endl;
50  }
51  VERIFY_IS_EQUAL(single_pixel_patch.data()[i], tensor.data()[i]);
52  // RowMajor
53  if (tensor_row_major.data()[i] != single_pixel_patch_row_major.data()[i]) {
54  std::cout << "Mismatch detected at index " << i << " : "
55  << tensor.data()[i] << " vs "
56  << single_pixel_patch_row_major.data()[i] << std::endl;
57  }
58  VERIFY_IS_EQUAL(single_pixel_patch_row_major.data()[i],
59  tensor_row_major.data()[i]);
60  VERIFY_IS_EQUAL(tensor.data()[i], tensor_row_major.data()[i]);
61  VERIFY_IS_EQUAL(single_pixel_patch.data()[i],
62  single_pixel_patch_row_major.data()[i]);
63  }
64 
65  // Entire image patch: ColMajor
66  Tensor<float, 5> entire_image_patch;
67  entire_image_patch = tensor.extract_image_patches(3, 5);
68  VERIFY_IS_EQUAL(entire_image_patch.dimension(0), 2);
69  VERIFY_IS_EQUAL(entire_image_patch.dimension(1), 3);
70  VERIFY_IS_EQUAL(entire_image_patch.dimension(2), 5);
71  VERIFY_IS_EQUAL(entire_image_patch.dimension(3), 3*5);
72  VERIFY_IS_EQUAL(entire_image_patch.dimension(4), 7);
73 
74  // Entire image patch: RowMajor
75  Tensor<float, 5, RowMajor> entire_image_patch_row_major;
76  entire_image_patch_row_major = tensor_row_major.extract_image_patches(3, 5);
77  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(0), 7);
78  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(1), 3*5);
79  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(2), 5);
80  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(3), 3);
81  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(4), 2);
82 
83  for (int i = 0; i < 3; ++i) {
84  for (int j = 0; j < 5; ++j) {
85  int patchId = i+3*j;
86  for (int r = 0; r < 3; ++r) {
87  for (int c = 0; c < 5; ++c) {
88  for (int d = 0; d < 2; ++d) {
89  for (int b = 0; b < 7; ++b) {
90  float expected = 0.0f;
91  float expected_row_major = 0.0f;
92  if (r-1+i >= 0 && c-2+j >= 0 && r-1+i < 3 && c-2+j < 5) {
93  expected = tensor(d, r-1+i, c-2+j, b);
94  expected_row_major = tensor_row_major(b, c-2+j, r-1+i, d);
95  }
96  // ColMajor
97  if (entire_image_patch(d, r, c, patchId, b) != expected) {
98  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
99  }
100  VERIFY_IS_EQUAL(entire_image_patch(d, r, c, patchId, b), expected);
101  // RowMajor
102  if (entire_image_patch_row_major(b, patchId, c, r, d) !=
103  expected_row_major) {
104  std::cout << "Mismatch detected at index i=" << i << " j=" << j
105  << " r=" << r << " c=" << c << " d=" << d << " b=" << b
106  << std::endl;
107  }
108  VERIFY_IS_EQUAL(entire_image_patch_row_major(b, patchId, c, r, d),
109  expected_row_major);
110  // Check that ColMajor and RowMajor agree.
111  VERIFY_IS_EQUAL(expected, expected_row_major);
112  }
113  }
114  }
115  }
116  }
117  }
118 
119  // 2D patch: ColMajor
120  Tensor<float, 5> twod_patch;
121  twod_patch = tensor.extract_image_patches(2, 2);
122  VERIFY_IS_EQUAL(twod_patch.dimension(0), 2);
123  VERIFY_IS_EQUAL(twod_patch.dimension(1), 2);
124  VERIFY_IS_EQUAL(twod_patch.dimension(2), 2);
125  VERIFY_IS_EQUAL(twod_patch.dimension(3), 3*5);
126  VERIFY_IS_EQUAL(twod_patch.dimension(4), 7);
127 
128  // 2D patch: RowMajor
129  Tensor<float, 5, RowMajor> twod_patch_row_major;
130  twod_patch_row_major = tensor_row_major.extract_image_patches(2, 2);
131  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(0), 7);
132  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(1), 3*5);
133  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(2), 2);
134  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(3), 2);
135  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(4), 2);
136 
137 
138  // Based on the calculation described in TensorTraits.h, padding happens to be 0.
139  int row_padding = 0;
140  int col_padding = 0;
141  int stride = 1;
142 
143  for (int i = 0; i < 3; ++i) {
144  for (int j = 0; j < 5; ++j) {
145  int patchId = i+3*j;
146  for (int r = 0; r < 2; ++r) {
147  for (int c = 0; c < 2; ++c) {
148  for (int d = 0; d < 2; ++d) {
149  for (int b = 0; b < 7; ++b) {
150  float expected = 0.0f;
151  float expected_row_major = 0.0f;
152  int row_offset = r*stride + i - row_padding;
153  int col_offset = c*stride + j - col_padding;
154  // ColMajor
155  if (row_offset >= 0 && col_offset >= 0 && row_offset < tensor.dimension(1) && col_offset < tensor.dimension(2)) {
156  expected = tensor(d, row_offset, col_offset, b);
157  }
158  if (twod_patch(d, r, c, patchId, b) != expected) {
159  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
160  }
161  VERIFY_IS_EQUAL(twod_patch(d, r, c, patchId, b), expected);
162 
163  // RowMajor
164  if (row_offset >= 0 && col_offset >= 0 && row_offset < tensor_row_major.dimension(2) && col_offset < tensor_row_major.dimension(1)) {
165  expected_row_major = tensor_row_major(b, col_offset, row_offset, d);
166 
167  }
168  if (twod_patch_row_major(b, patchId, c, r, d) != expected_row_major) {
169  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
170  }
171  VERIFY_IS_EQUAL(twod_patch_row_major(b, patchId, c, r, d), expected_row_major);
172  // Check that ColMajor and RowMajor agree.
173  VERIFY_IS_EQUAL(expected, expected_row_major);
174  }
175  }
176  }
177  }
178  }
179  }
180 }
181 
182 // Verifies VALID padding (no padding) with incrementing values.
184 {
185  int input_depth = 3;
186  int input_rows = 3;
187  int input_cols = 3;
188  int input_batches = 1;
189  int ksize = 2; // Corresponds to the Rows and Cols for tensor.extract_image_patches<>.
190  int stride = 2; // Only same stride is supported.
191  Tensor<float, 4> tensor(input_depth, input_rows, input_cols, input_batches);
192  // Initializes tensor with incrementing numbers.
193  for (int i = 0; i < tensor.size(); ++i) {
194  tensor.data()[i] = i + 1;
195  }
196  // ColMajor
197  Tensor<float, 5> result = tensor.extract_image_patches(ksize, ksize, stride, stride, 1, 1, PADDING_VALID);
198 
199  VERIFY_IS_EQUAL(result.dimension(0), input_depth); // depth
200  VERIFY_IS_EQUAL(result.dimension(1), ksize); // kernel rows
201  VERIFY_IS_EQUAL(result.dimension(2), ksize); // kernel cols
202  VERIFY_IS_EQUAL(result.dimension(3), 1); // number of patches
203  VERIFY_IS_EQUAL(result.dimension(4), input_batches); // number of batches
204 
205  // RowMajor
206  Tensor<float, 4, RowMajor> tensor_row_major = tensor.swap_layout();
207  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(3));
208  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(2));
209  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(1));
210  VERIFY_IS_EQUAL(tensor.dimension(3), tensor_row_major.dimension(0));
211 
212  Tensor<float, 5, RowMajor> result_row_major = tensor_row_major.extract_image_patches(ksize, ksize, stride, stride, 1, 1, PADDING_VALID);
213  VERIFY_IS_EQUAL(result.dimension(0), result_row_major.dimension(4));
214  VERIFY_IS_EQUAL(result.dimension(1), result_row_major.dimension(3));
215  VERIFY_IS_EQUAL(result.dimension(2), result_row_major.dimension(2));
216  VERIFY_IS_EQUAL(result.dimension(3), result_row_major.dimension(1));
217  VERIFY_IS_EQUAL(result.dimension(4), result_row_major.dimension(0));
218 
219  // No padding is carried out.
220  int row_padding = 0;
221  int col_padding = 0;
222 
223  for (int i = 0; (i+stride+ksize-1) < input_rows; i += stride) { // input rows
224  for (int j = 0; (j+stride+ksize-1) < input_cols; j += stride) { // input cols
225  int patchId = i+input_rows*j;
226  for (int r = 0; r < ksize; ++r) { // patch rows
227  for (int c = 0; c < ksize; ++c) { // patch cols
228  for (int d = 0; d < input_depth; ++d) { // depth
229  for (int b = 0; b < input_batches; ++b) { // batch
230  float expected = 0.0f;
231  float expected_row_major = 0.0f;
232  int row_offset = r + i - row_padding;
233  int col_offset = c + j - col_padding;
234  if (row_offset >= 0 && col_offset >= 0 && row_offset < input_rows && col_offset < input_cols) {
235  expected = tensor(d, row_offset, col_offset, b);
236  expected_row_major = tensor_row_major(b, col_offset, row_offset, d);
237  }
238  // ColMajor
239  if (result(d, r, c, patchId, b) != expected) {
240  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
241  }
242  VERIFY_IS_EQUAL(result(d, r, c, patchId, b), expected);
243  // RowMajor
244  if (result_row_major(b, patchId, c, r, d) != expected_row_major) {
245  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
246  }
247  VERIFY_IS_EQUAL(result_row_major(b, patchId, c, r, d), expected_row_major);
248  // Check that ColMajor and RowMajor agree.
249  VERIFY_IS_EQUAL(expected, expected_row_major);
250  }
251  }
252  }
253  }
254  }
255  }
256 }
257 
258 // Verifies VALID padding (no padding) with the same value.
260 {
261  int input_depth = 1;
262  int input_rows = 5;
263  int input_cols = 5;
264  int input_batches = 2;
265  int ksize = 3; // Corresponds to the Rows and Cols for tensor.extract_image_patches<>.
266  int stride = 2; // Only same stride is supported.
267  // ColMajor
268  Tensor<float, 4> tensor(input_depth, input_rows, input_cols, input_batches);
269  tensor = tensor.constant(11.0f);
270  Tensor<float, 5> result = tensor.extract_image_patches(ksize, ksize, stride, stride, 1, 1, PADDING_VALID);
271 
272  VERIFY_IS_EQUAL(result.dimension(0), input_depth); // depth
273  VERIFY_IS_EQUAL(result.dimension(1), ksize); // kernel rows
274  VERIFY_IS_EQUAL(result.dimension(2), ksize); // kernel cols
275  VERIFY_IS_EQUAL(result.dimension(3), 4); // number of patches
276  VERIFY_IS_EQUAL(result.dimension(4), input_batches); // number of batches
277 
278  // RowMajor
279  Tensor<float, 4, RowMajor> tensor_row_major = tensor.swap_layout();
280  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(3));
281  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(2));
282  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(1));
283  VERIFY_IS_EQUAL(tensor.dimension(3), tensor_row_major.dimension(0));
284 
285  Tensor<float, 5, RowMajor> result_row_major = tensor_row_major.extract_image_patches(ksize, ksize, stride, stride, 1, 1, PADDING_VALID);
286  VERIFY_IS_EQUAL(result.dimension(0), result_row_major.dimension(4));
287  VERIFY_IS_EQUAL(result.dimension(1), result_row_major.dimension(3));
288  VERIFY_IS_EQUAL(result.dimension(2), result_row_major.dimension(2));
289  VERIFY_IS_EQUAL(result.dimension(3), result_row_major.dimension(1));
290  VERIFY_IS_EQUAL(result.dimension(4), result_row_major.dimension(0));
291 
292  // No padding is carried out.
293  int row_padding = 0;
294  int col_padding = 0;
295 
296  for (int i = 0; (i+stride+ksize-1) <= input_rows; i += stride) { // input rows
297  for (int j = 0; (j+stride+ksize-1) <= input_cols; j += stride) { // input cols
298  int patchId = i+input_rows*j;
299  for (int r = 0; r < ksize; ++r) { // patch rows
300  for (int c = 0; c < ksize; ++c) { // patch cols
301  for (int d = 0; d < input_depth; ++d) { // depth
302  for (int b = 0; b < input_batches; ++b) { // batch
303  float expected = 0.0f;
304  float expected_row_major = 0.0f;
305  int row_offset = r + i - row_padding;
306  int col_offset = c + j - col_padding;
307  if (row_offset >= 0 && col_offset >= 0 && row_offset < input_rows && col_offset < input_cols) {
308  expected = tensor(d, row_offset, col_offset, b);
309  expected_row_major = tensor_row_major(b, col_offset, row_offset, d);
310  }
311  // ColMajor
312  if (result(d, r, c, patchId, b) != expected) {
313  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
314  }
315  VERIFY_IS_EQUAL(result(d, r, c, patchId, b), expected);
316  // RowMajor
317  if (result_row_major(b, patchId, c, r, d) != expected_row_major) {
318  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
319  }
320  VERIFY_IS_EQUAL(result_row_major(b, patchId, c, r, d), expected_row_major);
321  // Check that ColMajor and RowMajor agree.
322  VERIFY_IS_EQUAL(expected, expected_row_major);
323  }
324  }
325  }
326  }
327  }
328  }
329 }
330 
331 // Verifies SAME padding.
333 {
334  int input_depth = 3;
335  int input_rows = 4;
336  int input_cols = 2;
337  int input_batches = 1;
338  int ksize = 2; // Corresponds to the Rows and Cols for tensor.extract_image_patches<>.
339  int stride = 2; // Only same stride is supported.
340  // ColMajor
341  Tensor<float, 4> tensor(input_depth, input_rows, input_cols, input_batches);
342  // Initializes tensor with incrementing numbers.
343  for (int i = 0; i < tensor.size(); ++i) {
344  tensor.data()[i] = i + 1;
345  }
346  Tensor<float, 5> result = tensor.extract_image_patches(ksize, ksize, stride, stride, PADDING_SAME);
347 
348  VERIFY_IS_EQUAL(result.dimension(0), input_depth); // depth
349  VERIFY_IS_EQUAL(result.dimension(1), ksize); // kernel rows
350  VERIFY_IS_EQUAL(result.dimension(2), ksize); // kernel cols
351  VERIFY_IS_EQUAL(result.dimension(3), 2); // number of patches
352  VERIFY_IS_EQUAL(result.dimension(4), input_batches); // number of batches
353 
354  // RowMajor
355  Tensor<float, 4, RowMajor> tensor_row_major = tensor.swap_layout();
356  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(3));
357  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(2));
358  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(1));
359  VERIFY_IS_EQUAL(tensor.dimension(3), tensor_row_major.dimension(0));
360 
361  Tensor<float, 5, RowMajor> result_row_major = tensor_row_major.extract_image_patches(ksize, ksize, stride, stride, PADDING_SAME);
362  VERIFY_IS_EQUAL(result.dimension(0), result_row_major.dimension(4));
363  VERIFY_IS_EQUAL(result.dimension(1), result_row_major.dimension(3));
364  VERIFY_IS_EQUAL(result.dimension(2), result_row_major.dimension(2));
365  VERIFY_IS_EQUAL(result.dimension(3), result_row_major.dimension(1));
366  VERIFY_IS_EQUAL(result.dimension(4), result_row_major.dimension(0));
367 
368  // Based on the calculation described in TensorTraits.h, padding happens to be
369  // 0.
370  int row_padding = 0;
371  int col_padding = 0;
372 
373  for (int i = 0; (i+stride+ksize-1) <= input_rows; i += stride) { // input rows
374  for (int j = 0; (j+stride+ksize-1) <= input_cols; j += stride) { // input cols
375  int patchId = i+input_rows*j;
376  for (int r = 0; r < ksize; ++r) { // patch rows
377  for (int c = 0; c < ksize; ++c) { // patch cols
378  for (int d = 0; d < input_depth; ++d) { // depth
379  for (int b = 0; b < input_batches; ++b) { // batch
380  float expected = 0.0f;
381  float expected_row_major = 0.0f;
382  int row_offset = r*stride + i - row_padding;
383  int col_offset = c*stride + j - col_padding;
384  if (row_offset >= 0 && col_offset >= 0 && row_offset < input_rows && col_offset < input_cols) {
385  expected = tensor(d, row_offset, col_offset, b);
386  expected_row_major = tensor_row_major(b, col_offset, row_offset, d);
387  }
388  // ColMajor
389  if (result(d, r, c, patchId, b) != expected) {
390  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
391  }
392  VERIFY_IS_EQUAL(result(d, r, c, patchId, b), expected);
393  // RowMajor
394  if (result_row_major(b, patchId, c, r, d) != expected_row_major) {
395  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
396  }
397  VERIFY_IS_EQUAL(result_row_major(b, patchId, c, r, d), expected_row_major);
398  // Check that ColMajor and RowMajor agree.
399  VERIFY_IS_EQUAL(expected, expected_row_major);
400  }
401  }
402  }
403  }
404  }
405  }
406 }
407 
408 // Verifies that SAME padding, when computed as negative values, will be clipped
409 // to zero.
411  int input_depth = 1;
412  int input_rows = 15;
413  int input_cols = 1;
414  int input_batches = 1;
415  int ksize = 1; // Corresponds to the Rows and Cols for
416  // tensor.extract_image_patches<>.
417  int row_stride = 5;
418  int col_stride = 1;
419  // ColMajor
420  Tensor<float, 4> tensor(input_depth, input_rows, input_cols, input_batches);
421  // Initializes tensor with incrementing numbers.
422  for (int i = 0; i < tensor.size(); ++i) {
423  tensor.data()[i] = i + 1;
424  }
425  Tensor<float, 5> result = tensor.extract_image_patches(
426  ksize, ksize, row_stride, col_stride, 1, 1, PADDING_SAME);
427  // row padding will be computed as -2 originally and then be clipped to 0.
428  VERIFY_IS_EQUAL(result.coeff(0), 1.0f);
429  VERIFY_IS_EQUAL(result.coeff(1), 6.0f);
430  VERIFY_IS_EQUAL(result.coeff(2), 11.0f);
431 
432  VERIFY_IS_EQUAL(result.dimension(0), input_depth); // depth
433  VERIFY_IS_EQUAL(result.dimension(1), ksize); // kernel rows
434  VERIFY_IS_EQUAL(result.dimension(2), ksize); // kernel cols
435  VERIFY_IS_EQUAL(result.dimension(3), 3); // number of patches
436  VERIFY_IS_EQUAL(result.dimension(4), input_batches); // number of batches
437 
438  // RowMajor
439  Tensor<float, 4, RowMajor> tensor_row_major = tensor.swap_layout();
440  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(3));
441  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(2));
442  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(1));
443  VERIFY_IS_EQUAL(tensor.dimension(3), tensor_row_major.dimension(0));
444 
445  Tensor<float, 5, RowMajor> result_row_major =
446  tensor_row_major.extract_image_patches(ksize, ksize, row_stride,
447  col_stride, 1, 1, PADDING_SAME);
448  VERIFY_IS_EQUAL(result_row_major.coeff(0), 1.0f);
449  VERIFY_IS_EQUAL(result_row_major.coeff(1), 6.0f);
450  VERIFY_IS_EQUAL(result_row_major.coeff(2), 11.0f);
451 
452  VERIFY_IS_EQUAL(result.dimension(0), result_row_major.dimension(4));
453  VERIFY_IS_EQUAL(result.dimension(1), result_row_major.dimension(3));
454  VERIFY_IS_EQUAL(result.dimension(2), result_row_major.dimension(2));
455  VERIFY_IS_EQUAL(result.dimension(3), result_row_major.dimension(1));
456  VERIFY_IS_EQUAL(result.dimension(4), result_row_major.dimension(0));
457 }
458 
460 {
461  Tensor<float, 3> tensor(2,3,5);
462  tensor.setRandom();
463  Tensor<float, 3, RowMajor> tensor_row_major = tensor.swap_layout();
464  VERIFY_IS_EQUAL(tensor.dimension(0), tensor_row_major.dimension(2));
465  VERIFY_IS_EQUAL(tensor.dimension(1), tensor_row_major.dimension(1));
466  VERIFY_IS_EQUAL(tensor.dimension(2), tensor_row_major.dimension(0));
467 
468  // Single pixel patch: ColMajor
469  Tensor<float, 4> single_pixel_patch;
470  single_pixel_patch = tensor.extract_image_patches(1, 1);
471  VERIFY_IS_EQUAL(single_pixel_patch.dimension(0), 2);
472  VERIFY_IS_EQUAL(single_pixel_patch.dimension(1), 1);
473  VERIFY_IS_EQUAL(single_pixel_patch.dimension(2), 1);
474  VERIFY_IS_EQUAL(single_pixel_patch.dimension(3), 3*5);
475 
476  // Single pixel patch: RowMajor
477  Tensor<float, 4, RowMajor> single_pixel_patch_row_major;
478  single_pixel_patch_row_major = tensor_row_major.extract_image_patches(1, 1);
479  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(0), 3*5);
480  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(1), 1);
481  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(2), 1);
482  VERIFY_IS_EQUAL(single_pixel_patch_row_major.dimension(3), 2);
483 
484  for (int i = 0; i < tensor.size(); ++i) {
485  // ColMajor
486  if (tensor.data()[i] != single_pixel_patch.data()[i]) {
487  std::cout << "Mismatch detected at index " << i << " : " << tensor.data()[i] << " vs " << single_pixel_patch.data()[i] << std::endl;
488  }
489  VERIFY_IS_EQUAL(single_pixel_patch.data()[i], tensor.data()[i]);
490  // RowMajor
491  if (tensor_row_major.data()[i] != single_pixel_patch_row_major.data()[i]) {
492  std::cout << "Mismatch detected at index " << i << " : "
493  << tensor.data()[i] << " vs "
494  << single_pixel_patch_row_major.data()[i] << std::endl;
495  }
496  VERIFY_IS_EQUAL(single_pixel_patch_row_major.data()[i],
497  tensor_row_major.data()[i]);
498  VERIFY_IS_EQUAL(tensor.data()[i], tensor_row_major.data()[i]);
499  VERIFY_IS_EQUAL(single_pixel_patch.data()[i],
500  single_pixel_patch_row_major.data()[i]);
501  }
502 
503  // Entire image patch: ColMajor
504  Tensor<float, 4> entire_image_patch;
505  entire_image_patch = tensor.extract_image_patches(3, 5);
506  VERIFY_IS_EQUAL(entire_image_patch.dimension(0), 2);
507  VERIFY_IS_EQUAL(entire_image_patch.dimension(1), 3);
508  VERIFY_IS_EQUAL(entire_image_patch.dimension(2), 5);
509  VERIFY_IS_EQUAL(entire_image_patch.dimension(3), 3*5);
510 
511  // Entire image patch: RowMajor
512  Tensor<float, 4, RowMajor> entire_image_patch_row_major;
513  entire_image_patch_row_major = tensor_row_major.extract_image_patches(3, 5);
514  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(0), 3*5);
515  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(1), 5);
516  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(2), 3);
517  VERIFY_IS_EQUAL(entire_image_patch_row_major.dimension(3), 2);
518 
519  for (int i = 0; i < 3; ++i) {
520  for (int j = 0; j < 5; ++j) {
521  int patchId = i+3*j;
522  for (int r = 0; r < 3; ++r) {
523  for (int c = 0; c < 5; ++c) {
524  for (int d = 0; d < 2; ++d) {
525  float expected = 0.0f;
526  float expected_row_major = 0.0f;
527  if (r-1+i >= 0 && c-2+j >= 0 && r-1+i < 3 && c-2+j < 5) {
528  expected = tensor(d, r-1+i, c-2+j);
529  expected_row_major = tensor_row_major(c-2+j, r-1+i, d);
530  }
531  // ColMajor
532  if (entire_image_patch(d, r, c, patchId) != expected) {
533  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << std::endl;
534  }
535  VERIFY_IS_EQUAL(entire_image_patch(d, r, c, patchId), expected);
536  // RowMajor
537  if (entire_image_patch_row_major(patchId, c, r, d) !=
538  expected_row_major) {
539  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << std::endl;
540  }
541  VERIFY_IS_EQUAL(entire_image_patch_row_major(patchId, c, r, d),
542  expected_row_major);
543  // Check that ColMajor and RowMajor agree.
544  VERIFY_IS_EQUAL(expected, expected_row_major);
545  }
546  }
547  }
548  }
549  }
550 
551  // 2D patch: ColMajor
552  Tensor<float, 4> twod_patch;
553  twod_patch = tensor.extract_image_patches(2, 2);
554  VERIFY_IS_EQUAL(twod_patch.dimension(0), 2);
555  VERIFY_IS_EQUAL(twod_patch.dimension(1), 2);
556  VERIFY_IS_EQUAL(twod_patch.dimension(2), 2);
557  VERIFY_IS_EQUAL(twod_patch.dimension(3), 3*5);
558 
559  // 2D patch: RowMajor
560  Tensor<float, 4, RowMajor> twod_patch_row_major;
561  twod_patch_row_major = tensor_row_major.extract_image_patches(2, 2);
562  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(0), 3*5);
563  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(1), 2);
564  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(2), 2);
565  VERIFY_IS_EQUAL(twod_patch_row_major.dimension(3), 2);
566 
567  // Based on the calculation described in TensorTraits.h, padding happens to be 0.
568  int row_padding = 0;
569  int col_padding = 0;
570  int stride = 1;
571 
572  for (int i = 0; i < 3; ++i) {
573  for (int j = 0; j < 5; ++j) {
574  int patchId = i+3*j;
575  for (int r = 0; r < 2; ++r) {
576  for (int c = 0; c < 2; ++c) {
577  for (int d = 0; d < 2; ++d) {
578  float expected = 0.0f;
579  float expected_row_major = 0.0f;
580  int row_offset = r*stride + i - row_padding;
581  int col_offset = c*stride + j - col_padding;
582  // ColMajor
583  if (row_offset >= 0 && col_offset >= 0 && row_offset < tensor.dimension(1) && col_offset < tensor.dimension(2)) {
584  expected = tensor(d, row_offset, col_offset);
585  }
586  if (twod_patch(d, r, c, patchId) != expected) {
587  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << std::endl;
588  }
589  VERIFY_IS_EQUAL(twod_patch(d, r, c, patchId), expected);
590  // RowMajor
591  if (row_offset >= 0 && col_offset >= 0 && row_offset < tensor_row_major.dimension(1) && col_offset < tensor_row_major.dimension(0)) {
592  expected_row_major = tensor_row_major(col_offset, row_offset, d);
593  }
594  if (twod_patch_row_major(patchId, c, r, d) != expected_row_major) {
595  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << std::endl;
596  }
597  VERIFY_IS_EQUAL(twod_patch_row_major(patchId, c, r, d), expected_row_major);
598  // Check that ColMajor and RowMajor agree.
599  VERIFY_IS_EQUAL(expected, expected_row_major);
600  }
601  }
602  }
603  }
604  }
605 }
606 
608 {
609  // Test the code on typical configurations used by the 'imagenet' benchmarks at
610  // https://github.com/soumith/convnet-benchmarks
611  // ColMajor
612  Tensor<float, 4> l_in(3, 128, 128, 16);
613  l_in.setRandom();
614  Tensor<float, 5> l_out = l_in.extract_image_patches(11, 11);
615  VERIFY_IS_EQUAL(l_out.dimension(0), 3);
616  VERIFY_IS_EQUAL(l_out.dimension(1), 11);
617  VERIFY_IS_EQUAL(l_out.dimension(2), 11);
618  VERIFY_IS_EQUAL(l_out.dimension(3), 128*128);
619  VERIFY_IS_EQUAL(l_out.dimension(4), 16);
620 
621  // RowMajor
622  Tensor<float, 5, RowMajor> l_out_row_major = l_in.swap_layout().extract_image_patches(11, 11);
623  VERIFY_IS_EQUAL(l_out_row_major.dimension(0), 16);
624  VERIFY_IS_EQUAL(l_out_row_major.dimension(1), 128*128);
625  VERIFY_IS_EQUAL(l_out_row_major.dimension(2), 11);
626  VERIFY_IS_EQUAL(l_out_row_major.dimension(3), 11);
627  VERIFY_IS_EQUAL(l_out_row_major.dimension(4), 3);
628 
629  for (int b = 0; b < 16; ++b) {
630  for (int i = 0; i < 128; ++i) {
631  for (int j = 0; j < 128; ++j) {
632  int patchId = i+128*j;
633  for (int c = 0; c < 11; ++c) {
634  for (int r = 0; r < 11; ++r) {
635  for (int d = 0; d < 3; ++d) {
636  float expected = 0.0f;
637  if (r-5+i >= 0 && c-5+j >= 0 && r-5+i < 128 && c-5+j < 128) {
638  expected = l_in(d, r-5+i, c-5+j, b);
639  }
640  // ColMajor
641  if (l_out(d, r, c, patchId, b) != expected) {
642  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
643  }
644  VERIFY_IS_EQUAL(l_out(d, r, c, patchId, b), expected);
645  // RowMajor
646  if (l_out_row_major(b, patchId, c, r, d) !=
647  expected) {
648  std::cout << "Mismatch detected at index i=" << i << " j=" << j
649  << " r=" << r << " c=" << c << " d=" << d << " b=" << b
650  << std::endl;
651  }
652  VERIFY_IS_EQUAL(l_out_row_major(b, patchId, c, r, d),
653  expected);
654  }
655  }
656  }
657  }
658  }
659  }
660 
661  // ColMajor
662  l_in.resize(16, 64, 64, 32);
663  l_in.setRandom();
664  l_out = l_in.extract_image_patches(9, 9);
665  VERIFY_IS_EQUAL(l_out.dimension(0), 16);
666  VERIFY_IS_EQUAL(l_out.dimension(1), 9);
667  VERIFY_IS_EQUAL(l_out.dimension(2), 9);
668  VERIFY_IS_EQUAL(l_out.dimension(3), 64*64);
669  VERIFY_IS_EQUAL(l_out.dimension(4), 32);
670 
671  // RowMajor
672  l_out_row_major = l_in.swap_layout().extract_image_patches(9, 9);
673  VERIFY_IS_EQUAL(l_out_row_major.dimension(0), 32);
674  VERIFY_IS_EQUAL(l_out_row_major.dimension(1), 64*64);
675  VERIFY_IS_EQUAL(l_out_row_major.dimension(2), 9);
676  VERIFY_IS_EQUAL(l_out_row_major.dimension(3), 9);
677  VERIFY_IS_EQUAL(l_out_row_major.dimension(4), 16);
678 
679  for (int b = 0; b < 32; ++b) {
680  for (int i = 0; i < 64; ++i) {
681  for (int j = 0; j < 64; ++j) {
682  int patchId = i+64*j;
683  for (int c = 0; c < 9; ++c) {
684  for (int r = 0; r < 9; ++r) {
685  for (int d = 0; d < 16; ++d) {
686  float expected = 0.0f;
687  if (r-4+i >= 0 && c-4+j >= 0 && r-4+i < 64 && c-4+j < 64) {
688  expected = l_in(d, r-4+i, c-4+j, b);
689  }
690  // ColMajor
691  if (l_out(d, r, c, patchId, b) != expected) {
692  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
693  }
694  VERIFY_IS_EQUAL(l_out(d, r, c, patchId, b), expected);
695  // RowMajor
696  if (l_out_row_major(b, patchId, c, r, d) != expected) {
697  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
698  }
699  VERIFY_IS_EQUAL(l_out_row_major(b, patchId, c, r, d), expected);
700  }
701  }
702  }
703  }
704  }
705  }
706 
707  // ColMajor
708  l_in.resize(32, 16, 16, 32);
709  l_in.setRandom();
710  l_out = l_in.extract_image_patches(7, 7);
711  VERIFY_IS_EQUAL(l_out.dimension(0), 32);
712  VERIFY_IS_EQUAL(l_out.dimension(1), 7);
713  VERIFY_IS_EQUAL(l_out.dimension(2), 7);
714  VERIFY_IS_EQUAL(l_out.dimension(3), 16*16);
715  VERIFY_IS_EQUAL(l_out.dimension(4), 32);
716 
717  // RowMajor
718  l_out_row_major = l_in.swap_layout().extract_image_patches(7, 7);
719  VERIFY_IS_EQUAL(l_out_row_major.dimension(0), 32);
720  VERIFY_IS_EQUAL(l_out_row_major.dimension(1), 16*16);
721  VERIFY_IS_EQUAL(l_out_row_major.dimension(2), 7);
722  VERIFY_IS_EQUAL(l_out_row_major.dimension(3), 7);
723  VERIFY_IS_EQUAL(l_out_row_major.dimension(4), 32);
724 
725  for (int b = 0; b < 32; ++b) {
726  for (int i = 0; i < 16; ++i) {
727  for (int j = 0; j < 16; ++j) {
728  int patchId = i+16*j;
729  for (int c = 0; c < 7; ++c) {
730  for (int r = 0; r < 7; ++r) {
731  for (int d = 0; d < 32; ++d) {
732  float expected = 0.0f;
733  if (r-3+i >= 0 && c-3+j >= 0 && r-3+i < 16 && c-3+j < 16) {
734  expected = l_in(d, r-3+i, c-3+j, b);
735  }
736  // ColMajor
737  if (l_out(d, r, c, patchId, b) != expected) {
738  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
739  }
740  VERIFY_IS_EQUAL(l_out(d, r, c, patchId, b), expected);
741  // RowMajor
742  if (l_out_row_major(b, patchId, c, r, d) != expected) {
743  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
744  }
745  VERIFY_IS_EQUAL(l_out_row_major(b, patchId, c, r, d), expected);
746  }
747  }
748  }
749  }
750  }
751  }
752 
753  // ColMajor
754  l_in.resize(64, 13, 13, 32);
755  l_in.setRandom();
756  l_out = l_in.extract_image_patches(3, 3);
757  VERIFY_IS_EQUAL(l_out.dimension(0), 64);
758  VERIFY_IS_EQUAL(l_out.dimension(1), 3);
759  VERIFY_IS_EQUAL(l_out.dimension(2), 3);
760  VERIFY_IS_EQUAL(l_out.dimension(3), 13*13);
761  VERIFY_IS_EQUAL(l_out.dimension(4), 32);
762 
763  // RowMajor
764  l_out_row_major = l_in.swap_layout().extract_image_patches(3, 3);
765  VERIFY_IS_EQUAL(l_out_row_major.dimension(0), 32);
766  VERIFY_IS_EQUAL(l_out_row_major.dimension(1), 13*13);
767  VERIFY_IS_EQUAL(l_out_row_major.dimension(2), 3);
768  VERIFY_IS_EQUAL(l_out_row_major.dimension(3), 3);
769  VERIFY_IS_EQUAL(l_out_row_major.dimension(4), 64);
770 
771  for (int b = 0; b < 32; ++b) {
772  for (int i = 0; i < 13; ++i) {
773  for (int j = 0; j < 13; ++j) {
774  int patchId = i+13*j;
775  for (int c = 0; c < 3; ++c) {
776  for (int r = 0; r < 3; ++r) {
777  for (int d = 0; d < 64; ++d) {
778  float expected = 0.0f;
779  if (r-1+i >= 0 && c-1+j >= 0 && r-1+i < 13 && c-1+j < 13) {
780  expected = l_in(d, r-1+i, c-1+j, b);
781  }
782  // ColMajor
783  if (l_out(d, r, c, patchId, b) != expected) {
784  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
785  }
786  VERIFY_IS_EQUAL(l_out(d, r, c, patchId, b), expected);
787  // RowMajor
788  if (l_out_row_major(b, patchId, c, r, d) != expected) {
789  std::cout << "Mismatch detected at index i=" << i << " j=" << j << " r=" << r << " c=" << c << " d=" << d << " b=" << b << std::endl;
790  }
791  VERIFY_IS_EQUAL(l_out_row_major(b, patchId, c, r, d), expected);
792  }
793  }
794  }
795  }
796  }
797  }
798 }
799 
800 EIGEN_DECLARE_TEST(cxx11_tensor_image_patch)
801 {
809 }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const
Definition: Tensor.h:103
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar & coeff(const array< Index, NumIndices > &indices) const
Definition: Tensor.h:124
#define CALL_SUBTEST_6(FUNC)
#define CALL_SUBTEST_4(FUNC)
Scalar * b
Definition: benchVecAdd.cpp:17
void test_patch_no_extra_dim()
Matrix expected
Definition: testMatrix.cpp:971
#define CALL_SUBTEST_3(FUNC)
#define CALL_SUBTEST_7(FUNC)
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor< Scalar_, NumIndices_, Options_, IndexType_ > & setRandom()
Definition: TensorBase.h:996
void test_patch_padding_same_negative_padding_clip_to_zero()
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const TensorLayoutSwapOp< const Tensor< Scalar_, NumIndices_, Options_, IndexType_ > > swap_layout() const
Definition: TensorBase.h:1033
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:386
#define CALL_SUBTEST_1(FUNC)
Values result
void test_patch_padding_valid_same_value()
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
void test_patch_padding_valid()
EIGEN_DEVICE_FUNC void resize(const array< Index, NumIndices > &dimensions)
Definition: Tensor.h:447
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar * data()
Definition: Tensor.h:104
void test_patch_padding_same()
EIGEN_DECLARE_TEST(cxx11_tensor_image_patch)
#define CALL_SUBTEST_5(FUNC)
void test_simple_patch()
void test_imagenet_patches()
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index dimension(std::size_t n) const
Definition: Tensor.h:101
#define CALL_SUBTEST_2(FUNC)
std::ptrdiff_t j
The tensor class.
Definition: Tensor.h:63


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:07