WolseyTheCat commited on
Commit
3d82aef
·
1 Parent(s): de3df47

inital commit

Browse files
Files changed (2) hide show
  1. app.py +165 -4
  2. requerements.txt +4 -0
app.py CHANGED
@@ -1,7 +1,168 @@
1
  import gradio as gr
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import cv2
3
+ import numpy as np
4
+ import pytesseract
5
+ import base64, json, io
6
+ from PIL import Image
7
 
8
+ # HTML template that loads Fabric.js and creates an interactive canvas.
9
+ html_template = """
10
+ <!DOCTYPE html>
11
+ <html>
12
+ <head>
13
+ <meta charset="utf-8">
14
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.6.0/fabric.min.js"></script>
15
+ <style>
16
+ canvas { border: 1px solid #ccc; }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <canvas id="c" width="600" height="400"></canvas>
21
+ <script>
22
+ // Parse JSON data from Python.
23
+ var data = {data_json};
24
 
25
+ // Initialize Fabric.js canvas.
26
+ var canvas = new fabric.Canvas('c');
27
+
28
+ // Load the image as canvas background.
29
+ var imgObj = new Image();
30
+ imgObj.src = "data:image/png;base64," + data.image_data;
31
+ imgObj.onload = function() {
32
+ var bg = new fabric.Image(imgObj);
33
+ bg.selectable = false;
34
+ // Scale background to canvas dimensions.
35
+ bg.scaleToWidth(canvas.width);
36
+ bg.scaleToHeight(canvas.height);
37
+ canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
38
+ };
39
+
40
+ // Add detected objects to the canvas.
41
+ data.objects.forEach(function(obj) {
42
+ if(obj.type === "text") {
43
+ var textObj = new fabric.IText(obj.text, {
44
+ left: obj.x,
45
+ top: obj.y,
46
+ fontSize: 20,
47
+ fill: 'black'
48
+ });
49
+ canvas.add(textObj);
50
+ } else if(obj.type === "image") {
51
+ var rect = new fabric.Rect({
52
+ left: obj.x,
53
+ top: obj.y,
54
+ width: obj.width,
55
+ height: obj.height,
56
+ fill: 'rgba(0, 0, 255, 0.3)'
57
+ });
58
+ canvas.add(rect);
59
+ }
60
+ });
61
+ </script>
62
+ </body>
63
+ </html>
64
+ """
65
+
66
+ def generate_html(image):
67
+ # If the PNG has transparency, composite it onto a white background.
68
+ if image.shape[2] == 4:
69
+ alpha = image[:, :, 3] / 255.0
70
+ image_rgb = image[:, :, :3]
71
+ white_bg = np.ones_like(image_rgb, dtype=np.uint8) * 255
72
+ image = np.uint8(image_rgb * alpha[..., None] + white_bg * (1 - alpha[..., None]))
73
+
74
+ # Convert the image (numpy array) to a base64-encoded PNG.
75
+ pil_image = Image.fromarray(image)
76
+ buffer = io.BytesIO()
77
+ pil_image.save(buffer, format="PNG")
78
+ base64_image = base64.b64encode(buffer.getvalue()).decode('utf-8')
79
+
80
+ # ------------------- TEXT DETECTION -------------------
81
+ text_data = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)
82
+ detected_texts = []
83
+ n_boxes = len(text_data['level'])
84
+ for i in range(n_boxes):
85
+ try:
86
+ conf = int(text_data['conf'][i])
87
+ except:
88
+ conf = 0
89
+ text_content = text_data['text'][i].strip()
90
+ if conf > 60 and text_content:
91
+ x = int(text_data['left'][i])
92
+ y = int(text_data['top'][i])
93
+ w = int(text_data['width'][i])
94
+ h = int(text_data['height'][i])
95
+ detected_texts.append({
96
+ 'type': 'text',
97
+ 'text': text_content,
98
+ 'x': x,
99
+ 'y': y,
100
+ 'width': w,
101
+ 'height': h,
102
+ 'confidence': conf
103
+ })
104
+
105
+ # ---------------- NON-TEXT OBJECT DETECTION ----------------
106
+ # Convert image to grayscale and threshold to detect non-white regions.
107
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
108
+ _, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)
109
+ contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
110
+ detected_images = []
111
+
112
+ # Helper function to compute Intersection over Union (IoU) for overlap testing.
113
+ def iou(box1, box2):
114
+ x1, y1, w1, h1 = box1
115
+ x2, y2, w2, h2 = box2
116
+ inter_x = max(0, min(x1+w1, x2+w2) - max(x1, x2))
117
+ inter_y = max(0, min(y1+h1, y2+h2) - max(y1, y2))
118
+ inter_area = inter_x * inter_y
119
+ area1 = w1 * h1
120
+ area2 = w2 * h2
121
+ union = area1 + area2 - inter_area
122
+ return inter_area / union if union != 0 else 0
123
+
124
+ # Prepare text bounding boxes for filtering.
125
+ text_boxes = [(obj['x'], obj['y'], obj['width'], obj['height']) for obj in detected_texts]
126
+ image_id = 0
127
+ for cnt in contours:
128
+ x, y, w, h = cv2.boundingRect(cnt)
129
+ if w < 10 or h < 10:
130
+ continue
131
+ # Skip if the contour significantly overlaps with a detected text box.
132
+ overlap = any(iou((x, y, w, h), tb) > 0.5 for tb in text_boxes)
133
+ if not overlap:
134
+ detected_images.append({
135
+ 'type': 'image',
136
+ 'id': image_id,
137
+ 'x': x,
138
+ 'y': y,
139
+ 'width': w,
140
+ 'height': h
141
+ })
142
+ image_id += 1
143
+
144
+ # Combine text and non-text objects.
145
+ objects = detected_texts + detected_images
146
+ result = {
147
+ "image_data": base64_image,
148
+ "objects": objects
149
+ }
150
+
151
+ # Insert the JSON data into the HTML template.
152
+ json_data = json.dumps(result)
153
+ html_code = html_template.replace("{data_json}", json_data)
154
+ return html_code
155
+
156
+ # Create the Gradio interface.
157
+ with gr.Blocks() as demo:
158
+ gr.Markdown("## Interactive Image Editor")
159
+ with gr.Row():
160
+ with gr.Column():
161
+ input_image = gr.Image(label="Upload PNG Image", source="upload", type="numpy")
162
+ process_button = gr.Button("Process Image")
163
+ with gr.Column():
164
+ html_output = gr.HTML(label="Interactive Editor")
165
+
166
+ process_button.click(fn=generate_html, inputs=input_image, outputs=html_output)
167
+
168
+ demo.launch()
requerements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio
2
+ pytesseract
3
+ Pillow
4
+ opencv-python