src/convnet_vol_util.ts
import * as util from './utils';
import { Vol } from './convnet_vol';
/**
* Data augmentation to the given `volume` based on `crop`.
* - `crop` is the size of output
* - `dx`,`dy` are offset wrt incoming volume, of the shift
* - `flip` is boolean on whether we also want to flip the matrix between left and right horizontally
*/
export function augment(volume: Vol, crop: number, dx?: number, dy?: number, flip?: number): Vol {
if (isNaN(dx)) {
dx = util.randi(0, volume.sx - crop);
}
if (isNaN(dy)) {
dy = util.randi(0, volume.sy - crop);
}
let croppedVolume;
if (crop !== volume.sx || dx!==0 || dy!==0) {
croppedVolume = new Vol(crop, crop, volume.depth, 0.0);
for(let x = 0; x < crop; x++) {
for(let y = 0; y < crop; y++) {
if (x + dx < 0 || x + dx >= volume.sx || y + dy < 0 || y + dy >= volume.sy) {
continue;
} else {
for(let d = 0; d < volume.depth; d++) {
// Fetch the weight value by offset `dx`/`dy`, then set it to the `croppedVolume`
croppedVolume.set(x, y, d, volume.get(x + dx, y + dy, d));
}
}
}
}
} else {
croppedVolume = volume;
}
if(flip) {
// Horizontally get the flipped `croppedVolume` and set it to a cloneAndZeroed volume
let clonedCroppedVolume = croppedVolume.cloneAndZero();
for(let x = 0; x < croppedVolume.sx; x++) {
for(let y = 0; y < croppedVolume.sy; y++) {
for(let d = 0; d < croppedVolume.depth; d++) {
clonedCroppedVolume.set(x, y, d, croppedVolume.get(croppedVolume.sx - x - 1, y, d));
}
}
}
croppedVolume = clonedCroppedVolume;
}
return croppedVolume;
}
/**
* Load an HTML DOM image to a virtual canvas and get the pixles data. Then return a `volume` based on the image data
* - If `grayScale` is given, the depth of the `volume` is 1
* - If `grayScale` is not given, the depth of the `volume` is 4 (RGBA)
*/
export function img_to_vol(img: HTMLImageElement, grayScale: boolean = false): Vol {
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.width;
let context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
let imgData = context.getImageData(0, 0, canvas.width, canvas.height);
// Extract the pixels data from image through a canvas
let {data, width, height} = imgData;
let volume = new Vol(width, height, 4, 0.0);
volume.w = Float64Array.from(data, item => item / 255.0 - 0.5);
// Only keep the gray channel data
if (grayScale) {
let grayScaleVolume = new Vol(width, height, 1, 0.0);
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
grayScaleVolume.set(i, j, 0, volume.get(i, j, 0));
}
}
volume = grayScaleVolume;
}
return volume;
}