Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
import cv2
|
4 |
+
import gradio as gr
|
5 |
+
import numpy as np
|
6 |
+
from PIL import Image
|
7 |
+
|
8 |
+
# Path to images folder
|
9 |
+
image_folder = "./olmocr_images"
|
10 |
+
output_folder = "./olmocr_annotations"
|
11 |
+
|
12 |
+
# Ensure output folder exists
|
13 |
+
os.makedirs(output_folder, exist_ok=True)
|
14 |
+
|
15 |
+
# Get all image files
|
16 |
+
image_files = sorted([f for f in os.listdir(image_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg'))])
|
17 |
+
image_index = 0 # Start at first image
|
18 |
+
|
19 |
+
# JSON template for annotation
|
20 |
+
default_json_template = {
|
21 |
+
"image_path": "",
|
22 |
+
"text": {
|
23 |
+
"TITLE": "",
|
24 |
+
"TEMPAT-TANGGAL": "",
|
25 |
+
"NOMOR REGISTRASI": "",
|
26 |
+
"No.": "",
|
27 |
+
"NAMA PEMILIK": "",
|
28 |
+
"ALAMAT": "",
|
29 |
+
"MERK": "",
|
30 |
+
"TYPE": "",
|
31 |
+
"JENIS": "",
|
32 |
+
"MODEL": "",
|
33 |
+
"TAHUN PEMBUATAN": "",
|
34 |
+
"ISI SILINDER/DAYA LISTRIK": "",
|
35 |
+
"NOMOR RANGKA": "",
|
36 |
+
"NOMOR MESIN": "",
|
37 |
+
"NIK/TDP/NIB/KITAS/KITAP": "",
|
38 |
+
"WARNA": "",
|
39 |
+
"BAHAN BAKAR": "",
|
40 |
+
"WARNA TNKB": "",
|
41 |
+
"TAHUN REGISTRASI": "",
|
42 |
+
"NOMOR BPKB": "",
|
43 |
+
"KODE LOKASI": "",
|
44 |
+
"NO URUT PENDAFTARAN": "",
|
45 |
+
"BERLAKU SAMPAI": ""
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
def load_image():
|
50 |
+
global image_index
|
51 |
+
if 0 <= image_index < len(image_files):
|
52 |
+
image_path = os.path.join(image_folder, image_files[image_index])
|
53 |
+
image = Image.open(image_path)
|
54 |
+
|
55 |
+
json_filename = f"license_{image_index+1:03d}.json"
|
56 |
+
json_path = os.path.join(output_folder, json_filename)
|
57 |
+
annotation_data = default_json_template.copy()
|
58 |
+
|
59 |
+
if os.path.exists(json_path):
|
60 |
+
with open(json_path, "r") as f:
|
61 |
+
annotation_data = json.load(f)
|
62 |
+
|
63 |
+
return image, annotation_data["text"], image_path
|
64 |
+
return None, {}, ""
|
65 |
+
|
66 |
+
def save_annotation(image_path, annotation_text):
|
67 |
+
global image_index
|
68 |
+
if 0 <= image_index < len(image_files):
|
69 |
+
json_filename = f"license_{image_index+1:03d}.json"
|
70 |
+
json_path = os.path.join(output_folder, json_filename)
|
71 |
+
|
72 |
+
annotation_data = {"image_path": image_path, "text": annotation_text}
|
73 |
+
|
74 |
+
with open(json_path, "w") as f:
|
75 |
+
json.dump(annotation_data, f, indent=4)
|
76 |
+
|
77 |
+
return f"✅ Saved: {json_filename}"
|
78 |
+
return "❌ Error saving annotation"
|
79 |
+
|
80 |
+
def next_image():
|
81 |
+
global image_index
|
82 |
+
if image_index < len(image_files) - 1:
|
83 |
+
image_index += 1
|
84 |
+
return load_image()
|
85 |
+
|
86 |
+
def prev_image():
|
87 |
+
global image_index
|
88 |
+
if image_index > 0:
|
89 |
+
image_index -= 1
|
90 |
+
return load_image()
|
91 |
+
|
92 |
+
# Gradio Interface
|
93 |
+
with gr.Blocks() as demo:
|
94 |
+
with gr.Row():
|
95 |
+
image_display = gr.Image()
|
96 |
+
|
97 |
+
with gr.Column():
|
98 |
+
text_inputs = {key: gr.Textbox(label=key) for key in default_json_template["text"]}
|
99 |
+
save_button = gr.Button("Save")
|
100 |
+
|
101 |
+
status = gr.Textbox(label="Status", interactive=False)
|
102 |
+
|
103 |
+
with gr.Row():
|
104 |
+
prev_button = gr.Button("Previous")
|
105 |
+
next_button = gr.Button("Next")
|
106 |
+
|
107 |
+
# Load first image on startup
|
108 |
+
image, annotation, img_path = load_image()
|
109 |
+
image_display.value = image
|
110 |
+
for key, textbox in text_inputs.items():
|
111 |
+
textbox.value = annotation.get(key, "")
|
112 |
+
|
113 |
+
# Button Actions
|
114 |
+
def save_action():
|
115 |
+
annotation_text = {key: text_inputs[key].value for key in text_inputs}
|
116 |
+
return save_annotation(img_path, annotation_text)
|
117 |
+
|
118 |
+
save_button.click(save_action, outputs=status)
|
119 |
+
next_button.click(lambda: next_image(), outputs=[image_display, *text_inputs.values()])
|
120 |
+
prev_button.click(lambda: prev_image(), outputs=[image_display, *text_inputs.values()])
|
121 |
+
|
122 |
+
demo.launch()
|