add blur detection + Ollama ID validation + corporate check for all carriers
- Client-side: Laplacian variance blur detection in photo quality check (very blurry / somewhat blurry / acceptable / good) - Server-side: async Ollama vision model validates uploaded image is a real government ID (minicpm-v:8b), flags non-ID uploads - Corporate check: sole proprietors now get yellow 'form an LLC' upsell, formal entities get annual report/RA reminder
This commit is contained in:
parent
e40f359693
commit
e2313bcc5e
3 changed files with 150 additions and 2 deletions
|
|
@ -624,6 +624,51 @@
|
|||
checks.push({ok: false, text: "Aspect ratio: " + ratio.toFixed(1) + ":1 — doesn't look like a standard ID"});
|
||||
warnings.push("This doesn't appear to be a photo of an ID card. Please upload a clear photo of the front of your government-issued ID.");
|
||||
}
|
||||
|
||||
// Blur detection — Laplacian variance on grayscale canvas
|
||||
try {
|
||||
var canvas = document.createElement("canvas");
|
||||
var sz = 300; // downsample for speed
|
||||
var scale = Math.min(sz / w, sz / h, 1);
|
||||
canvas.width = Math.round(w * scale);
|
||||
canvas.height = Math.round(h * scale);
|
||||
var ctx = canvas.getContext("2d");
|
||||
if (ctx) {
|
||||
ctx.drawImage(imgEl, 0, 0, canvas.width, canvas.height);
|
||||
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
var gray = new Float32Array(canvas.width * canvas.height);
|
||||
for (var p = 0; p < gray.length; p++) {
|
||||
gray[p] = imgData.data[p * 4] * 0.299 + imgData.data[p * 4 + 1] * 0.587 + imgData.data[p * 4 + 2] * 0.114;
|
||||
}
|
||||
// 3x3 Laplacian kernel: [0,-1,0,-1,4,-1,0,-1,0]
|
||||
var cw = canvas.width;
|
||||
var laplacianSum = 0;
|
||||
var laplacianCount = 0;
|
||||
for (var y = 1; y < canvas.height - 1; y++) {
|
||||
for (var x = 1; x < cw - 1; x++) {
|
||||
var idx = y * cw + x;
|
||||
var lap = 4 * gray[idx] - gray[idx - 1] - gray[idx + 1] - gray[idx - cw] - gray[idx + cw];
|
||||
laplacianSum += lap * lap;
|
||||
laplacianCount++;
|
||||
}
|
||||
}
|
||||
var blurScore = laplacianSum / laplacianCount;
|
||||
// Typical thresholds: <100 = very blurry, 100-300 = moderate, >300 = sharp
|
||||
if (blurScore < 50) {
|
||||
checks.push({ok: false, text: "Sharpness: very blurry — text will be unreadable"});
|
||||
warnings.push("Your photo is too blurry. Hold the camera steady and make sure the ID is in focus before taking the picture.");
|
||||
} else if (blurScore < 150) {
|
||||
checks.push({ok: false, text: "Sharpness: somewhat blurry — try retaking"});
|
||||
warnings.push("Your photo may be slightly blurry. For best results, hold the camera steady and ensure good lighting.");
|
||||
} else if (blurScore < 400) {
|
||||
checks.push({ok: true, text: "Sharpness: acceptable"});
|
||||
} else {
|
||||
checks.push({ok: true, text: "Sharpness: good, text should be readable"});
|
||||
}
|
||||
}
|
||||
} catch (blurErr) {
|
||||
// Blur check failed silently — not critical
|
||||
}
|
||||
}
|
||||
|
||||
// Render checks
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue