|
import gradio as gr |
|
from gradio_imageslider import ImageSlider |
|
import os |
|
import pprint |
|
import sys |
|
from pathlib import Path |
|
from collections import OrderedDict |
|
from PIL import Image |
|
|
|
|
|
print('\n\n================================ START') |
|
|
|
SEP = os.path.sep |
|
BASE_URL = "https://huggingface.co/spaces/menorki/windmill-project-belle-ile/resolve/main/" |
|
BASE_PATH = Path(__file__).resolve().parent |
|
BASE_DIR = str(BASE_PATH) + SEP |
|
IN_SPACE = os.environ.get("SPACE_AUTHOR_NAME") in ["menorki"] |
|
|
|
TMP_PATH = BASE_PATH / 'gradio_tmp' |
|
TMP_DIR = str(TMP_PATH) + SEP |
|
|
|
|
|
TMP_PATH.mkdir(exist_ok=True, parents=True) |
|
os.environ['GRADIO_TEMP_DIR'] = TMP_DIR |
|
|
|
print(f"BASE_URL: {BASE_URL}") |
|
print(f"BASE_DIR: {BASE_DIR}") |
|
print(f"TMP_DIR: {TMP_DIR}") |
|
print(f"IN_SPACE: {IN_SPACE}") |
|
|
|
dir_models3D = "assets/windmill/models3D/" |
|
dir_images = "assets/windmill/images/" |
|
dir_videos = "assets/windmill/videos/" |
|
|
|
|
|
|
|
model3D_names = [f for f in os.listdir(dir_models3D) if f.endswith('.gltf') or f.endswith('.obj') or f.endswith('.glb')] |
|
if model3D_names: |
|
model3D_files = [BASE_URL + dir_models3D + name for name in model3D_names] |
|
|
|
images_names = sorted([f for f in os.listdir(dir_images) if f.endswith('.jpg') or f.endswith('.png')] , reverse=True) |
|
if images_names: |
|
images_files = [(BASE_URL + dir_images + name , name) for name in images_names] |
|
|
|
video_names = [f for f in os.listdir(dir_videos) if f.endswith('.mp4') or f.endswith('.avi')] |
|
if video_names: |
|
video_files = [BASE_URL + dir_videos + name for name in video_names] |
|
|
|
|
|
DESCRIPTION = """# PROJET MOULIN SIMON """ |
|
|
|
css = ''' |
|
.gradio-container {max-width: 1280px !important; height:90%;} |
|
#gallery { height: 90% !important; } /* Adjusted for padding/margin if any */ |
|
h1{text-align:center} |
|
''' |
|
|
|
head = ''' |
|
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.5.0/model-viewer.min.js"></script> |
|
<script defer src="https://cdn.jsdelivr.net/npm/img-comparison-slider@8/dist/index.js"></script> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/img-comparison-slider@8/dist/styles.css"/> |
|
<style> |
|
.custom-animated-handle { |
|
transition: transform 0.2s; |
|
} |
|
|
|
.slider-with-animated-handle:hover .custom-animated-handle { |
|
transform: scale(1.2); |
|
} |
|
|
|
h1, h2 { |
|
color: #0056b3; |
|
# padding-bottom:10px; |
|
padding-top:10px; |
|
} |
|
p { |
|
margin: 1em 0; |
|
} |
|
.highlight { |
|
color: #d9534f; |
|
font-weight: bold; |
|
} |
|
.emphasis { |
|
color: #5cb85c; |
|
font-style: italic; |
|
} |
|
</style> |
|
''' |
|
|
|
def read_text_file(path:str)->str : |
|
with open(path, 'r', encoding='utf-8') as file: |
|
content = file.read() |
|
return content |
|
|
|
def read_PIL_images(filenames): |
|
images = [] |
|
for filename in filenames: |
|
try: |
|
print(f'Loading {filename}......') |
|
img = Image.open(filename) |
|
images.append(img) |
|
print(f'Loaded {filename}') |
|
except Exception as e: |
|
print(f"Error opening image {filename}: {e}") |
|
return images |
|
|
|
def build_comparison_slider(before_url , after_url): |
|
|
|
html = f''' |
|
<img-comparison-slider class="slider-with-animated-handle" style="max-width:500px; --divider-width: 4px; --divider-color: #ff0000;"> |
|
<img slot="first" width="100%" src="{before_url}" /> |
|
<img slot="second" width="100%" src="{after_url}" /> |
|
<svg slot="handle" class="custom-animated-handle" xmlns="http://www.w3.org/2000/svg" width="100" viewBox="-8 -3 16 6"> |
|
<path stroke="#fff" d="M -5 -2 L -7 0 L -5 2 M -5 -2 L -5 2 M 5 -2 L 7 0 L 5 2 M 5 -2 L 5 2" stroke-width="1" fill="#fff" vector-effect="non-scaling-stroke"></path> |
|
</svg> |
|
</img-comparison-slider>''' |
|
|
|
return html |
|
|
|
with gr.Blocks(analytics_enabled=False , head=head , css=css, theme="bethecloud/storj_theme" , elem_id='gradio-container') as demo: |
|
gr.HTML(f'''<div style="width:100%; text-align:left"><img src="{BASE_URL}assets/images/banner-dugrainaupain.jpg" style="display: inline-block;"></div>''') |
|
|
|
|
|
with gr.Tab("PROJECT....."): |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
before = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-BEFORE.jpg' |
|
after = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-AFTER.jpg' |
|
gr.HTML(build_comparison_slider(before , after)) |
|
|
|
with gr.Column(scale=1): |
|
gr.HTML(read_text_file("assets/html/intro.txt")) |
|
|
|
|
|
with gr.Tab("Before/After"): |
|
with gr.Row(): |
|
before = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-schema-BEFORE.jpg' |
|
after = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-AFTER.jpg' |
|
gr.HTML(build_comparison_slider(before , after)) |
|
|
|
before = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-BEFORE.jpg' |
|
after = BASE_URL + 'assets/images/before-after/moulin-insitu-1-_1610534-AFTER.jpg' |
|
gr.HTML(build_comparison_slider(before , after)) |
|
|
|
print(f'{BASE_URL}assets/images/before-after/moulin-insitu-1-_1610534-schema-BEFORE.jpg') |
|
print(f'{BASE_URL}assets/images/before-after/moulin-insitu-1-_1610534-BEFORE.jpg') |
|
print(f'{BASE_URL}assets/images/before-after/moulin-insitu-1-_1610534-AFTER.jpg') |
|
|
|
if images_names: |
|
with gr.Tab("Ref. Images"): |
|
image_viewer = gr.Gallery(label="Generated images", |
|
show_label=False, |
|
elem_id='gallery', |
|
columns=[3], |
|
rows=[1], |
|
object_fit="cover", |
|
interactive=False, |
|
value=images_files) |
|
|
|
|
|
if model3D_names: |
|
with gr.Tab("3D Models"): |
|
|
|
viewer_html = '''<div id="google-3D-viewer-container" style="min-width:800px; width:100%; height:600px;" style="flex: 1; display: flex; justify-content: center; align-items: center;"> |
|
<model-viewer id="google-3D-viewer" style="width: 100%; height: 100%;" src="DEFAULT_MODEL_URL" auto-rotate camera-controls></model-viewer> |
|
</div> |
|
''' |
|
|
|
viewer_html = viewer_html.replace('DEFAULT_MODEL_URL' , BASE_URL + dir_models3D + model3D_names[0]) |
|
viewer_html = viewer_html.replace('BASE_URL_3D' , BASE_URL + dir_models3D) |
|
|
|
google_viewer = gr.HTML(viewer_html) |
|
|
|
with gr.Row(visible=True): |
|
|
|
model_selection = gr.Radio( |
|
show_label=True, |
|
container=True, |
|
interactive=True, |
|
choices=model3D_names, |
|
value=model3D_names[0], |
|
label="Selectionner un modèle 3D :", |
|
) |
|
|
|
|
|
model_selection.change(fn=None, |
|
inputs=model_selection, |
|
outputs=None , |
|
js=f"(name) => document.getElementById('google-3D-viewer').src = '{BASE_URL + dir_models3D}' + name") |
|
|
|
if video_names: |
|
with gr.Tab("Windmill Site Videos"): |
|
|
|
video_viewer = gr.Video(interactive=False, value=video_files[0]) |
|
|
|
with gr.Row(visible=True): |
|
|
|
video_selection = gr.Radio( |
|
show_label=True, |
|
container=True, |
|
interactive=True, |
|
choices=video_names, |
|
value=video_names[0], |
|
label="Select a video:" |
|
) |
|
|
|
def load_video(video_name): |
|
video_file = BASE_URL + dir_videos + video_name |
|
print(f'LOADING VIDEO: {video_file}') |
|
return video_file |
|
|
|
video_selection.change(fn=load_video, inputs=video_selection, outputs=video_viewer) |
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch(debug=not IN_SPACE, show_api=False) |