xxxxxxxxxx
157
let img;
const redPix = new Float32Array(65536);
const greenPix = new Float32Array(65536);
const bluePix = new Float32Array(65536);
const redPixAlt = new Float32Array(65536);
const greenPixAlt = new Float32Array(65536);
const bluePixAlt = new Float32Array(65536);
const buf = new Float32Array(65536);
function preload() {
img = loadImage("https://picsum.photos/256");
}
function setup() {
createCanvas(512, 512);
image(img, 0, 0);
// Store image into arrays
for (let y = 0, idx = 0; y < 256; y++) {
for (let x = 0; x < 256; x++) {
let c = img.get(x, y);
redPix[idx] = red(c) - 127.5;
greenPix[idx] = green(c) - 127.5;
bluePix[idx] = blue(c) - 127.5;
idx++;
}
}
setImage(0, 0, redPix, greenPix, bluePix, 1, 127.5);
// Convert to Random Projection
randomSignFlip(redPix); // Random sign flip
whtN(redPix); // Plus whtN = Random Projection
randomSignFlip(greenPix);
whtN(greenPix);
randomSignFlip(bluePix);
whtN(bluePix);
// Draw random projection of the image
setImage(256, 0, redPix, greenPix, bluePix, 0.5, 127.5);
//Transfer 20% of the Random projection (dimensional reduction)
for (let i = 0; i < 13107; i++) {
redPixAlt[i] = redPix[i];
greenPixAlt[i] = greenPix[i];
bluePixAlt[i] = bluePix[i];
}
// do the inverse Random Projection on the 20% of data
whtN(redPixAlt);
randomSignFlip(redPixAlt);
whtN(greenPixAlt);
randomSignFlip(greenPixAlt);
whtN(bluePixAlt);
randomSignFlip(bluePixAlt);
// Show reconstruction from 20%
setImage(0, 256, redPixAlt, greenPixAlt, bluePixAlt, 5, 127.5);
updatePixels();
}
function draw() {
// Smooth the image with a binomial filter
binomialFilter256(redPixAlt, buf);
binomialFilter256(greenPixAlt, buf);
binomialFilter256(bluePixAlt, buf);
// Show the image
setImage(256, 256, redPixAlt, greenPixAlt, bluePixAlt, 1, 127.5);
updatePixels();
// Do the forward random Projection again
randomSignFlip(redPixAlt);
whtN(redPixAlt);
randomSignFlip(greenPixAlt);
whtN(greenPixAlt);
randomSignFlip(bluePixAlt);
whtN(bluePixAlt);
// Correct with 20% from the original random projection
for (let i = 0; i < 13106; i++) {
redPixAlt[i] = redPix[i];
greenPixAlt[i] = greenPix[i];
bluePixAlt[i] = bluePix[i];
}
// Do the inverse Random Projection
whtN(redPixAlt);
randomSignFlip(redPixAlt);
whtN(greenPixAlt);
randomSignFlip(greenPixAlt);
whtN(bluePixAlt);
randomSignFlip(bluePixAlt);
}
function setImage(x, y, ra, ga, ba, sc, os) {
for (let yi = 0, idx = 0; yi < 256; yi++) {
for (let xi = 0; xi < 256; xi++) {
let r = constrain(ra[idx] * sc + os, 0, 255);
let g = constrain(ga[idx] * sc + os, 0, 255);
let b = constrain(ba[idx] * sc + os, 0, 255);
idx++;
set(x + xi, y + yi, color(r, g, b));
}
}
}
// Fixed sequence of Random Sign Flips applied to array x
function randomSignFlip(x) {
randomSeed(1234567); //Random number seed value
for (let i = 0; i < x.length; i++) {
if (random(-1, 1) < 0) {
x[i] = -x[i];
}
}
}
function binomialFilter256(im, buffer) {
for (let y = 0; y < 256; y++) {
let a;
let b = im[y * 256];
let c = b;
for (let x = 0; x < 255; x++) {
a = b;
b = c;
c = im[x + 1 + y * 256];
buffer[x + y * 256] = 0.25 * a + 0.5 * b + 0.25 * c;
}
buffer[255 + y * 256] = 0.25 * b + 0.75 * c;
}
for (let x = 0; x < 256; x++) {
let a;
let b = im[x];
let c = b;
for (let y = 0; y < 255; y++) {
a = b;
b = c;
c = buffer[x + 256 + y * 256];
im[x + y * 256] = 0.25 * a + 0.5 * b + 0.25 * c;
}
im[255 * 256 + x] = 0.25 * b + 0.75 * c;
}
}
// Fast Walsh Hadamard Transform (Normalized)
function whtN(vec) {
const n = vec.length;
let hs = 1;
while (hs < n) {
let i = 0;
while (i < n) {
const j = i + hs;
while (i < j) {
var a = vec[i];
var b = vec[i + hs];
vec[i] = a + b;
vec[i + hs] = a - b;
i += 1;
}
i += hs;
}
hs += hs;
}
const sc = 1 / sqrt(n);
for (let i = 0; i < n; i++) {
vec[i] *= sc;
}
}