Refactor HTML generation with Tailwind CSS and enhanced model result visualization
Browse files- Replace Bootstrap with Tailwind CSS for more flexible styling
- Implement dynamic color-coding for model result cards
- Add detailed model information and confidence score displays
- Improve layout and responsiveness of results presentation
- Update Gradio interface column scaling for better visual balance
app.py
CHANGED
|
@@ -67,7 +67,7 @@ def predict_image(img, confidence_threshold):
|
|
| 67 |
try:
|
| 68 |
prediction_1 = clf_1(img_pil)
|
| 69 |
result_1 = {pred['label']: pred['score'] for pred in prediction_1}
|
| 70 |
-
result_1output = [1, result_1['real'], result_1['artificial']]
|
| 71 |
print(result_1output)
|
| 72 |
# Ensure the result dictionary contains all class names
|
| 73 |
for class_name in class_names_1:
|
|
@@ -91,7 +91,7 @@ def predict_image(img, confidence_threshold):
|
|
| 91 |
try:
|
| 92 |
prediction_2 = clf_2(img_pil)
|
| 93 |
result_2 = {pred['label']: pred['score'] for pred in prediction_2}
|
| 94 |
-
result_2output = [2, result_2['Real Image'], result_2['AI Image']]
|
| 95 |
print(result_2output)
|
| 96 |
# Ensure the result dictionary contains all class names
|
| 97 |
for class_name in class_names_2:
|
|
@@ -121,7 +121,7 @@ def predict_image(img, confidence_threshold):
|
|
| 121 |
labels_3[1]: float(probabilities_3[1]), # Real
|
| 122 |
labels_3[0]: float(probabilities_3[0]) # AI
|
| 123 |
}
|
| 124 |
-
result_3output = [3, float(probabilities_3[1]), float(probabilities_3[0])]
|
| 125 |
print(result_3output)
|
| 126 |
# Ensure the result dictionary contains all class names
|
| 127 |
for class_name in labels_3:
|
|
@@ -151,7 +151,7 @@ def predict_image(img, confidence_threshold):
|
|
| 151 |
labels_4[1]: float(probabilities_4[1]), # Real
|
| 152 |
labels_4[0]: float(probabilities_4[0]) # AI
|
| 153 |
}
|
| 154 |
-
result_4output = [4, float(probabilities_4[1]), float(probabilities_4[0])]
|
| 155 |
print(result_4)
|
| 156 |
# Ensure the result dictionary contains all class names
|
| 157 |
for class_name in labels_4:
|
|
@@ -171,7 +171,7 @@ def predict_image(img, confidence_threshold):
|
|
| 171 |
label_4 = f"Error: {str(e)}"
|
| 172 |
|
| 173 |
try:
|
| 174 |
-
result_5output = [5, 0.0, 0.0, 'MAINTENANCE']
|
| 175 |
img_bytes = convert_pil_to_bytes(img_pil)
|
| 176 |
# print(img)
|
| 177 |
# print(img_bytes)
|
|
@@ -195,137 +195,239 @@ def predict_image(img, confidence_threshold):
|
|
| 195 |
combined_outputs = [ result_1output, result_2output, result_3output, result_4output, result_5output ]
|
| 196 |
return img_pil, combined_outputs
|
| 197 |
|
|
|
|
| 198 |
# Define a function to generate the HTML content
|
| 199 |
def generate_results_html(results):
|
| 200 |
def get_header_color(label):
|
| 201 |
if label == 'AI':
|
| 202 |
-
return 'bg-
|
| 203 |
elif label == 'REAL':
|
| 204 |
-
return 'bg-
|
| 205 |
elif label == 'UNCERTAIN':
|
| 206 |
-
return 'bg-
|
| 207 |
elif label == 'MAINTENANCE':
|
| 208 |
-
return 'bg-
|
| 209 |
else:
|
| 210 |
-
return 'bg-
|
| 211 |
-
|
| 212 |
html_content = f"""
|
| 213 |
-
<link href="https://
|
| 214 |
-
<div class="container">
|
| 215 |
-
<div class="
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
<p>{results[3][3]}</p>
|
| 231 |
-
</div>
|
| 232 |
-
<div class="col">
|
| 233 |
-
<h5>GOAT <span class="badge badge-secondary ml-1">M5</span></h5>
|
| 234 |
-
<p>{results[4][3]}</p>
|
| 235 |
-
</div>
|
| 236 |
-
</div>
|
| 237 |
-
<div class="col">
|
| 238 |
-
<div class="card-group">
|
| 239 |
-
<div class="card">
|
| 240 |
-
<div class="card-header {get_header_color(results[0][-1])}" style="height:120px;">
|
| 241 |
-
<span class="text-center font-weight-bolder">{results[0][-1]}</span>
|
| 242 |
-
</div>
|
| 243 |
-
<div class="card-body">
|
| 244 |
-
<h5 class="card-title">SwinV2/detect <span class="badge badge-secondary ml-1">M1</span></h5>
|
| 245 |
-
|
| 246 |
-
<div class="progress">
|
| 247 |
-
<div class="progress-bar" role="progressbar" style="width: {results[0][-3] * 100:.2f}%;" aria-valuenow="{results[0][-3] * 100:.2f}" aria-valuemin="0" aria-valuemax="100">{results[0][-3] * 100:.2f}% (Real)</div>
|
| 248 |
-
</div>
|
| 249 |
-
<div class="progress">
|
| 250 |
-
<div class="progress-bar bg-danger" role="progressbar" style="width: {results[0][-4] * 100:.2f}%;" aria-valuenow="{results[0][-4] * 100:.2f}" aria-valuemin="0" aria-valuemax="100">{results[0][-4] * 100:.2f}% (AI)</div>
|
| 251 |
-
</div>
|
| 252 |
-
</div>
|
| 253 |
-
<div class="card-footer">
|
| 254 |
-
<small class="text-muted">model by @haywoodsloan / more info</small>
|
| 255 |
-
</div>
|
| 256 |
</div>
|
| 257 |
-
<div
|
| 258 |
-
<div class="
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
</div>
|
| 267 |
-
<div class="progress">
|
| 268 |
-
<div class="progress-bar bg-danger" role="progressbar" style="width: {results[0][-4] * 100:.2f}%;" aria-valuenow="{results[0][-4] * 100:.2f}" aria-valuemin="0" aria-valuemax="100">{results[0][-4] * 100:.2f}% (AI)</div>
|
| 269 |
</div>
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
</div>
|
| 274 |
</div>
|
| 275 |
-
<div class="
|
| 276 |
-
<
|
| 277 |
-
<
|
| 278 |
-
</div>
|
| 279 |
-
<
|
| 280 |
-
<
|
| 281 |
-
|
| 282 |
-
<div class="progress">
|
| 283 |
-
<div class="progress-bar" role="progressbar" style="width: {results[0][-3] * 100:.2f}%;" aria-valuenow="{results[0][-3] * 100:.2f}" aria-valuemin="0" aria-valuemax="100">{results[0][-3] * 100:.2f}% (Real)</div>
|
| 284 |
-
</div>
|
| 285 |
-
<div class="progress">
|
| 286 |
-
<div class="progress-bar bg-danger" role="progressbar" style="width: {results[0][-4] * 100:.2f}%;" aria-valuenow="{results[0][-4] * 100:.2f}" aria-valuemin="0" aria-valuemax="100">{results[0][-4] * 100:.2f}% (AI)</div>
|
| 287 |
-
</div>
|
| 288 |
-
</div>
|
| 289 |
-
<div class="card-footer">
|
| 290 |
-
<small class="text-muted">model by @haywoodsloan / more info</small>
|
| 291 |
-
</div>
|
| 292 |
</div>
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
<
|
| 301 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
</div>
|
| 303 |
-
<div class="
|
| 304 |
-
<div class="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
</div>
|
| 307 |
-
<div class="
|
| 308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
</div>
|
| 310 |
</div>
|
| 311 |
-
<div class="
|
| 312 |
-
<
|
| 313 |
-
<
|
| 314 |
-
</div>
|
| 315 |
-
<
|
| 316 |
-
<
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
</div>
|
| 321 |
-
<div class="
|
| 322 |
-
<div class="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
</div>
|
| 325 |
-
<div class="
|
| 326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
</div>
|
| 328 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
</div>
|
| 330 |
</div>
|
| 331 |
</div>
|
|
@@ -343,11 +445,11 @@ with gr.Blocks() as iface:
|
|
| 343 |
gr.Markdown("# AI Generated Image Classification")
|
| 344 |
|
| 345 |
with gr.Row():
|
| 346 |
-
with gr.Column(scale=
|
| 347 |
image_input = gr.Image(label="Upload Image to Analyze", sources=['upload'], type='pil')
|
| 348 |
confidence_slider = gr.Slider(0.0, 1.0, value=0.5, step=0.01, label="Confidence Threshold")
|
| 349 |
inputs = [image_input, confidence_slider]
|
| 350 |
-
with gr.Column(scale=
|
| 351 |
image_output = gr.Image(label="Processed Image")
|
| 352 |
# Custom HTML component to display results in 5 columns
|
| 353 |
results_html = gr.HTML(label="Model Predictions")
|
|
|
|
| 67 |
try:
|
| 68 |
prediction_1 = clf_1(img_pil)
|
| 69 |
result_1 = {pred['label']: pred['score'] for pred in prediction_1}
|
| 70 |
+
result_1output = [1, 'SwinV2-base', result_1['real'], result_1['artificial']]
|
| 71 |
print(result_1output)
|
| 72 |
# Ensure the result dictionary contains all class names
|
| 73 |
for class_name in class_names_1:
|
|
|
|
| 91 |
try:
|
| 92 |
prediction_2 = clf_2(img_pil)
|
| 93 |
result_2 = {pred['label']: pred['score'] for pred in prediction_2}
|
| 94 |
+
result_2output = [2, 'ViT-base Classifer', result_2['Real Image'], result_2['AI Image']]
|
| 95 |
print(result_2output)
|
| 96 |
# Ensure the result dictionary contains all class names
|
| 97 |
for class_name in class_names_2:
|
|
|
|
| 121 |
labels_3[1]: float(probabilities_3[1]), # Real
|
| 122 |
labels_3[0]: float(probabilities_3[0]) # AI
|
| 123 |
}
|
| 124 |
+
result_3output = [3, 'SDXL-Trained', float(probabilities_3[1]), float(probabilities_3[0])]
|
| 125 |
print(result_3output)
|
| 126 |
# Ensure the result dictionary contains all class names
|
| 127 |
for class_name in labels_3:
|
|
|
|
| 151 |
labels_4[1]: float(probabilities_4[1]), # Real
|
| 152 |
labels_4[0]: float(probabilities_4[0]) # AI
|
| 153 |
}
|
| 154 |
+
result_4output = [4, 'SDXL + FLUX', float(probabilities_4[1]), float(probabilities_4[0])]
|
| 155 |
print(result_4)
|
| 156 |
# Ensure the result dictionary contains all class names
|
| 157 |
for class_name in labels_4:
|
|
|
|
| 171 |
label_4 = f"Error: {str(e)}"
|
| 172 |
|
| 173 |
try:
|
| 174 |
+
result_5output = [5, 'TBA', 0.0, 0.0, 'MAINTENANCE']
|
| 175 |
img_bytes = convert_pil_to_bytes(img_pil)
|
| 176 |
# print(img)
|
| 177 |
# print(img_bytes)
|
|
|
|
| 195 |
combined_outputs = [ result_1output, result_2output, result_3output, result_4output, result_5output ]
|
| 196 |
return img_pil, combined_outputs
|
| 197 |
|
| 198 |
+
# Define a function to generate the HTML content
|
| 199 |
# Define a function to generate the HTML content
|
| 200 |
def generate_results_html(results):
|
| 201 |
def get_header_color(label):
|
| 202 |
if label == 'AI':
|
| 203 |
+
return 'bg-red-500 text-red-700 bg-red-100', 'bg-red-400', 'bg-red-100', 'bg-red-700 text-red-700', 'bg-red-200'
|
| 204 |
elif label == 'REAL':
|
| 205 |
+
return 'bg-green-500 text-green-700 bg-green-100', 'bg-green-400', 'bg-green-100', 'bg-green-700 text-green-700', 'bg-green-200'
|
| 206 |
elif label == 'UNCERTAIN':
|
| 207 |
+
return 'bg-yellow-500 text-yellow-700 bg-yellow-100', 'bg-yellow-400', 'bg-yellow-100', 'bg-yellow-700 text-yellow-700', 'bg-yellow-200'
|
| 208 |
elif label == 'MAINTENANCE':
|
| 209 |
+
return 'bg-blue-500 text-blue-700 bg-blue-100', 'bg-blue-400', 'bg-blue-100', 'bg-blue-700 text-blue-700', 'bg-blue-200'
|
| 210 |
else:
|
| 211 |
+
return 'bg-gray-300 text-gray-700 bg-gray-100', 'bg-gray-400', 'bg-gray-100', 'bg-gray-700 text-gray-700', 'bg-gray-200'
|
| 212 |
+
|
| 213 |
html_content = f"""
|
| 214 |
+
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
| 215 |
+
<div class="container mx-auto mt-4">
|
| 216 |
+
<div class="grid xl:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-4">
|
| 217 |
+
<!-- Tile 1: SwinV2/detect -->
|
| 218 |
+
<div
|
| 219 |
+
class="group flex flex-col bg-neutral-300 rounded-sm p-4 m-1 border border-neutral-800 shadow-xs transition hover:shadow-lg dark:shadow-gray-700/25">
|
| 220 |
+
<div
|
| 221 |
+
class="-m-4 h-24 {get_header_color(results[0][-1])[0]} rounded-sm rounded-b-none transition border group-hover:border-gray-100 group-hover:shadow-lg group-hover:{get_header_color(results[0][-1])[4]}">
|
| 222 |
+
<span class="text-neutral-300 font-mono tracking-widest p-4 pb-3 block text-xs text-center">MODEL 1: {results[0][1]}</span>
|
| 223 |
+
<span
|
| 224 |
+
class="flex w-24 mx-auto tracking-wide items-center justify-center rounded-full {get_header_color(results[0][-1])[2]} px-2.5 py-0.5 {get_header_color(results[0][-1])[3]}"
|
| 225 |
+
>
|
| 226 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="size-5 mr-2 -ml-3 group-hover:animate group-hover:animate-pulse">
|
| 227 |
+
{'<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />' if results[0][-1] == 'REAL' else '<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'}
|
| 228 |
+
</svg>
|
| 229 |
+
<p class="whitespace-nowrap text-lg leading-normal font-bold text-center self-center align-middle py-px">{results[0][-1]}</p>
|
| 230 |
+
</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
</div>
|
| 232 |
+
<div>
|
| 233 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 234 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 235 |
+
<div class="bg-green-400 h-full rounded-none" style="width: {results[0][2] * 100:.2f}%;">
|
| 236 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 237 |
+
<span class="ml-1 font-medium font-mono">{results[0][2]:.2f}</span>
|
| 238 |
+
</p>
|
| 239 |
+
</div>
|
| 240 |
+
</div>
|
|
|
|
|
|
|
|
|
|
| 241 |
</div>
|
| 242 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 243 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 244 |
+
<div class="bg-red-400 h-full rounded-none" style="width: {results[0][3] * 100:.2f}%;">
|
| 245 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 246 |
+
<span class="ml-1 font-medium font-mono">{results[0][3]:.2f}</span>
|
| 247 |
+
</p>
|
| 248 |
+
</div>
|
| 249 |
+
</div>
|
| 250 |
</div>
|
| 251 |
</div>
|
| 252 |
+
<div class="flex flex-col items-start">
|
| 253 |
+
<h4 class="mt-4 text-sm font-semibold tracking-wide">SwinV2 Based</h4>
|
| 254 |
+
<hr class="py-px my-2 w-full bg-neutral-700" />
|
| 255 |
+
<div class="text-xs font-mono">Real: {results[0][2]:.4f}, AI: {results[0][3]:.4f}</div>
|
| 256 |
+
<hr class="py-px mt-6 w-full bg-neutral-700" />
|
| 257 |
+
<a class="mt-2 text-[0.66rem] tracking-wide">@haywoodsloan / more info</a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
</div>
|
| 259 |
+
</div>
|
| 260 |
+
<!-- Tile 2: ViT/AI-vs-Real -->
|
| 261 |
+
<div
|
| 262 |
+
class="group flex flex-col bg-neutral-300 rounded-sm p-4 m-1 border border-neutral-800 shadow-xs transition hover:shadow-lg dark:shadow-gray-700/25">
|
| 263 |
+
<div
|
| 264 |
+
class="-m-4 h-24 {get_header_color(results[1][-1])[0]} rounded-sm rounded-b-none transition border group-hover:border-gray-100 group-hover:shadow-lg group-hover:{get_header_color(results[1][-1])[4]}">
|
| 265 |
+
<span class="text-neutral-300 font-mono tracking-widest p-4 pb-3 block text-xs text-center">MODEL 2: {results[1][1]}</span>
|
| 266 |
+
<span
|
| 267 |
+
class="flex w-24 mx-auto tracking-wide items-center justify-center rounded-full {get_header_color(results[1][-1])[2]} px-2.5 py-0.5 {get_header_color(results[1][-1])[3]}"
|
| 268 |
+
>
|
| 269 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="size-5 mr-2 -ml-3 group-hover:animate group-hover:animate-pulse">
|
| 270 |
+
{'<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />' if results[1][-1] == 'REAL' else '<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'}
|
| 271 |
+
</svg>
|
| 272 |
+
<p class="whitespace-nowrap text-lg leading-normal font-bold text-center self-center align-middle py-px">{results[1][-1]}</p>
|
| 273 |
+
</span>
|
| 274 |
+
</div>
|
| 275 |
+
<div>
|
| 276 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 277 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 278 |
+
<div class="bg-green-400 h-full rounded-none" style="width: {results[1][1] * 100:.2f}%;">
|
| 279 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 280 |
+
<span class="ml-1 font-medium font-mono">{results[1][1]:.2f}</span>
|
| 281 |
+
</p>
|
| 282 |
+
</div>
|
| 283 |
+
</div>
|
| 284 |
</div>
|
| 285 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 286 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 287 |
+
<div class="bg-red-400 h-full rounded-none" style="width: {results[1][2] * 100:.2f}%;">
|
| 288 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 289 |
+
<span class="ml-1 font-medium font-mono">{results[1][2]:.2f}</span>
|
| 290 |
+
</p>
|
| 291 |
+
</div>
|
| 292 |
+
</div>
|
| 293 |
</div>
|
| 294 |
+
</div>
|
| 295 |
+
<div class="flex flex-col items-start">
|
| 296 |
+
<h4 class="mt-4 text-sm font-semibold tracking-wide">ViT Based</h4>
|
| 297 |
+
<hr class="py-px my-2 w-full bg-neutral-700" />
|
| 298 |
+
<div class="text-xs font-mono">Real: {results[1][1]:.4f}, AI: {results[1][2]:.4f}</div>
|
| 299 |
+
<hr class="py-px mt-6 w-full bg-neutral-700" />
|
| 300 |
+
<a class="mt-2 text-[0.66rem] tracking-wide">@Heem2 / more info</a>
|
| 301 |
+
</div>
|
| 302 |
+
</div>
|
| 303 |
+
<!-- Tile 3: Swin/SDXL -->
|
| 304 |
+
<div
|
| 305 |
+
class="group flex flex-col bg-neutral-300 rounded-sm p-4 m-1 border border-neutral-800 shadow-xs transition hover:shadow-lg dark:shadow-gray-700/25">
|
| 306 |
+
<div
|
| 307 |
+
class="-m-4 h-24 {get_header_color(results[2][-1])[0]} rounded-sm rounded-b-none transition border group-hover:border-gray-100 group-hover:shadow-lg group-hover:{get_header_color(results[2][-1])[4]}">
|
| 308 |
+
<span class="text-neutral-300 font-mono tracking-widest p-4 pb-3 block text-xs text-center">MODEL 3: {results[2][1]}</span>
|
| 309 |
+
<span
|
| 310 |
+
class="flex w-24 mx-auto tracking-wide items-center justify-center rounded-full {get_header_color(results[2][-1])[2]} px-2.5 py-0.5 {get_header_color(results[2][-1])[3]}"
|
| 311 |
+
>
|
| 312 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="size-5 mr-2 -ml-3 group-hover:animate group-hover:animate-pulse">
|
| 313 |
+
{'<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />' if results[2][-1] == 'REAL' else '<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'}
|
| 314 |
+
</svg>
|
| 315 |
+
<p class="whitespace-nowrap text-lg leading-normal font-bold text-center self-center align-middle py-px">{results[2][-1]}</p>
|
| 316 |
+
</span>
|
| 317 |
+
</div>
|
| 318 |
+
<div>
|
| 319 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 320 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 321 |
+
<div class="bg-green-400 h-full rounded-none" style="width: {results[2][1] * 100:.2f}%;">
|
| 322 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 323 |
+
<span class="ml-1 font-medium font-mono">{results[2][1]:.2f}</span>
|
| 324 |
+
</p>
|
| 325 |
+
</div>
|
| 326 |
+
</div>
|
| 327 |
</div>
|
| 328 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 329 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 330 |
+
<div class="bg-red-400 h-full rounded-none" style="width: {results[2][2] * 100:.2f}%;">
|
| 331 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 332 |
+
<span class="ml-1 font-medium font-mono">{results[2][2]:.2f}</span>
|
| 333 |
+
</p>
|
| 334 |
+
</div>
|
| 335 |
+
</div>
|
| 336 |
</div>
|
| 337 |
</div>
|
| 338 |
+
<div class="flex flex-col items-start">
|
| 339 |
+
<h4 class="mt-4 text-sm font-semibold tracking-wide">Swin Based</h4>
|
| 340 |
+
<hr class="py-px my-2 w-full bg-neutral-700" />
|
| 341 |
+
<div class="text-xs font-mono">Real: {results[2][1]:.4f}, AI: {results[2][2]:.4f}</div>
|
| 342 |
+
<hr class="py-px mt-6 w-full bg-neutral-700" />
|
| 343 |
+
<a class="mt-2 text-[0.66rem] tracking-wide">@Organika / more info</a>
|
| 344 |
+
</div>
|
| 345 |
+
</div>
|
| 346 |
+
<!-- Tile 4: Swin/SDXL-FLUX -->
|
| 347 |
+
<div
|
| 348 |
+
class="group flex flex-col bg-neutral-300 rounded-sm p-4 m-1 border border-neutral-800 shadow-xs transition hover:shadow-lg dark:shadow-gray-700/25">
|
| 349 |
+
<div
|
| 350 |
+
class="-m-4 h-24 {get_header_color(results[3][-1])[0]} rounded-sm rounded-b-none transition border group-hover:border-gray-100 group-hover:shadow-lg group-hover:{get_header_color(results[3][-1])[4]}">
|
| 351 |
+
<span class="text-neutral-300 font-mono tracking-widest p-4 pb-3 block text-xs text-center">MODEL 4: {results[3][1]}</span>
|
| 352 |
+
<span
|
| 353 |
+
class="flex w-24 mx-auto tracking-wide items-center justify-center rounded-full {get_header_color(results[3][-1])[2]} px-2.5 py-0.5 {get_header_color(results[3][-1])[3]}"
|
| 354 |
+
>
|
| 355 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="size-5 mr-2 -ml-3 group-hover:animate group-hover:animate-pulse">
|
| 356 |
+
{'<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />' if results[3][-1] == 'REAL' else '<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'}
|
| 357 |
+
</svg>
|
| 358 |
+
<p class="whitespace-nowrap text-lg leading-normal font-bold text-center self-center align-middle py-px">{results[3][-1]}</p>
|
| 359 |
+
</span>
|
| 360 |
+
</div>
|
| 361 |
+
<div>
|
| 362 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 363 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 364 |
+
<div class="bg-green-400 h-full rounded-none" style="width: {results[3][1] * 100:.2f}%;">
|
| 365 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 366 |
+
<span class="ml-1 font-medium font-mono">{results[3][1]:.2f}</span>
|
| 367 |
+
</p>
|
| 368 |
+
</div>
|
| 369 |
+
</div>
|
| 370 |
</div>
|
| 371 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 372 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 373 |
+
<div class="bg-red-400 h-full rounded-none" style="width: {results[3][2] * 100:.2f}%;">
|
| 374 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 375 |
+
<span class="ml-1 font-medium font-mono">{results[3][2]:.2f}</span>
|
| 376 |
+
</p>
|
| 377 |
+
</div>
|
| 378 |
+
</div>
|
| 379 |
</div>
|
| 380 |
+
</div>
|
| 381 |
+
<div class="flex flex-col items-start">
|
| 382 |
+
<h4 class="mt-4 text-sm font-semibold tracking-wide">Swin Based</h4>
|
| 383 |
+
<hr class="py-px my-2 w-full bg-neutral-700" />
|
| 384 |
+
<div class="text-xs font-mono">Real: {results[3][1]:.4f}, AI: {results[3][2]:.4f}</div>
|
| 385 |
+
<hr class="py-px mt-6 w-full bg-neutral-700" />
|
| 386 |
+
<a class="mt-2 text-[0.66rem] tracking-wide">@cmckinle / more info</a>
|
| 387 |
+
</div>
|
| 388 |
+
</div>
|
| 389 |
+
<!-- Tile 5: GOAT -->
|
| 390 |
+
<div
|
| 391 |
+
class="group flex flex-col bg-neutral-300 rounded-sm p-4 m-1 border border-neutral-800 shadow-xs transition hover:shadow-lg dark:shadow-gray-700/25">
|
| 392 |
+
<div
|
| 393 |
+
class="-m-4 h-24 {get_header_color(results[4][-1])[0]} rounded-sm rounded-b-none transition border group-hover:border-gray-100 group-hover:shadow-lg group-hover:{get_header_color(results[4][-1])[4]}">
|
| 394 |
+
<span class="text-neutral-300 font-mono tracking-widest p-4 pb-3 block text-xs text-center">MODEL 5: {results[4][1]}</span>
|
| 395 |
+
<span
|
| 396 |
+
class="flex w-24 mx-auto tracking-wide items-center justify-center rounded-full {get_header_color(results[4][-1])[2]} px-2.5 py-0.5 {get_header_color(results[4][-1])[3]}"
|
| 397 |
+
>
|
| 398 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="size-5 mr-2 -ml-3 group-hover:animate group-hover:animate-pulse">
|
| 399 |
+
{'<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />' if results[4][-1] == 'REAL' else '<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />'}
|
| 400 |
+
</svg>
|
| 401 |
+
<p class="whitespace-nowrap text-lg leading-normal font-bold text-center self-center align-middle py-px">{results[4][-1]}</p>
|
| 402 |
+
</span>
|
| 403 |
+
</div>
|
| 404 |
+
<div>
|
| 405 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 406 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 407 |
+
<div class="bg-green-400 h-full rounded-none" style="width: 50%;">
|
| 408 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 409 |
+
<span class="ml-1 font-medium font-mono">50%</span>
|
| 410 |
+
</p>
|
| 411 |
+
</div>
|
| 412 |
+
</div>
|
| 413 |
</div>
|
| 414 |
+
<div class="mt-4 relative -mx-4 bg-neutral-800">
|
| 415 |
+
<div class="w-full bg-neutral-400 rounded-none h-8">
|
| 416 |
+
<div class="bg-red-400 h-full rounded-none" style="width: 50%;">
|
| 417 |
+
<p class="p-2 px-4 text-xs self-center align-middle">Conf:
|
| 418 |
+
<span class="ml-1 font-medium font-mono">50%</span>
|
| 419 |
+
</p>
|
| 420 |
+
</div>
|
| 421 |
+
</div>
|
| 422 |
</div>
|
| 423 |
</div>
|
| 424 |
+
<div class="flex flex-col items-start">
|
| 425 |
+
<h4 class="mt-4 text-sm font-semibold tracking-wide">GOAT Model</h4>
|
| 426 |
+
<hr class="py-px my-2 w-full bg-neutral-700" />
|
| 427 |
+
<div class="text-xs font-mono">Real: 50%, AI: 50%</div>
|
| 428 |
+
<hr class="py-px mt-6 w-full bg-neutral-700" />
|
| 429 |
+
<a class="mt-2 text-[0.66rem] tracking-wide">@GOAT / more info</a>
|
| 430 |
+
</div>
|
| 431 |
</div>
|
| 432 |
</div>
|
| 433 |
</div>
|
|
|
|
| 445 |
gr.Markdown("# AI Generated Image Classification")
|
| 446 |
|
| 447 |
with gr.Row():
|
| 448 |
+
with gr.Column(scale=1):
|
| 449 |
image_input = gr.Image(label="Upload Image to Analyze", sources=['upload'], type='pil')
|
| 450 |
confidence_slider = gr.Slider(0.0, 1.0, value=0.5, step=0.01, label="Confidence Threshold")
|
| 451 |
inputs = [image_input, confidence_slider]
|
| 452 |
+
with gr.Column(scale=2):
|
| 453 |
image_output = gr.Image(label="Processed Image")
|
| 454 |
# Custom HTML component to display results in 5 columns
|
| 455 |
results_html = gr.HTML(label="Model Predictions")
|