Skip to content

Instantly share code, notes, and snippets.

@stengoes
Created October 5, 2020 10:02
Show Gist options
  • Save stengoes/ba2b22ef4954273ae173a3c600811722 to your computer and use it in GitHub Desktop.
Save stengoes/ba2b22ef4954273ae173a3c600811722 to your computer and use it in GitHub Desktop.
image_pad_or_crop
function image_pad_or_crop(image, output_height, output_width) {
// Pads or crops an image so that the height and width dimensions match output_height and output_width.
// This function is compatible with tf.image.resize_with_crop_or_pad(image, target_height, target_width)
// Validate inputs
const image_size = image.height * image.width * image.depth;
if (image.data.length != image_size) {
console.log("Error: image dimensions do not match rgba buffer size!");
return null;
}
if (image.data.constructor !== Uint8ClampedArray && image.data.constructor !== Float32Array) {
console.log("Error: image data should be of type Uint8ClampedArray or Float32Array!");
return null;
}
if (output_height <= 0 || output_width <= 0)
{
console.log("Error: output_height and output_width should be positive integers ( > 0)!");
return null;
}
// Compute output dimensions
const output_depth = image.depth;
// Init output image
const output = {
height: output_height,
width: output_width,
depth: output_depth,
data: new image.data.constructor(output_height * output_width * output_depth) // Initialized with zeros
}
// Compute padding/cropping amounts
function floor(v) { return (v >= 0 || -1) * Math.floor(Math.abs(v));} // use custom floor that is compatible with tf.image.resize_with_crop_or_pad
const top = floor((output_height - image.height) / 2);
const bottom = output_height - image.height - top;
const left = floor((output_width - image.width) / 2);
const right = output_width - image.width - left;
// Copy input image into output
let output_idx = Math.max(top, 0) * output.width * output.depth + Math.max(left, 0) * output_depth;
let image_idx = Math.max(-top, 0) * image.width * image.depth + Math.max(-left, 0) * image.depth;
for (let y = 0; y < (output_height - Math.max(top, 0) - Math.max(bottom, 0)); y++, image_idx += image.width * image.depth, output_idx += output_width * output.depth)
output.data.set(image.data.slice(image_idx, image_idx + (image.width - Math.max(-left, 0) - Math.max(-right, 0)) * image.depth), output_idx)
return output;
}
// Utility function (only for testing)
function show_image(image) {
str = "";
let idx = 0;
for (let y = 0; y < image.height; y++) {
for (let x = 0; x < image.width; x++) {
str += "[ ";
for (let z = 0; z < image.depth; z++)
str += image.data[idx++] + " ";
str += "] ";
}
str += "\n";
}
console.log(str);
}
// Test
test_image = {
"height": 3,
"width": 4,
"depth": 1,
"data": (new Float32Array([...Array(3*4*1).keys()]))
}
show_image(test_image);
/* should output:
[ 0 ] [ 1 ] [ 2 ] [ 3 ]
[ 4 ] [ 5 ] [ 6 ] [ 7 ]
[ 8 ] [ 9 ] [ 10 ] [ 11 ]
*/
output = image_pad_or_crop(test_image, 6, 6);
show_image(output);
/* should output:
[ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ]
[ 0 ] [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 0 ]
[ 0 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 0 ]
[ 0 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 0 ]
[ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ]
[ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment