TheFrenchDemos commited on
Commit
1244a5c
·
verified ·
1 Parent(s): ef996ab

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +134 -148
templates/index.html CHANGED
@@ -3,190 +3,176 @@
3
  <html lang="en">
4
  <head>
5
  <meta charset="UTF-8">
6
- <title>Compare Two Images</title>
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
9
  <style>
10
- .preset-image-container { width: 100%; overflow: hidden; margin-bottom: 10px; }
11
- .preset-image { width: 100%; height: auto; cursor: pointer; transition: transform 0.2s, border 0.2s; border: 2px solid transparent; border-radius: 8px; }
12
- .preset-image:hover { transform: scale(1.05); }
13
- .preset-image.selected { border-color: #0d6efd; }
14
- .dropzone { border: 2px dashed #ccc; padding: 20px; text-align: center; margin-top: 10px; border-radius: 8px; background-color: #f9f9f9; }
15
- .preview-image { width: 100%; max-width: 200px; height: auto; margin: 10px auto; display: block; border-radius: 8px; opacity: 0; transition: opacity 0.5s ease-in; }
16
- .preview-image.visible { opacity: 1; }
17
- .loading-container { text-align: center; margin-top: 20px; }
18
- .loading-text { margin-top: 10px; font-size: 18px; color: #555; }
19
- .jauge-container { display: flex; align-items: center; }
20
- .jauge { position: relative; width: 40px; height: 200px; border: 2px solid #ccc; border-radius: 10px; background: #f0f0f0; overflow: hidden; margin-right: 20px; }
21
- .jauge-level { position: absolute; width: 100%; bottom: 0; border-radius: 8px; transition: height 1s ease, background-color 1s ease; }
22
- .jauge-labels { display: flex; flex-direction: column; justify-content: space-between; height: 200px; font-size: 0.8rem; text-align: left; }
23
- #compareSection { margin-top: 30px; text-align: center; }
24
- #results { margin-top: 20px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  </style>
26
  </head>
27
  <body>
28
- <div class="container my-4">
29
- <h1 class="text-center">Fraud Score</h1>
 
30
 
31
- <div class="row mt-4">
 
32
  <div class="col-md-6">
33
- <h5 class="text-center">Select Original Image</h5>
34
  <div class="row">
35
- <div class="col-4">
36
- <div class="preset-image-container">
37
- <img id="preset-1-1" src="/static/marilyn_1.jpg" class="preset-image" onclick="selectPreset(1, 1)" alt="Original 1">
38
- </div>
39
- </div>
40
- <div class="col-4">
41
- <div class="preset-image-container">
42
- <img id="preset-2-1" src="/static/star wars_1b.jpg" class="preset-image" onclick="selectPreset(2, 1)" alt="Original 2">
43
- </div>
44
- </div>
45
- <div class="col-4">
46
- <div class="preset-image-container">
47
- <img id="preset-3-1" src="/static/muhammad ali_1.jpg" class="preset-image" onclick="selectPreset(3, 1)" alt="Original 3">
48
- </div>
49
- </div>
50
  </div>
51
- <div class="dropzone" id="dropzone1">
52
- <p>Or drag and drop an image here (.jpg .jpeg .png .webp)</p>
53
  <input type="file" id="fileInput1" accept="image/*" hidden>
54
- <button class="btn btn-outline-primary" onclick="document.getElementById('fileInput1').click()">Upload Original</button>
55
  </div>
56
  </div>
 
 
57
  <div class="col-md-6">
58
- <h5 class="text-center">Select AI Generated Image</h5>
59
  <div class="row">
60
- <div class="col-4">
61
- <div class="preset-image-container">
62
- <img id="preset-1-2" src="/static/marilyn_2.png" class="preset-image" onclick="selectPreset(1, 2)" alt="AI 1">
63
- </div>
64
- </div>
65
- <div class="col-4">
66
- <div class="preset-image-container">
67
- <img id="preset-2-2" src="/static/star wars_2b.png" class="preset-image" onclick="selectPreset(2, 2)" alt="AI 2">
68
- </div>
69
- </div>
70
- <div class="col-4">
71
- <div class="preset-image-container">
72
- <img id="preset-3-2" src="/static/muhammad ali_2.png" class="preset-image" onclick="selectPreset(3, 2)" alt="AI 3">
73
- </div>
74
- </div>
75
  </div>
76
- <div class="dropzone" id="dropzone2">
77
- <p>Or drag and drop an image here (.jpg .jpeg .png .webp)</p>
78
  <input type="file" id="fileInput2" accept="image/*" hidden>
79
- <button class="btn btn-outline-primary" onclick="document.getElementById('fileInput2').click()">Upload AI Image</button>
80
  </div>
81
  </div>
82
  </div>
83
 
84
- <div id="compareSection" class="d-flex justify-content-center align-items-center flex-column" style="display: none;">
85
- <div class="d-flex justify-content-around align-items-center w-100">
86
- <img id="previewImage1" class="preview-image" alt="Original Preview">
87
- <div id="compareButtonContainer"></div>
88
- <img id="previewImage2" class="preview-image" alt="AI Preview">
89
- </div>
90
- <div id="results"></div>
91
- </div>
92
 
93
- <h2>Fraud Score: <span id="euclidVal"></span>%</h2>
94
- <div class="jauge-container">
95
- <div class="jauge">
96
- <div class="jauge-level" id="jaugeLevel"></div>
97
- </div>
98
- <div class="jauge-labels">
99
- <span>most certainly</span>
100
- <span>very probably</span>
101
- <span>probably</span>
102
- <span>possibly</span>
103
- <span>probably not</span>
104
- <span>definitely not</span>
 
 
 
 
105
  </div>
 
 
106
  </div>
107
  </div>
 
108
  <script>
109
- let file1 = null, file2 = null;
110
- function resetSelection(target) {
111
- for (let i = 1; i <= 3; i++) {
112
- const img = document.getElementById(`preset-${i}-${target}`);
113
- if (img) img.classList.remove('selected');
114
  }
115
  }
116
- function selectPreset(presetNumber, target) {
117
- const imgElement = document.getElementById(`preset-${presetNumber}-${target}`);
118
- const imagePath = imgElement.getAttribute('src');
119
- fetch(imagePath)
120
- .then(res => res.blob())
121
- .then(blob => {
122
- const file = new File([blob], imagePath.split('/').pop(), { type: blob.type });
123
- if (target === 1) {
124
- file1 = file;
125
- updatePreview(blob, 1);
126
- resetSelection(1);
127
- imgElement.classList.add('selected');
128
- } else {
129
- file2 = file;
130
- updatePreview(blob, 2);
131
- resetSelection(2);
132
- imgElement.classList.add('selected');
133
- }
134
- checkReadyToCompare();
135
- });
136
  }
137
- function updatePreview(blob, target) {
138
- const reader = new FileReader();
139
- reader.onload = event => {
140
- const img = document.getElementById(`previewImage${target}`);
141
- img.src = event.target.result;
142
  img.classList.add('visible');
143
- document.getElementById('compareSection').style.display = 'flex';
144
  };
145
- reader.readAsDataURL(blob);
146
  }
147
- document.getElementById('fileInput1').addEventListener('change', (e) => {
148
- file1 = e.target.files[0];
149
- updatePreview(file1, 1);
150
- resetSelection(1);
151
- checkReadyToCompare();
152
  });
153
- document.getElementById('fileInput2').addEventListener('change', (e) => {
154
- file2 = e.target.files[0];
155
- updatePreview(file2, 2);
156
- resetSelection(2);
157
- checkReadyToCompare();
158
  });
159
- function checkReadyToCompare() {
160
- const container = document.getElementById('compareButtonContainer');
161
- if (file1 && file2) {
162
- container.innerHTML = `<button class="btn btn-primary" onclick="processImages()">Calculate Fraud Score</button>`;
163
- } else {
164
- container.innerHTML = '';
165
  }
166
  }
167
- async function processImages() {
168
- const formData = new FormData();
169
- formData.append('image1', file1);
170
- formData.append('image2', file2);
171
- const resultsDiv = document.getElementById('results');
172
- resultsDiv.innerHTML = `<div class='loading-container'><div class='spinner-border text-primary' role='status'></div><div class='loading-text'>Processing...</div></div>`;
173
- const response = await fetch('/process', { method: 'POST', body: formData });
174
- const data = await response.json();
175
- if (data.distance !== undefined) {
176
- const euclid = data.distance;
177
- const fraudScore = Math.max(5, 174 - 2.4 * euclid);
178
- document.getElementById('euclidVal').textContent = fraudScore.toFixed(2);
179
- const level = fraudScore;
180
- let color = '#ccc';
181
- if (level > 90) color = '#dc3545';
182
- else if (level > 75) color = '#fd7e14';
183
- else if (level > 60) color = '#ffc107';
184
- else if (level > 45) color = '#0dcaf0';
185
- else if (level > 30) color = '#0d6efd';
186
- else color = '#198754';
187
- document.getElementById('jaugeLevel').style.height = `${level}%`;
188
- document.getElementById('jaugeLevel').style.backgroundColor = color;
189
- resultsDiv.innerHTML = `<div class="card mt-3 p-4 text-center"><h4>Fraud Score</h4><p class="display-6">${fraudScore.toFixed(2)}%</p></div>`;
 
 
 
 
 
190
  }
191
  }
192
  </script>
 
3
  <html lang="en">
4
  <head>
5
  <meta charset="UTF-8">
6
+ <title>Fraud Score</title>
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
9
  <style>
10
+ :root{
11
+ --apple-blue:#007aff;
12
+ --apple-gray:#f2f2f7;
13
+ --apple-border:#d1d1d6;
14
+ --apple-shadow:0 4px 12px rgba(0,0,0,.08);
15
+ }
16
+ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;background:var(--apple-gray);color:#1c1c1e;}
17
+ h1,h2,h5{font-weight:600;}
18
+ /* preset thumbnails */
19
+ .preset-image-container{overflow:hidden;margin-bottom:12px}
20
+ .preset-image{width:100%;border-radius:12px;border:2px solid transparent;box-shadow:var(--apple-shadow);transition:transform .3s ease,border-color .3s ease;cursor:pointer}
21
+ .preset-image:hover{transform:scale(1.05)}
22
+ .preset-image.selected{border-color:var(--apple-blue)}
23
+ /* dropzone */
24
+ .dropzone{border:2px dashed var(--apple-border);border-radius:16px;background:#fff;padding:20px;text-align:center;box-shadow:var(--apple-shadow)}
25
+ /* preview */
26
+ .preview-image{max-width:220px;border-radius:16px;box-shadow:var(--apple-shadow);opacity:0;transition:opacity .4s ease}
27
+ .preview-image.visible{opacity:1}
28
+ /* buttons */
29
+ .btn-primary{background:var(--apple-blue);border:none;font-weight:500}
30
+ .btn-primary:hover{background:#005ecb}
31
+ /* gauge */
32
+ .jauge-container{display:none;align-items:center;gap:14px;margin-top:24px}
33
+ .jauge{width:24px;height:160px;border-radius:12px;background:#e5e5ea;position:relative;overflow:hidden;border:1px solid var(--apple-border)}
34
+ .jauge-level{position:absolute;bottom:0;width:100%;border-radius:12px;background:var(--apple-blue);transition:height .6s ease,background .3s ease}
35
+ .jauge-labels{font-size:.7rem;color:#636366;display:flex;flex-direction:column;justify-content:space-between;height:160px}
36
+ /* sections */
37
+ #compareSection{margin-top:40px;text-align:center;display:none}
38
  </style>
39
  </head>
40
  <body>
41
+ <div class="container py-5">
42
+ <h1 class="text-center mb-1">Fraud Score</h1>
43
+ <p class="text-center text-muted mb-5 fs-5">Are my works used by generative AI?</p>
44
 
45
+ <div class="row g-5">
46
+ <!-- Original column -->
47
  <div class="col-md-6">
48
+ <h5 class="text-center mb-3">Select Original Image</h5>
49
  <div class="row">
50
+ <div class="col-4"><div class="preset-image-container"><img id="preset-1-1" src="/static/marilyn_1.jpg" class="preset-image" onclick="selectPreset(1,1)" alt="Original 1"></div></div>
51
+ <div class="col-4"><div class="preset-image-container"><img id="preset-2-1" src="/static/star wars_1b.jpg" class="preset-image" onclick="selectPreset(2,1)" alt="Original 2"></div></div>
52
+ <div class="col-4"><div class="preset-image-container"><img id="preset-3-1" src="/static/muhammad ali_1.jpg" class="preset-image" onclick="selectPreset(3,1)" alt="Original 3"></div></div>
 
 
 
 
 
 
 
 
 
 
 
 
53
  </div>
54
+ <div class="dropzone mt-3" id="dropzone1">
55
+ <p class="mb-2">Drag & Drop or Upload (.jpg/.png/.webp)</p>
56
  <input type="file" id="fileInput1" accept="image/*" hidden>
57
+ <button class="btn btn-outline-secondary" onclick="document.getElementById('fileInput1').click()">Upload</button>
58
  </div>
59
  </div>
60
+
61
+ <!-- AI column -->
62
  <div class="col-md-6">
63
+ <h5 class="text-center mb-3">Select AI Generated Image</h5>
64
  <div class="row">
65
+ <div class="col-4"><div class="preset-image-container"><img id="preset-1-2" src="/static/marilyn_2.png" class="preset-image" onclick="selectPreset(1,2)" alt="AI 1"></div></div>
66
+ <div class="col-4"><div class="preset-image-container"><img id="preset-2-2" src="/static/star wars_2b.png" class="preset-image" onclick="selectPreset(2,2)" alt="AI 2"></div></div>
67
+ <div class="col-4"><div class="preset-image-container"><img id="preset-3-2" src="/static/muhammad ali_2.png" class="preset-image" onclick="selectPreset(3,2)" alt="AI 3"></div></div>
 
 
 
 
 
 
 
 
 
 
 
 
68
  </div>
69
+ <div class="dropzone mt-3" id="dropzone2">
70
+ <p class="mb-2">Drag & Drop or Upload (.jpg/.png/.webp)</p>
71
  <input type="file" id="fileInput2" accept="image/*" hidden>
72
+ <button class="btn btn-outline-secondary" onclick="document.getElementById('fileInput2').click()">Upload</button>
73
  </div>
74
  </div>
75
  </div>
76
 
77
+ <!-- Compare / previews + button + gauge -->
78
+ <div id="compareSection">
79
+ <div class="d-flex justify-content-center align-items-center gap-5 mt-5">
80
+ <img id="previewImage1" class="preview-image" alt="Original preview">
 
 
 
 
81
 
82
+ <div class="d-flex flex-column align-items-center">
83
+ <!-- dynamic button here -->
84
+ <div id="compareButtonContainer" class="mb-3"></div>
85
+ <!-- hidden score & gauge -->
86
+ <div id="scoreBlock" style="display:none;">
87
+ <h2 class="fw-semibold mb-3">Fraud Score <span id="euclidVal" class="text-muted"></span>%</h2>
88
+ <div class="jauge-container mx-auto" id="gaugeWrapper">
89
+ <div class="jauge"><div class="jauge-level" id="jaugeLevel"></div></div>
90
+ <div class="jauge-labels text-start">
91
+ <span>most certainly</span><span>very probably</span><span>probably</span><span>possibly</span><span>probably not</span><span>definitely not</span>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <img id="previewImage2" class="preview-image" alt="AI preview">
98
  </div>
99
+
100
+ <div id="results" class="mt-4"></div>
101
  </div>
102
  </div>
103
+
104
  <script>
105
+ let file1=null, file2=null;
106
+ function resetSelection(target){
107
+ for(let i=1;i<=3;i++){
108
+ const thumb=document.getElementById(`preset-${i}-${target}`);
109
+ if(thumb)thumb.classList.remove('selected');
110
  }
111
  }
112
+ function selectPreset(n,target){
113
+ const imgEl=document.getElementById(`preset-${n}-${target}`);
114
+ const src=imgEl.src;
115
+ fetch(src).then(r=>r.blob()).then(blob=>{
116
+ const file=new File([blob],src.split('/').pop(),{type:blob.type});
117
+ if(target===1){file1=file;} else {file2=file;}
118
+ updatePreview(blob,target);
119
+ resetSelection(target);
120
+ imgEl.classList.add('selected');
121
+ checkReady();
122
+ });
 
 
 
 
 
 
 
 
 
123
  }
124
+ function updatePreview(fileOrBlob,target){
125
+ const reader=new FileReader();
126
+ reader.onload=e=>{
127
+ const img=document.getElementById(`previewImage${target}`);
128
+ img.src=e.target.result;
129
  img.classList.add('visible');
130
+ document.getElementById('compareSection').style.display='block';
131
  };
132
+ reader.readAsDataURL(fileOrBlob);
133
  }
134
+ document.getElementById('fileInput1').addEventListener('change',e=>{
135
+ if(e.target.files.length){file1=e.target.files[0];updatePreview(file1,1);resetSelection(1);checkReady();}
 
 
 
136
  });
137
+ document.getElementById('fileInput2').addEventListener('change',e=>{
138
+ if(e.target.files.length){file2=e.target.files[0];updatePreview(file2,2);resetSelection(2);checkReady();}
 
 
 
139
  });
140
+ function checkReady(){
141
+ const container=document.getElementById('compareButtonContainer');
142
+ if(file1&&file2){
143
+ container.innerHTML='<button class="btn btn-primary" onclick="processImages()">Calculate Fraud Score</button>';
144
+ }else{
145
+ container.innerHTML='';
146
  }
147
  }
148
+ async function processImages(){
149
+ const fd=new FormData();
150
+ fd.append('image1',file1);
151
+ fd.append('image2',file2);
152
+ const resDiv=document.getElementById('results');
153
+ resDiv.innerHTML='<div class="spinner-border text-primary"></div>';
154
+ try{
155
+ const res=await fetch('/process',{method:'POST',body:fd});
156
+ const data=await res.json();
157
+ const euclid=parseFloat(data.distance);
158
+ const fraud=Math.min(100,Math.max(2,185-2.73*euclid));
159
+ // show score block and update value
160
+ document.getElementById('euclidVal').textContent=fraud.toFixed(1);
161
+ document.getElementById('scoreBlock').style.display='block';
162
+ // gauge color & height
163
+ let color='#198754';
164
+ if(fraud>90)color='#dc3545';
165
+ else if(fraud>75)color='#fd7e14';
166
+ else if(fraud>60)color='#ffc107';
167
+ else if(fraud>45)color='#0dcaf0';
168
+ else if(fraud>30)color='#0d6efd';
169
+ const gaugeLevel=document.getElementById('jaugeLevel');
170
+ gaugeLevel.style.height=`${Math.min(100,fraud)}%`;
171
+ gaugeLevel.style.backgroundColor=color;
172
+ document.getElementById('gaugeWrapper').style.display='flex';
173
+ resDiv.innerHTML='';
174
+ }catch(err){
175
+ resDiv.innerHTML='<div class="text-danger">Error processing images.</div>';
176
  }
177
  }
178
  </script>