Reputation: 90
Random cropping is not implemented in TensorFlow JS, but is it possible to replicate it? My idea was to use Tensor.slice() with tensors generated from tf.randomUniform as parameters, but it only accepts "numbers". So it seems to me, that in order to get random cropping working, I'd have to reconstruct that part of the computation graph in each iteration with newly generated random numbers (e.g. from Math.random()) as slice parameters. Or is there another way?
Here is my code. My understanding is, that the inner function will create the random offset rx and ry only once, and I'd need a tensorflow operation to continuously get random values in each iteration.
export function jitter (d) {
const inner = (tImage) => {
const tShp = tImage.shape;
const cropShape = [
tShp[0], tShp[1]-d,
tShp[2]-d, tShp[3]];
const rx = Math.floor(Math.random() * d + 0.5);
const ry = Math.floor(Math.random() * d + 0.5);
const crop = tImage.slice(
[0, rx, ry, 0],
[cropShape[0], cropShape[1], cropShape[2], cropShape[3]]);
}
return inner;
}
Link to doc for Tensor.slice()
Upvotes: 0
Views: 146
Reputation: 18381
slice will allow to slice or crop a part of the input. Using gatherND will allow on the other hand to slice multiples times if one wants to avoid using slice repeatedly. But the indices at where to slice should be given. Below, the function g
generate the indices from the random coordinates and try to calculate the indices of all the z * z
elements that will be included in the crop.
const g = (r, s, z, n) => {
const arr = []
for (let i = 0; i < n; i++) {
const c = Math.floor(Math.random() * r)
const d = Math.floor(Math.random() * s)
const p = Array.from({length: z}, (_, k) => k + c)
const q = Array.from({length: z}, (_, k) => k + d)
arr.push(p.map( e => q.map(f => ([e, f]))).flat())
}
return arr
}
const n = 3
const crop = 4
const hsize = 2 // maximum of the height where to start cropping
const wsize = 2 // maximum of the width where to start cropping
// hsize = length_of_height_dimension - crop_size_over_height
// wsize = length_of_width_dimension - crop_size_over_width
const indices = tf.tensor( g(hsize, wsize, crop, n)).toInt()
const input = tf.tensor(Array.from({length: 64 * 3}, (_, k) => k +1), [8, 8, 3]);
tf.gatherND(input, indices).reshape([n, crop, crop, 3]).print()
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"> </script>
</head>
<body>
</body>
</html>
Upvotes: 0