Spaces:
Running
Running
Download phash.js from node-user1/ncp: direct link, hf CLI and curl.
- Browser
- Download file 2.16 kB
-
https://huggingface.co/spaces/node-user1/ncp/resolve/main/phash.js
- Command line
-
hf download hf://spaces/node-user1/ncp/phash.js
-
curl -L -o phash.js https://huggingface.co/spaces/node-user1/ncp/resolve/main/phash.js
2.16 kB
| import sharp from 'sharp' | |
| const SAMPLE_SIZE = 32 | |
| const initSQRT = (N) => { | |
| const c = new Array(N) | |
| for (let i = 1; i < N; i++) { | |
| c[i] = 1 | |
| } | |
| c[0] = 1 / Math.sqrt(2.0) | |
| return c | |
| } | |
| const SQRT = initSQRT(SAMPLE_SIZE) | |
| const initCOS = (N) => { | |
| const cosines = new Array(N) | |
| for (let k = 0; k < N; k++) { | |
| cosines[k] = new Array(N) | |
| for (let n = 0; n < N; n++) { | |
| cosines[k][n] = Math.cos(((2 * k + 1) / (2.0 * N)) * n * Math.PI) | |
| } | |
| } | |
| return cosines | |
| } | |
| const COS = initCOS(SAMPLE_SIZE) | |
| const applyDCT = (f, size) => { | |
| var N = size | |
| var F = new Array(N) | |
| for (var u = 0; u < N; u++) { | |
| F[u] = new Array(N) | |
| for (var v = 0; v < N; v++) { | |
| var sum = 0 | |
| for (var i = 0; i < N; i++) { | |
| for (var j = 0; j < N; j++) { | |
| sum += COS[i][u] * COS[j][v] * f[i][j] | |
| } | |
| } | |
| sum *= (SQRT[u] * SQRT[v]) / 4 | |
| F[u][v] = sum | |
| } | |
| } | |
| return F | |
| } | |
| const LOW_SIZE = 8 | |
| export const phash = async (image, options) => { | |
| const data = await sharp(image, options) | |
| .greyscale() | |
| .resize(SAMPLE_SIZE, SAMPLE_SIZE, { fit: 'fill' }) | |
| .rotate() | |
| .raw() | |
| .toBuffer() | |
| // copy signal | |
| const s = new Array(SAMPLE_SIZE) | |
| for (let x = 0; x < SAMPLE_SIZE; x++) { | |
| s[x] = new Array(SAMPLE_SIZE) | |
| for (let y = 0; y < SAMPLE_SIZE; y++) { | |
| s[x][y] = data[SAMPLE_SIZE * y + x] | |
| } | |
| } | |
| // apply 2D DCT II | |
| const dct = applyDCT(s, SAMPLE_SIZE) | |
| // get AVG on high frequencies | |
| let totalSum = 0 | |
| for (let x = 0; x < LOW_SIZE; x++) { | |
| for (let y = 0; y < LOW_SIZE; y++) { | |
| totalSum += dct[x + 1][y + 1] | |
| } | |
| } | |
| const avg = totalSum / (LOW_SIZE * LOW_SIZE) | |
| // compute hash | |
| let fingerprint = [] | |
| for (let x = 0; x < LOW_SIZE; x++) { | |
| for (let y = 0; y < LOW_SIZE; y++) { | |
| fingerprint.push(dct[x + 1][y + 1] > avg ? 1 : 0) | |
| } | |
| } | |
| return parseInt(fingerprint.join(''), 2).toString(16) | |
| } | |
| export const distance = (a, b) => { | |
| let count = 0 | |
| for (let i = 0; i < a.length; i++) { | |
| if (a[i] !== b[i]) { | |
| count++ | |
| } | |
| } | |
| return count | |
| } | |