diff --git a/hunks/adhoc/correlate.js b/hunks/adhoc/correlate.js index 6aa9be975cb3d14bae1d867edf2836ab87e298eb..601ebbf317d68bd6db748dcf137f6283d8adf812 100644 --- a/hunks/adhoc/correlate.js +++ b/hunks/adhoc/correlate.js @@ -11,158 +11,149 @@ import { State } from '../hunks.js' -let computedResult = null -let running = false - -let correlateGrayscale = (a, b, x, y) => { - // score a against b, starting b from x, y - // a, b are float64 arrays, pixel-wise - let sumA = 0 - let sumB = 0 - let sumDot = 0 - // i will be index within the flat-af array under a, - for(let i = 0; i < a.length; i ++){ - for(let j = 0; j < a[0].length; j ++){ - sumA += a[i][j] - sumB += b[i + x][j + y] - sumDot += a[i][j] * b[i + x][j + y] +function worker(){ + 'use strict' + let correlateGrayscale = (a, b, x, y) => { + // score a against b, starting b from x, y + // a, b are float64 arrays, pixel-wise + let sumA = 0 + let sumB = 0 + let sumDot = 0 + // i will be index within the flat-af array under a, + for (let i = 0; i < a.length; i++) { + for (let j = 0; j < a[0].length; j++) { + sumA += a[i][j] + sumB += b[i + x][j + y] + sumDot += a[i][j] * b[i + x][j + y] + } } + // I'm still not convinced this is a really great filter + return sumDot / Math.sqrt((sumB * sumB) * (sumA * sumA)) } - // I'm still not convinced this is a really great filter - return sumDot / Math.sqrt((sumB * sumB)*(sumA * sumA)) -} -let correlateRBGA = (a, b, x, y) => { - let ai, bi - let sumA = 0 - let sumB = 0 - let sumDot = 0 - for(let i = 0; i < a.length; i ++){ - for(let j = 0; j < a[0].length; j ++){ - ai = a[i][j] - bi = b[i + x][j + y] - // have two vals, - a[i][j] // has [0-3] rgba - b[i + x][j + y] // has [0-3] rgba - // so ? per pixel, this is like: - let pdb = ai[0] * bi[0] + ai[1] * bi[1] + ai[2] * bi[2] - let pas = ai[0] + ai[1] + ai[2] - let pbs = bi[0] + bi[1] + bi[2] - let pps = pdb / Math.sqrt(pas * pas * pbs * pbs) // per pixel score, - sumA += pas - sumB += pbs - sumDot += pdb + let correlateRBGA = (a, b, x, y) => { + let ai, bi + let sumA = 0 + let sumB = 0 + let sumDot = 0 + for (let i = 0; i < a.length; i++) { + for (let j = 0; j < a[0].length; j++) { + ai = a[i][j] + bi = b[i + x][j + y] + // have two vals, + a[i][j] // has [0-3] rgba + b[i + x][j + y] // has [0-3] rgba + // so ? per pixel, this is like: + let pdb = ai[0] * bi[0] + ai[1] * bi[1] + ai[2] * bi[2] + let pas = ai[0] + ai[1] + ai[2] + let pbs = bi[0] + bi[1] + bi[2] + let pps = pdb / Math.sqrt(pas * pas * pbs * pbs) // per pixel score, + sumA += pas + sumB += pbs + sumDot += pdb + } } + return sumDot / Math.sqrt(sumA * sumA * sumB * sumB) } - return sumDot / Math.sqrt(sumA * sumA * sumB * sumB) -} - -let delay = (time) => { - return new Promise(resolve =>{ - setTimeout(() => { - resolve() - }, time) - }) -} -let packGrayscale = (imgD) => { - // make an md array shaped like[x][y] - let arr = [] - for(let x = 0; x < imgD.width; x ++){ - arr.push(new Float64Array(imgD.height)) - } - let p = 0 - for(let y = 0; y < imgD.height; y ++){ - for(let x = 0; x < imgD.width; x ++){ - // grayscale all values as we load them up: - arr[x][y] = (imgD.data[p] + imgD.data[p + 1] + imgD.data[p + 2]) / 3 // + imgD.data[p + 3]) / 4; - p += 4; + let packGrayscale = (imgD) => { + // make an md array shaped like[x][y] + let arr = [] + for (let x = 0; x < imgD.width; x++) { + arr.push(new Float64Array(imgD.height)) + } + let p = 0 + for (let y = 0; y < imgD.height; y++) { + for (let x = 0; x < imgD.width; x++) { + // grayscale all values as we load them up: + arr[x][y] = (imgD.data[p] + imgD.data[p + 1] + imgD.data[p + 2]) / 3 // + imgD.data[p + 3]) / 4; + p += 4; + } } + return arr } - return arr -} -let packRBGA = (imgD) => { - let arr = [] - for(let x = 0; x< imgD.width; x ++){ - arr.push([]) - for(let y = 0; y < imgD.height; y ++){ - arr[x][y] = new Float64Array(4) + let packRBGA = (imgD) => { + let arr = [] + for (let x = 0; x < imgD.width; x++) { + arr.push([]) + for (let y = 0; y < imgD.height; y++) { + arr[x][y] = new Float64Array(4) + } } - } - let p = 0 - for(let y = 0; y < imgD.height; y ++){ - for(let x = 0; x < imgD.width; x ++){ - arr[x][y][0] = imgD.data[p ++] - arr[x][y][1] = imgD.data[p ++] - arr[x][y][2] = imgD.data[p ++] - arr[x][y][3] = imgD.data[p ++] + let p = 0 + for (let y = 0; y < imgD.height; y++) { + for (let x = 0; x < imgD.width; x++) { + arr[x][y][0] = imgD.data[p++] + arr[x][y][1] = imgD.data[p++] + arr[x][y][2] = imgD.data[p++] + arr[x][y][3] = imgD.data[p++] + } } + return arr } - return arr -} -async function run(a, b){ - running = true - // a is img to search for, b is img to search within. both are ImageData types - let resX = b.width - a.width - let resY = b.height - a.height - let numruns = resX * resY - console.log('numruns', numruns) - // the move now is to make an md array of these values, - let bArr = packRBGA(b) //packGrayscale(b) - let aArr = packRBGA(a) //packGrayscale(a) - // ok, results array like[x][y] - let result = [] - for(let x = 0; x < resX; x ++){ - result.push(new Float64Array(resY)) - } - // now fill, - for(let x = 0; x < resX; x ++){ - for(let y = 0; y < resY; y ++){ - result[x][y] = correlateRBGA(aArr, bArr, x, y) + function run(a, b) { + // a is img to search for, b is img to search within. both are ImageData types + let resX = b.width - a.width + let resY = b.height - a.height + let numruns = resX * resY + // the move now is to make an md array of these values, + let bArr = packRBGA(b) //packGrayscale(b) + let aArr = packRBGA(a) //packGrayscale(a) + // ok, results array like[x][y] + let result = [] + for (let x = 0; x < resX; x++) { + result.push(new Float64Array(resY)) } - await delay(0) // to avoid blocking, - } - console.log('run complete') - // make image from the result, - let max = -Infinity - let min = Infinity - let mp = {x: 0, y: 0} - for(let x = 0; x < resX; x ++){ - for(let y = 0; y < resY; y ++){ - if(result[x][y] > max){ - max = result[x][y] - mp.x = x - mp.y = y + // now fill, + for (let x = 0; x < resX; x++) { + for (let y = 0; y < resY; y++) { + result[x][y] = correlateRBGA(aArr, bArr, x, y) } - if(result[x][y] < min) min = result[x][y] } - } - console.log('max, min', max, min) - console.log('mp', mp) - // now we want to unwrap this into an imagedata type, - // filling back in grayscale type - let imdBuffer = new Uint8ClampedArray(resX * resY * 4) - let lc = 0 - let dt = 0 - for(let y = 0; y < resY; y ++){ - for(let x = 0; x < resX; x ++){ - // stretch to full range, - dt = (result[x][y] - min) * (255 / (max - min)) - imdBuffer[lc ++] = dt - imdBuffer[lc ++] = dt - imdBuffer[lc ++] = dt - imdBuffer[lc ++] = 255 + // make image from the result, + let max = -Infinity + let min = Infinity + let mp = { x: 0, y: 0 } + for (let x = 0; x < resX; x++) { + for (let y = 0; y < resY; y++) { + if (result[x][y] > max) { + max = result[x][y] + mp.x = x + mp.y = y + } + if (result[x][y] < min) min = result[x][y] + } + } + // now we want to unwrap this into an imagedata type, + // filling back in grayscale type + let imdBuffer = new Uint8ClampedArray(resX * resY * 4) + let lc = 0 + let dt = 0 + for (let y = 0; y < resY; y++) { + for (let x = 0; x < resX; x++) { + // stretch to full range, + dt = (result[x][y] - min) * (255 / (max - min)) + imdBuffer[lc++] = dt + imdBuffer[lc++] = dt + imdBuffer[lc++] = dt + imdBuffer[lc++] = 255 + } } + let imgRes = new ImageData(imdBuffer, resX, resY) + self.postMessage(imgRes) + } + + onmessage = (evt) => { + run(evt.data.a, evt.data.b) } - let imgRes = new ImageData(imdBuffer, resX, resY) - console.log('imgRes', imgRes) - running = false - computedResult = imgRes } -export default function Correlate(){ +let computedResult = null +let running = false + +export default function Correlate() { Hunkify(this) let imgIn = this.input('ImageData', 'frame') @@ -180,7 +171,19 @@ export default function Correlate(){ this.dom = $('<div>').get(0) + let webWorker + this.init = () => { + // startup the worker: + let bleb = new Blob(['('+worker.toString()+'())']) + let url = window.URL.createObjectURL(bleb) + webWorker = new Worker(url) + webWorker.addEventListener('message', (evt) => { + running = false + if(!resOut.io()){ + resOut.put(evt.data) + } + }) } this.onload = () => { @@ -189,7 +192,13 @@ export default function Correlate(){ } this.loop = () => { - if(imgIn.io() && !running){ + if (imgIn.io() && !running) { + /* + imgIn.get() + running = true + console.log("POSTING") + webWorker.postMessage('msg') + */ // ok, the image data: let img = imgIn.get() // to scale this thing, we draw it into a canvas (virtual ... not attached to page) @@ -208,10 +217,8 @@ export default function Correlate(){ let a = ctxB.getImageData(b.width / 2, b.height / 2, 50, 50) // and write that out, to debug ... ctxA.putImageData(a, 0, 0) - run(a, b) - } - if(!resOut.io() && computedResult !== null){ - resOut.put(computedResult) + webWorker.postMessage({a: a, b: b}) + running = true } } }