shadow-score 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts","../src/detector.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ShadowOptions } from './types';\n\n/**\n * Validates the image input parameter.\n */\nexport function validateInput(input: unknown): void {\n if (input === null || input === undefined) {\n throw new TypeError('Invalid image input: input must be a file path string, Buffer, or Uint8Array.');\n }\n\n if (typeof input === 'string') {\n if (input.trim().length === 0) {\n throw new Error('Invalid image input: file path string cannot be empty.');\n }\n return;\n }\n\n if (Buffer.isBuffer(input) || input instanceof Uint8Array) {\n if (input.length === 0) {\n throw new Error('Invalid image input: buffer cannot be empty.');\n }\n return;\n }\n\n throw new TypeError('Invalid image input: expected a file path string, Buffer, or Uint8Array.');\n}\n\n/**\n * Validates and normalizes user-provided shadow options with safe defaults.\n */\nexport function normalizeOptions(options?: ShadowOptions): Required<ShadowOptions> {\n const threshold = options?.threshold ?? 0.2;\n const downsampleWidth = options?.downsampleWidth ?? 256;\n const minIlluminationDelta = options?.minIlluminationDelta ?? 20;\n const smoothingRadius = options?.smoothingRadius ?? 4;\n\n if (typeof threshold !== 'number' || Number.isNaN(threshold) || threshold < 0 || threshold > 1) {\n throw new RangeError(`Invalid option 'threshold': expected a number between 0 and 1, got ${threshold}.`);\n }\n\n if (\n typeof downsampleWidth !== 'number' ||\n Number.isNaN(downsampleWidth) ||\n downsampleWidth < 16 ||\n !Number.isInteger(downsampleWidth)\n ) {\n throw new RangeError(\n `Invalid option 'downsampleWidth': expected an integer >= 16, got ${downsampleWidth}.`\n );\n }\n\n if (\n typeof minIlluminationDelta !== 'number' ||\n Number.isNaN(minIlluminationDelta) ||\n minIlluminationDelta < 0 ||\n minIlluminationDelta > 255\n ) {\n throw new RangeError(\n `Invalid option 'minIlluminationDelta': expected a number between 0 and 255, got ${minIlluminationDelta}.`\n );\n }\n\n if (\n typeof smoothingRadius !== 'number' ||\n Number.isNaN(smoothingRadius) ||\n smoothingRadius < 1 ||\n smoothingRadius > 32 ||\n !Number.isInteger(smoothingRadius)\n ) {\n throw new RangeError(\n `Invalid option 'smoothingRadius': expected an integer between 1 and 32, got ${smoothingRadius}.`\n );\n }\n\n return {\n threshold,\n downsampleWidth,\n minIlluminationDelta,\n smoothingRadius,\n };\n}\n","import sharp from 'sharp';\nimport type { ShadowOptions, ShadowResult, ShadowDetails } from './types';\nimport { normalizeOptions, validateInput } from './utils';\n\n/**\n * Applies a separable 2D box filter to eliminate high-frequency details (like fine text)\n * and extract the underlying illumination field.\n */\nfunction extractIlluminationMap(\n src: Uint8Array,\n width: number,\n height: number,\n radius: number\n): Uint8Array {\n const temp = new Uint8Array(width * height);\n const dst = new Uint8Array(width * height);\n const div = 2 * radius + 1;\n\n // Horizontal pass\n for (let y = 0; y < height; y++) {\n const row = y * width;\n let sum = 0;\n for (let i = -radius; i <= radius; i++) {\n const c = i < 0 ? 0 : (i >= width ? width - 1 : i);\n sum += src[row + c]!;\n }\n for (let x = 0; x < width; x++) {\n temp[row + x] = Math.round(sum / div);\n const removeX = x - radius;\n const addX = x + radius + 1;\n const removeVal = src[row + (removeX < 0 ? 0 : removeX)]!;\n const addVal = src[row + (addX >= width ? width - 1 : addX)]!;\n sum += addVal - removeVal;\n }\n }\n\n // Vertical pass\n for (let x = 0; x < width; x++) {\n let sum = 0;\n for (let i = -radius; i <= radius; i++) {\n const r = i < 0 ? 0 : (i >= height ? height - 1 : i);\n sum += temp[r * width + x]!;\n }\n for (let y = 0; y < height; y++) {\n dst[y * width + x] = Math.round(sum / div);\n const removeY = y - radius;\n const addY = y + radius + 1;\n const removeVal = temp[(removeY < 0 ? 0 : removeY) * width + x]!;\n const addVal = temp[(addY >= height ? height - 1 : addY) * width + x]!;\n sum += addVal - removeVal;\n }\n }\n\n return dst;\n}\n\n/**\n * Measures the ratio of the largest connected shadow cluster to total shadow pixels.\n */\nfunction computeContiguity(\n isShadow: Uint8Array,\n width: number,\n height: number,\n totalShadowPixels: number\n): number {\n if (totalShadowPixels === 0) return 0;\n\n const totalPixels = width * height;\n const visited = new Uint8Array(totalPixels);\n const queue = new Int32Array(totalPixels);\n let maxClusterSize = 0;\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const startIdx = y * width + x;\n if (visited[startIdx] === 1 || isShadow[startIdx] === 0) continue;\n\n let head = 0;\n let tail = 0;\n queue[tail++] = startIdx;\n visited[startIdx] = 1;\n let clusterSize = 0;\n\n while (head < tail) {\n const curr = queue[head++]!;\n clusterSize++;\n const cy = Math.floor(curr / width);\n const cx = curr % width;\n\n if (cx > 0) {\n const n = curr - 1;\n if (visited[n] === 0 && isShadow[n] === 1) {\n visited[n] = 1;\n queue[tail++] = n;\n }\n }\n if (cx < width - 1) {\n const n = curr + 1;\n if (visited[n] === 0 && isShadow[n] === 1) {\n visited[n] = 1;\n queue[tail++] = n;\n }\n }\n if (cy > 0) {\n const n = curr - width;\n if (visited[n] === 0 && isShadow[n] === 1) {\n visited[n] = 1;\n queue[tail++] = n;\n }\n }\n if (cy < height - 1) {\n const n = curr + width;\n if (visited[n] === 0 && isShadow[n] === 1) {\n visited[n] = 1;\n queue[tail++] = n;\n }\n }\n }\n\n if (clusterSize > maxClusterSize) {\n maxClusterSize = clusterSize;\n }\n }\n }\n\n return maxClusterSize / totalShadowPixels;\n}\n\n/**\n * Analyzes an image for directional shadows using Otsu bimodal luminance segmentation\n * and spatial illumination gradient analysis.\n *\n * @param input - Image file path, Buffer, or Uint8Array.\n * @param options - Configuration options for shadow analysis.\n * @returns Detailed ShadowResult object.\n */\nexport async function analyzeShadow(\n input: string | Buffer | Uint8Array,\n options?: ShadowOptions\n): Promise<ShadowResult> {\n validateInput(input);\n const opts = normalizeOptions(options);\n\n // 1. Downsample and convert to raw grayscale buffer\n const imagePipeline = sharp(input);\n const { data, info } = await imagePipeline\n .resize({ width: opts.downsampleWidth, withoutEnlargement: true })\n .grayscale()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n const width = info.width;\n const height = info.height;\n const totalPixels = width * height;\n\n if (totalPixels === 0) {\n throw new Error('Image contains no pixel data.');\n }\n\n // 2. Extract smooth illumination field (removing high-frequency text & fine textures)\n const illum = extractIlluminationMap(data, width, height, opts.smoothingRadius);\n\n // 3. Compute histogram, global mean, and total variance\n const hist = new Int32Array(256);\n let totalSum = 0;\n for (let i = 0; i < totalPixels; i++) {\n const val = illum[i]!;\n hist[val]++;\n totalSum += val;\n }\n\n const meanT = totalSum / totalPixels;\n let varT = 0;\n for (let i = 0; i < 256; i++) {\n const count = hist[i]!;\n if (count > 0) {\n const diff = i - meanT;\n varT += count * diff * diff;\n }\n }\n varT /= totalPixels;\n\n // If variance is negligible, image lighting is completely uniform\n if (varT < 1.0) {\n const roundedMean = Number(meanT.toFixed(2));\n return {\n score: 0,\n hasShadow: false,\n shadowAreaPercentage: 0,\n illuminationDelta: 0,\n quality: 'excellent',\n details: {\n litLuminance: roundedMean,\n shadowLuminance: roundedMean,\n otsuThreshold: Math.round(meanT),\n separability: 0,\n boundaryGradient: 0,\n },\n };\n }\n\n // 4. Otsu's bimodal threshold search to maximize between-class variance\n let bestT = 128;\n let maxBetweenVar = 0;\n let weight0 = 0;\n let sum0 = 0;\n\n for (let t = 0; t < 255; t++) {\n const count = hist[t]!;\n weight0 += count;\n if (weight0 === 0) continue;\n const weight1 = totalPixels - weight0;\n if (weight1 === 0) break;\n\n sum0 += t * count;\n const mean0 = sum0 / weight0;\n const mean1 = (totalSum - sum0) / weight1;\n const meanDiff = mean1 - mean0;\n const betweenVar = (weight0 * weight1 * meanDiff * meanDiff) / (totalPixels * totalPixels);\n\n if (betweenVar > maxBetweenVar) {\n maxBetweenVar = betweenVar;\n bestT = t;\n }\n }\n\n // Calculate class metrics at best threshold\n let shadowCount = 0;\n let shadowSum = 0;\n let litCount = 0;\n let litSum = 0;\n\n const isShadow = new Uint8Array(totalPixels);\n for (let i = 0; i < totalPixels; i++) {\n const val = illum[i]!;\n if (val <= bestT) {\n isShadow[i] = 1;\n shadowCount++;\n shadowSum += val;\n } else {\n litCount++;\n litSum += val;\n }\n }\n\n const shadowLuminance = shadowCount > 0 ? shadowSum / shadowCount : 0;\n const litLuminance = litCount > 0 ? litSum / litCount : meanT;\n const illuminationDelta = Math.max(0, litLuminance - shadowLuminance);\n const shadowAreaPercentage = (shadowCount / totalPixels) * 100;\n const separability = Math.min(1.0, maxBetweenVar / varT);\n\n // 5. Spatial illumination gradient at the shadow boundary\n let boundaryGradientSum = 0;\n let boundaryPixelCount = 0;\n\n for (let y = 1; y < height - 1; y++) {\n const rowOffset = y * width;\n for (let x = 1; x < width - 1; x++) {\n const idx = rowOffset + x;\n if (isShadow[idx] === 1) {\n if (\n isShadow[idx - 1] === 0 ||\n isShadow[idx + 1] === 0 ||\n isShadow[idx - width] === 0 ||\n isShadow[idx + width] === 0\n ) {\n const gx = (illum[idx + 1]! - illum[idx - 1]!) * 0.5;\n const gy = (illum[idx + width]! - illum[idx - width]!) * 0.5;\n boundaryGradientSum += Math.sqrt(gx * gx + gy * gy);\n boundaryPixelCount++;\n }\n }\n }\n }\n\n const avgBoundaryGradient =\n boundaryPixelCount > 0 ? boundaryGradientSum / boundaryPixelCount : 0;\n\n // 6. Spatial contiguity of the shadow\n const contiguity = computeContiguity(isShadow, width, height, shadowCount);\n\n // 7. Calculate normalized shadow severity score (0.0 to 1.0)\n let score = 0;\n\n if (illuminationDelta >= opts.minIlluminationDelta && shadowAreaPercentage > 0) {\n // Delta factor: ramp from minIlluminationDelta up to delta ~ 120\n const deltaRange = Math.max(1, 120 - opts.minIlluminationDelta);\n const fDelta = Math.min(1.0, (illuminationDelta - opts.minIlluminationDelta) / deltaRange);\n\n // Separability factor (how clearly bimodal the distribution is)\n const fSep = Math.min(1.0, Math.max(0.0, (separability - 0.25) / 0.55));\n\n // Contrast ratio factor: (lit - shadow) / (lit + shadow)\n const contrastRatio = illuminationDelta / (litLuminance + shadowLuminance + 1e-5);\n const fContrast = Math.min(1.0, contrastRatio / 0.45);\n\n // Boundary gradient factor (harsh directional shadows have sharper boundaries than gentle ambient gradients)\n const fGrad = Math.min(1.0, avgBoundaryGradient / 8.0);\n const gradientTerm = 0.65 + 0.35 * fGrad;\n\n // Area factor: shadows covering 5% to 75% are typical directional shadows.\n // If area < 5%, linearly ramp up. If area > 75%, ramp down towards 95% (underexposed photo, not a directional shadow).\n let fArea = 1.0;\n if (shadowAreaPercentage < 5) {\n fArea = Math.max(0.0, shadowAreaPercentage / 5.0);\n } else if (shadowAreaPercentage > 75) {\n fArea = Math.max(0.0, (95 - shadowAreaPercentage) / 20.0);\n }\n\n // Lit brightness factor: if the lit region itself is dark (< 60), the entire image is underexposed\n const fLit = Math.min(1.0, litLuminance / 60.0);\n\n // Contiguity factor: directional shadows are clustered, not random speckles\n const fContig = 0.4 + 0.6 * Math.min(1.0, Math.max(0.0, (contiguity - 0.2) / 0.5));\n\n const contrastTerm = 0.5 * fSep + 0.5 * fContrast;\n const rawScore = fDelta * contrastTerm * gradientTerm * fArea * fLit * fContig;\n score = Math.max(0.0, Math.min(1.0, rawScore));\n }\n\n score = Number(score.toFixed(4));\n const hasShadowResult = score >= opts.threshold;\n\n // Qualitative rating\n let quality: 'excellent' | 'good' | 'fair' | 'poor';\n if (score < 0.1) {\n quality = 'excellent';\n } else if (score < 0.2) {\n quality = 'good';\n } else if (score < 0.45) {\n quality = 'fair';\n } else {\n quality = 'poor';\n }\n\n const details: ShadowDetails = {\n litLuminance: Number(litLuminance.toFixed(2)),\n shadowLuminance: Number(shadowLuminance.toFixed(2)),\n otsuThreshold: bestT,\n separability: Number(separability.toFixed(4)),\n boundaryGradient: Number(avgBoundaryGradient.toFixed(2)),\n };\n\n return {\n score,\n hasShadow: hasShadowResult,\n shadowAreaPercentage: Number(shadowAreaPercentage.toFixed(2)),\n illuminationDelta: Number(illuminationDelta.toFixed(2)),\n quality,\n details,\n };\n}\n\n/**\n * Returns the normalized shadow severity score (0.0 to 1.0) for an image.\n *\n * @param input - Image file path, Buffer, or Uint8Array.\n * @param options - Optional configuration options.\n * @returns Promise resolving to shadow score (0.0 to 1.0).\n */\nexport async function getShadowScore(\n input: string | Buffer | Uint8Array,\n options?: ShadowOptions\n): Promise<number> {\n const result = await analyzeShadow(input, options);\n return result.score;\n}\n\n/**\n * Checks whether an image has harsh shadows exceeding the threshold.\n *\n * @param input - Image file path, Buffer, or Uint8Array.\n * @param thresholdOrOptions - Number threshold (e.g. 0.2) or ShadowOptions configuration.\n * @returns Promise resolving to boolean.\n */\nexport async function hasShadow(\n input: string | Buffer | Uint8Array,\n thresholdOrOptions?: number | ShadowOptions\n): Promise<boolean> {\n let opts: ShadowOptions | undefined;\n if (typeof thresholdOrOptions === 'number') {\n opts = { threshold: thresholdOrOptions };\n } else if (thresholdOrOptions !== undefined) {\n opts = thresholdOrOptions;\n }\n\n const result = await analyzeShadow(input, opts);\n return result.hasShadow;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "shadow-score",
3
+ "version": "1.0.0",
4
+ "description": "Detect and quantify harsh directional shadows in documents and photos using Otsu bimodal luminance segmentation and spatial illumination gradient analysis with Sharp.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "typecheck": "tsc --noEmit",
27
+ "prepublishOnly": "npm run build && npm test"
28
+ },
29
+ "keywords": [
30
+ "shadow",
31
+ "shadow-detection",
32
+ "shadow-score",
33
+ "image-quality",
34
+ "document-scanner",
35
+ "kyc",
36
+ "ocr-preprocessing",
37
+ "sharp",
38
+ "blur-score",
39
+ "exposure-score",
40
+ "glare-score"
41
+ ],
42
+ "author": "Vijay Misal <misalvijay153@gmail.com>",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/vjymisal0/shadow-score.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/vjymisal0/shadow-score/issues"
49
+ },
50
+ "homepage": "https://github.com/vjymisal0/shadow-score#readme",
51
+ "license": "MIT",
52
+ "dependencies": {
53
+ "sharp": "^0.33.5"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^22.10.2",
57
+ "tsup": "^8.3.5",
58
+ "typescript": "^5.7.2",
59
+ "vitest": "^2.1.8"
60
+ },
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ }
64
+ }