Spaces:
Runtime error
Runtime error
Commit
·
3989022
1
Parent(s):
d69049c
hugging-face-app (#1)
Browse files- Add application files (61a5924e45a0b86be3001966a7c172f6307d7d91)
Co-authored-by: Nolan Boukachab <[email protected]>
- app.py +86 -0
- config.json +10 -0
- config.py +25 -0
- requirements.txt +2 -0
- resource/hugging_face_1.jpg +0 -0
- resource/hugging_face_2.jpg +0 -0
app.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
import gradio as gr
|
| 6 |
+
from PIL import Image, ImageDraw
|
| 7 |
+
|
| 8 |
+
from doc_ufcn import models
|
| 9 |
+
from doc_ufcn.main import DocUFCN
|
| 10 |
+
from config import parse_configurations
|
| 11 |
+
|
| 12 |
+
# Load the config
|
| 13 |
+
config = parse_configurations(Path("config.json"))
|
| 14 |
+
|
| 15 |
+
# Download the model
|
| 16 |
+
model_path, parameters = models.download_model(name=config["model_name"])
|
| 17 |
+
|
| 18 |
+
# Store classes_colors list
|
| 19 |
+
classes_colors = config["classes_colors"]
|
| 20 |
+
|
| 21 |
+
# Store classes
|
| 22 |
+
classes = parameters["classes"]
|
| 23 |
+
|
| 24 |
+
# Check that the number of colors is equal to the number of classes -1
|
| 25 |
+
assert len(classes) - 1 == len(
|
| 26 |
+
classes_colors
|
| 27 |
+
), f"The parameter classes_colors was filled with the wrong number of colors. {len(classes)-1} colors are expected instead of {len(classes_colors)}."
|
| 28 |
+
|
| 29 |
+
# Check that the paths of the examples are valid
|
| 30 |
+
for example in config["examples"]:
|
| 31 |
+
assert os.path.exists(example), f"The path of the image '{example}' does not exist."
|
| 32 |
+
|
| 33 |
+
# Load the model
|
| 34 |
+
model = DocUFCN(
|
| 35 |
+
no_of_classes=len(classes),
|
| 36 |
+
model_input_size=parameters["input_size"],
|
| 37 |
+
device="cpu",
|
| 38 |
+
)
|
| 39 |
+
model.load(model_path=model_path, mean=parameters["mean"], std=parameters["std"])
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def query_image(image):
|
| 43 |
+
"""
|
| 44 |
+
Draws the predicted polygons with the color provided by the model on an image
|
| 45 |
+
|
| 46 |
+
:param image: An image to predict
|
| 47 |
+
:return: Image, an image with the predictions
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
# Make a prediction with the model
|
| 51 |
+
detected_polygons, probabilities, mask, overlap = model.predict(
|
| 52 |
+
input_image=image, raw_output=True, mask_output=True, overlap_output=True
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
# Load image
|
| 56 |
+
image = Image.fromarray(image)
|
| 57 |
+
|
| 58 |
+
# Make a copy of the image to keep the source and also to be able to use Pillow's blend method
|
| 59 |
+
img2 = image.copy()
|
| 60 |
+
|
| 61 |
+
# Create the polygons on the copy of the image for each class with the corresponding color
|
| 62 |
+
# We do not draw polygons of the background channel (channel 0)
|
| 63 |
+
for channel in range(1, len(classes)):
|
| 64 |
+
for polygon in detected_polygons[channel]:
|
| 65 |
+
# Draw the polygons on the image copy.
|
| 66 |
+
# Loop through the class_colors list (channel 1 has color 0)
|
| 67 |
+
ImageDraw.Draw(img2).polygon(
|
| 68 |
+
polygon["polygon"], fill=classes_colors[channel - 1]
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
# Return the blend of the images
|
| 72 |
+
return Image.blend(image, img2, 0.5)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
# Create an interface with the config
|
| 76 |
+
process_image = gr.Interface(
|
| 77 |
+
fn=query_image,
|
| 78 |
+
inputs=[gr.Image()],
|
| 79 |
+
outputs=[gr.Image()],
|
| 80 |
+
title=config["title"],
|
| 81 |
+
description=config["description"],
|
| 82 |
+
examples=config["examples"],
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
# Launch the application with the public mode (True or False)
|
| 86 |
+
process_image.launch()
|
config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "doc-ufcn-generic-historical-line",
|
| 3 |
+
"classes_colors": ["green"],
|
| 4 |
+
"title":"doc-ufcn Line Detection Demo",
|
| 5 |
+
"description":"A demo showing a prediction from the [Teklia/doc-ufcn-generic-historical-line](https://huggingface.co/Teklia/doc-ufcn-generic-historical-line) model. The generic historical line detection model predicts text lines from document images.",
|
| 6 |
+
"examples":[
|
| 7 |
+
"resource/hugging_face_1.jpg",
|
| 8 |
+
"resource/hugging_face_2.jpg"
|
| 9 |
+
]
|
| 10 |
+
}
|
config.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from teklia_toolbox.config import ConfigParser
|
| 5 |
+
|
| 6 |
+
def parse_configurations(config_path: Path):
|
| 7 |
+
"""
|
| 8 |
+
Parse multiple JSON configuration files into a single source
|
| 9 |
+
of configuration for the HuggingFace app
|
| 10 |
+
|
| 11 |
+
:param config_path: pathlib.Path, Path to the .json config file
|
| 12 |
+
:return: dict, containing the configuration. Ensures config is complete and with correct typing
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
parser = ConfigParser()
|
| 16 |
+
|
| 17 |
+
parser.add_option(
|
| 18 |
+
"model_name", type=str, default="doc-ufcn-generic-historical-line"
|
| 19 |
+
)
|
| 20 |
+
parser.add_option("classes_colors", type=list, default=["green"])
|
| 21 |
+
parser.add_option("title", type=str)
|
| 22 |
+
parser.add_option("description", type=str)
|
| 23 |
+
parser.add_option("examples", type=list)
|
| 24 |
+
|
| 25 |
+
return parser.parse(config_path)
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
doc-ufcn==0.1.9-rc2
|
| 2 |
+
teklia_toolbox==0.1.3
|
resource/hugging_face_1.jpg
ADDED
|
resource/hugging_face_2.jpg
ADDED
|