Sam1 / index.html
Samarth043's picture
Update index.html
70e8190 verified
Raw History Blame Contribute Delete
6.62 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AI Image Detector</title>
<style>
body{margin:0;font:16px/1.5 system-ui,sans-serif;background:#0f151b;color:#e8eef3}
main{max-width:520px;margin:0 auto;padding:24px 16px}
h1{font-size:28px;margin:8px 0}
p{color:#93a3b1}
input{display:block;width:100%;margin:16px 0;padding:14px;background:#18212a;border:2px dashed #2c3844;border-radius:12px;color:#e8eef3}
img{max-width:100%;border-radius:10px;margin-top:8px}
#res{background:#18212a;border-radius:12px;padding:16px;margin-top:16px;display:none}
h2{margin:0 0 6px;font-size:24px}
h3{margin:16px 0 4px;font-size:15px;color:#93a3b1;font-weight:600}
#sub{color:#c5d0da;margin:0}
.bar{height:12px;background:#2c3844;border-radius:6px;overflow:hidden;margin:6px 0 10px}
.bar div{height:100%;background:#6f93ff;width:0}
li{color:#f0b04a;margin:4px 0}
small{color:#93a3b1}
</style>
</head>
<body>
<main>
<h1>Was this image made by AI?</h1>
<p>Runs on your phone. Your image is never uploaded. The first check downloads two models (a few hundred MB), so use Wi-Fi.</p>
<input id="f" type="file" accept="image/*">
<img id="p" alt="">
<div id="res">
<h2 id="v"></h2>
<p id="sub"></p>
<h3>Hidden labels</h3>
<ul id="m"></ul>
<h3>Pixel check 1</h3>
<div id="pct1"></div>
<div class="bar"><div id="b1"></div></div>
<h3>Pixel check 2</h3>
<div id="pct2"></div>
<div class="bar"><div id="b2"></div></div>
<small id="raw"></small><br><br>
<small>A probability, not proof. Detectors can be wrong, especially on new generators and screenshots.</small>
</div>
</main>
<script type="module">
import { pipeline, AutoProcessor, AutoModelForImageClassification, RawImage } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3';
const $ = id => document.getElementById(id);
const MODEL1 = 'buildborderless/CommunityForensics-DeepfakeDet-ViT';
const MODEL2 = 'LPX55/detection-model-2-ONNX';
let processor, model, clf2, fail2 = '';
async function load1(){
if(model) return;
processor = await AutoProcessor.from_pretrained(MODEL1);
model = await AutoModelForImageClassification.from_pretrained(MODEL1, { dtype: 'fp32' });
}
async function load2(){
if(clf2 || fail2) return;
try { clf2 = await pipeline('image-classification', MODEL2, { dtype: 'fp32' }); }
catch(e){ fail2 = String(e); }
}
const TOOLS = [
[/\bmidjourney\b/i,'Midjourney'],
[/\bopenai\b|\bdall[\s\-_·]?e\b/i,'OpenAI / DALL·E'],
[/stable[\s\-_]?diffusion|stability\.ai|automatic1111|\bsdxl\b/i,'Stable Diffusion'],
[/adobe firefly|\bfirefly\b|generative ?fill/i,'Adobe Firefly'],
[/\bimagen\b|\bgemini\b|\bsynthid\b|google ai/i,'Google AI'],
[/leonardo\.ai/i,'Leonardo AI'],
[/\bcomfyui\b/i,'ComfyUI'],
[/\bideogram\b/i,'Ideogram']
];
function markers(bytes){
const full = new TextDecoder('latin1').decode(bytes), out = [];
const runs = full.match(/[\x20-\x7e]{6,}/g);
const readable = runs ? runs.join('\n') : '';
if(/c2pa|jumbf|contentcredentials/i.test(full)) out.push('Content Credentials (C2PA) found');
if(/algorithmicMedia/.test(full)) out.push('Marked as AI media in metadata');
TOOLS.forEach(([re,n]) => { if(re.test(readable)) out.push('Names an AI tool: ' + n); });
if(/Steps:\s*\d+,\s*Sampler|negative prompt|"class_type"/i.test(readable)) out.push('Contains a generation prompt or settings');
return out;
}
function li(text, color){ const e = document.createElement('li'); e.textContent = text; if(color) e.style.color = color; return e; }
function show(n, ai){
if(ai === null){ $('pct'+n).textContent = 'Not available'; $('b'+n).style.width = '0'; return; }
$('pct'+n).textContent = 'Chance it is AI: ' + Math.round(ai*100) + '%';
$('b'+n).style.width = Math.round(ai*100) + '%';
}
$('f').onchange = async e => {
const file = e.target.files[0]; if(!file) return;
const url = URL.createObjectURL(file);
$('p').src = url;
$('res').style.display = 'block';
$('v').textContent = 'Loading models, please wait...';
$('sub').textContent = ''; $('m').innerHTML = ''; $('raw').textContent = '';
['1','2'].forEach(n => { $('pct'+n).textContent = ''; $('b'+n).style.width = '0'; });
try {
const mk = markers(new Uint8Array(await file.arrayBuffer()));
await load1();
$('v').textContent = 'Checking...';
const image = await RawImage.read(url);
const inputs = await processor(image);
const { logits } = await model(inputs);
const z = Array.from(logits.data);
let ai1;
if(z.length === 1){ ai1 = 1 / (1 + Math.exp(-z[0])); }
else { const m = Math.max(...z), ex = z.map(v => Math.exp(v - m)), s = ex.reduce((a,b) => a + b, 0); ai1 = ex[1] / s; }
show('1', ai1);
$('v').textContent = 'Loading second check...';
await load2();
let ai2 = null, raw2 = '';
if(clf2){
const r = await clf2(url, { top_k: 5 });
raw2 = r.map(x => x.label + ' ' + Math.round(x.score*100) + '%').join(', ');
const hit = r.find(x => /artificial|fake|synth|generat|\bai\b/i.test(x.label));
const real = r.find(x => /real|human|natural|authentic/i.test(x.label));
if(hit) ai2 = hit.score; else if(real) ai2 = 1 - real.score;
}
show('2', ai2);
$('raw').textContent = 'Check 1 raw score: ' + z.map(v => v.toFixed(2)).join(', ') + (clf2 ? ' | Check 2 output: ' + raw2 : ' | Check 2 could not load: ' + fail2.slice(0,120));
if(mk.length){ mk.forEach(t => $('m').appendChild(li(t))); }
else { $('m').appendChild(li('None found. Screenshots and forwarded images often lose their labels.', '#93a3b1')); }
const ai = Math.max(ai1, ai2 === null ? 0 : ai2);
if(mk.length){
$('v').textContent = 'AI markers found';
$('sub').textContent = ai >= 0.5
? "The file's labels say AI, and at least one pixel check agrees."
: "The file's labels say AI. Both pixel checks disagreed, which can happen with newer generators, so trust the labels.";
} else if(ai >= 0.85){
$('v').textContent = 'Likely AI-generated';
$('sub').textContent = 'No labels found, but a pixel check says AI.';
} else if(ai >= 0.5){
$('v').textContent = 'Possibly AI';
$('sub').textContent = 'No labels found and the pixel checks are unsure.';
} else {
$('v').textContent = 'No AI signs found';
$('sub').textContent = 'No labels found and the pixel checks say real. These models can miss newer AI images, so this is not proof.';
}
} catch(err){
$('v').textContent = 'Could not analyze this image.';
$('raw').textContent = String(err);
}
};
</script>
</body>
</html>