Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -15,6 +15,9 @@ import uvicorn
|
|
15 |
import requests
|
16 |
from urllib.parse import quote
|
17 |
from unicodedata import normalize
|
|
|
|
|
|
|
18 |
|
19 |
root = os.path.dirname(os.path.abspath(__file__))
|
20 |
textures_folder = os.path.join(root, 'textures')
|
@@ -191,7 +194,8 @@ footer:after {
|
|
191 |
}
|
192 |
|
193 |
#textured_result-download-link,
|
194 |
-
#restored_image-download-link
|
|
|
195 |
position: absolute;
|
196 |
z-index: 9999;
|
197 |
padding: 2px 4px;
|
@@ -203,17 +207,21 @@ footer:after {
|
|
203 |
transition: 300ms
|
204 |
}
|
205 |
|
206 |
-
#download-link:hover
|
|
|
|
|
207 |
color: #99f7a8
|
208 |
}
|
209 |
|
210 |
-
#restored_images.disabled
|
|
|
211 |
height: 0px !important;
|
212 |
opacity: 0;
|
213 |
transition: 300ms
|
214 |
}
|
215 |
|
216 |
-
#restored_images.enabled
|
|
|
217 |
transition: 300ms
|
218 |
}
|
219 |
""" + preview_css
|
@@ -238,24 +246,28 @@ const PageLoadObserver = new MutationObserver((mutationsList, observer) => {
|
|
238 |
document.querySelector("label[data-testid='05-radio-label']").click()
|
239 |
}, 150);
|
240 |
})
|
241 |
-
|
242 |
-
|
243 |
-
const firstDiv = RestoredGallery.querySelector('div:first-child');
|
244 |
const hasChildElements = firstDiv && firstDiv.children.length > 0;
|
245 |
-
const hasImages =
|
246 |
if (hasChildElements || hasImages) {
|
247 |
-
|
248 |
-
|
249 |
} else {
|
250 |
-
|
251 |
-
|
252 |
}
|
253 |
}
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
|
|
|
|
|
|
|
|
|
|
259 |
function magnify(imgID, zoom) {
|
260 |
var img, glass, w, h, bw;
|
261 |
img = document.querySelector(imgID);
|
@@ -343,6 +355,12 @@ const PageLoadObserver = new MutationObserver((mutationsList, observer) => {
|
|
343 |
});
|
344 |
|
345 |
ImageRestoredObserver.observe(document, DownloadLinkObserverOptions);
|
|
|
|
|
|
|
|
|
|
|
|
|
346 |
|
347 |
}
|
348 |
}
|
@@ -352,6 +370,7 @@ const PageLoadObserver = new MutationObserver((mutationsList, observer) => {
|
|
352 |
PageLoadObserver.observe(document, { childList: true, subtree: true });
|
353 |
"""
|
354 |
|
|
|
355 |
def extract_path_from_result(predict_answer):
|
356 |
if isinstance(predict_answer, (tuple, list)):
|
357 |
result = predict_answer[0]
|
@@ -449,7 +468,7 @@ async def restore_upscale(files, restore_method):
|
|
449 |
print(f"restore_upscale: get_file_paths: {file_paths}")
|
450 |
return file_paths
|
451 |
else:
|
452 |
-
return [
|
453 |
|
454 |
|
455 |
def image_noise_softlight_layer_mix(img, texture, output: str = None, opacity: float = 0.7):
|
@@ -493,12 +512,168 @@ def apply_texture(input_image, textures_choice, opacity_slider):
|
|
493 |
return [result]
|
494 |
|
495 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
with gr.Blocks(analytics_enabled=False, css=radio_css) as demo:
|
|
|
|
|
|
|
|
|
497 |
with gr.Tab(label="восстановление лиц", id=1, elem_id="restore_tab"):
|
498 |
restore_method = gr.Radio(["codeformer", "gfpgan", "оба"], value="codeformer", label="", interactive=True)
|
499 |
restore_method.change(fn=lambda x: print(f"restore_method value = {x}"), inputs=restore_method, api_name="show_selected_method")
|
500 |
file_output = gr.Gallery(label="", container=True, object_fit="cover", columns=4, rows=4, allow_preview=True, preview=True, show_share_button=False, show_download_button=False, elem_id="restored_images")
|
501 |
-
upload_button = gr.UploadButton("выбор изображений для обработки", file_types=["image"], file_count="multiple", variant="primary")
|
502 |
upload_button.upload(fn=restore_upscale, inputs=[upload_button, restore_method], outputs=file_output, api_name="face_restore")
|
503 |
with gr.Tab(label="наложение зернистости пленки и шума", id=2, elem_id="textures_tab"):
|
504 |
with gr.Row(variant="compact", elem_id="textures_tab_images"):
|
@@ -511,6 +686,7 @@ with gr.Blocks(analytics_enabled=False, css=radio_css) as demo:
|
|
511 |
apply_button.click(fn=apply_texture, inputs=[input_image, textures_choice, opacity_slider], outputs=result_image, api_name="texturize")
|
512 |
|
513 |
|
|
|
514 |
app = FastAPI()
|
515 |
|
516 |
|
|
|
15 |
import requests
|
16 |
from urllib.parse import quote
|
17 |
from unicodedata import normalize
|
18 |
+
import json
|
19 |
+
import time
|
20 |
+
from html.parser import HTMLParser
|
21 |
|
22 |
root = os.path.dirname(os.path.abspath(__file__))
|
23 |
textures_folder = os.path.join(root, 'textures')
|
|
|
194 |
}
|
195 |
|
196 |
#textured_result-download-link,
|
197 |
+
#restored_image-download-link,
|
198 |
+
#upscaled_image-download-link {
|
199 |
position: absolute;
|
200 |
z-index: 9999;
|
201 |
padding: 2px 4px;
|
|
|
207 |
transition: 300ms
|
208 |
}
|
209 |
|
210 |
+
#textured_result-download-link:hover,
|
211 |
+
#restored_image-download-link:hover,
|
212 |
+
#upscaled_image-download-link:hover {
|
213 |
color: #99f7a8
|
214 |
}
|
215 |
|
216 |
+
#restored_images.disabled,
|
217 |
+
#upscaled_images.disabled {
|
218 |
height: 0px !important;
|
219 |
opacity: 0;
|
220 |
transition: 300ms
|
221 |
}
|
222 |
|
223 |
+
#restored_images.enabled,
|
224 |
+
#upscaled_images.enabled {
|
225 |
transition: 300ms
|
226 |
}
|
227 |
""" + preview_css
|
|
|
246 |
document.querySelector("label[data-testid='05-radio-label']").click()
|
247 |
}, 150);
|
248 |
})
|
249 |
+
function checkImagesAndSetClass(galleryElement) {
|
250 |
+
const firstDiv = galleryElement.querySelector('div:first-child');
|
|
|
251 |
const hasChildElements = firstDiv && firstDiv.children.length > 0;
|
252 |
+
const hasImages = galleryElement.querySelectorAll('img').length > 0;
|
253 |
if (hasChildElements || hasImages) {
|
254 |
+
galleryElement.classList.add('enabled');
|
255 |
+
galleryElement.classList.remove('disabled');
|
256 |
} else {
|
257 |
+
galleryElement.classList.add('disabled');
|
258 |
+
galleryElement.classList.remove('enabled');
|
259 |
}
|
260 |
}
|
261 |
+
function setupGalleryObserver(galleryId) {
|
262 |
+
let gallery = document.getElementById(galleryId);
|
263 |
+
const observer = new MutationObserver(() => {
|
264 |
+
checkImagesAndSetClass(gallery);
|
265 |
+
});
|
266 |
+
observer.observe(gallery, { childList: true, subtree: true });
|
267 |
+
checkImagesAndSetClass(gallery);
|
268 |
+
}
|
269 |
+
setupGalleryObserver('restored_images');
|
270 |
+
setupGalleryObserver('upscaled_images');
|
271 |
function magnify(imgID, zoom) {
|
272 |
var img, glass, w, h, bw;
|
273 |
img = document.querySelector(imgID);
|
|
|
355 |
});
|
356 |
|
357 |
ImageRestoredObserver.observe(document, DownloadLinkObserverOptions);
|
358 |
+
|
359 |
+
const ImageUpscaledObserver = new MutationObserver((mutationsList, observer) => {
|
360 |
+
DownloadLinkObserverCallback(mutationsList, observer, '#upscaled_images img[data-testid="detailed-image"]', '#upscaled_image-download-link', 'upscaled_image-download-link');
|
361 |
+
});
|
362 |
+
|
363 |
+
ImageUpscaledObserver.observe(document, DownloadLinkObserverOptions);
|
364 |
|
365 |
}
|
366 |
}
|
|
|
370 |
PageLoadObserver.observe(document, { childList: true, subtree: true });
|
371 |
"""
|
372 |
|
373 |
+
|
374 |
def extract_path_from_result(predict_answer):
|
375 |
if isinstance(predict_answer, (tuple, list)):
|
376 |
result = predict_answer[0]
|
|
|
468 |
print(f"restore_upscale: get_file_paths: {file_paths}")
|
469 |
return file_paths
|
470 |
else:
|
471 |
+
return ['https://iili.io/JzrxjDP.png']
|
472 |
|
473 |
|
474 |
def image_noise_softlight_layer_mix(img, texture, output: str = None, opacity: float = 0.7):
|
|
|
512 |
return [result]
|
513 |
|
514 |
|
515 |
+
def get_headers(url: str) -> dict:
|
516 |
+
session = requests.Session()
|
517 |
+
anon_auth = session.get(url)
|
518 |
+
cookies = session.cookies.get_dict()
|
519 |
+
return {
|
520 |
+
'content-type': 'application/json',
|
521 |
+
'cookie': f'csrftoken={cookies["csrftoken"]}; replicate_anonymous_id={cookies["replicate_anonymous_id"]};',
|
522 |
+
'origin': 'https://replicate.com',
|
523 |
+
'x-csrftoken': cookies['csrftoken'],
|
524 |
+
'authority': 'replicate.com',
|
525 |
+
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
526 |
+
'accept-language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
|
527 |
+
'cache-control': 'no-cache',
|
528 |
+
'dnt': '1',
|
529 |
+
'pragma': 'no-cache',
|
530 |
+
'referer': f'{url}?input=http',
|
531 |
+
'sec-ch-ua': '"Chromium";v="117", "Not;A=Brand";v="8"',
|
532 |
+
'sec-ch-ua-mobile': '?0',
|
533 |
+
'sec-ch-ua-platform': '"Windows"',
|
534 |
+
'sec-fetch-dest': 'document',
|
535 |
+
'sec-fetch-mode': 'navigate',
|
536 |
+
'sec-fetch-site': 'same-origin',
|
537 |
+
'sec-fetch-user': '?1',
|
538 |
+
'upgrade-insecure-requests': '1',
|
539 |
+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36'
|
540 |
+
}
|
541 |
+
|
542 |
+
|
543 |
+
def get_version(url):
|
544 |
+
url = url.rstrip('/') + '/versions'
|
545 |
+
response = requests.get(url)
|
546 |
+
|
547 |
+
class Version(HTMLParser):
|
548 |
+
def __init__(self):
|
549 |
+
super().__init__()
|
550 |
+
self.recording = 0
|
551 |
+
self.data = ''
|
552 |
+
|
553 |
+
def handle_starttag(self, tag, attrs):
|
554 |
+
if tag == 'a':
|
555 |
+
for name, value in attrs:
|
556 |
+
if name == 'href' and '/versions/' in value:
|
557 |
+
self.recording = 1
|
558 |
+
|
559 |
+
def handle_endtag(self, tag):
|
560 |
+
if tag == 'a' and self.recording:
|
561 |
+
self.recording -= 1
|
562 |
+
|
563 |
+
def handle_data(self, data):
|
564 |
+
if self.recording:
|
565 |
+
self.data = data
|
566 |
+
|
567 |
+
parser = Version()
|
568 |
+
parser.feed(response.text)
|
569 |
+
return parser.data.strip()
|
570 |
+
|
571 |
+
|
572 |
+
def replicate_upscale(url: str, image_url: str, upscale: int = 2):
|
573 |
+
version = get_version(url)
|
574 |
+
headers = get_headers(url)
|
575 |
+
session = requests.Session()
|
576 |
+
anon_auth = session.get(url, headers=headers)
|
577 |
+
data = {
|
578 |
+
"version": version,
|
579 |
+
"input": {
|
580 |
+
"img": image_url,
|
581 |
+
"image": image_url,
|
582 |
+
"upscale": upscale,
|
583 |
+
"scale": upscale,
|
584 |
+
"version": "General - RealESRGANplus",
|
585 |
+
},
|
586 |
+
"face_enhance": False,
|
587 |
+
"is_training": False,
|
588 |
+
"stream": False
|
589 |
+
}
|
590 |
+
response = session.post('https://replicate.com/api/predictions', headers=headers, data=json.dumps(data))
|
591 |
+
prediction_id = response.json()['id']
|
592 |
+
while True:
|
593 |
+
response = session.get(f'https://replicate.com/api/predictions/{prediction_id}', headers=headers)
|
594 |
+
status = response.json()['status']
|
595 |
+
if status == 'succeeded':
|
596 |
+
break
|
597 |
+
time.sleep(1)
|
598 |
+
session.close()
|
599 |
+
return response.json()['output']
|
600 |
+
|
601 |
+
|
602 |
+
urls = [
|
603 |
+
'https://replicate.com/cjwbw/real-esrgan',
|
604 |
+
'https://replicate.com/daanelson/real-esrgan-a100',
|
605 |
+
'https://replicate.com/xinntao/realesrgan',
|
606 |
+
]
|
607 |
+
|
608 |
+
|
609 |
+
def upscaler(image):
|
610 |
+
img_url = upload_image(image)
|
611 |
+
|
612 |
+
def run(url):
|
613 |
+
try:
|
614 |
+
return replicate_upscale(url, img_url)
|
615 |
+
except Exception as e:
|
616 |
+
print(e)
|
617 |
+
return return 'https://iili.io/JzrxjDP.png'
|
618 |
+
with ThreadPoolExecutor() as executor:
|
619 |
+
futures = {executor.submit(run, url) for url in urls}
|
620 |
+
for future in as_completed(futures):
|
621 |
+
result = future.result()
|
622 |
+
if result is not None:
|
623 |
+
break
|
624 |
+
return [result]
|
625 |
+
|
626 |
+
|
627 |
+
def temp_upload_file(file_path: str) -> str | None:
|
628 |
+
servers = [
|
629 |
+
('https://transfer.sh/', 'fileToUpload'),
|
630 |
+
('https://x0.at/', 'file'),
|
631 |
+
('https://tmpfiles.org/api/v1/upload', 'file'),
|
632 |
+
('https://uguu.se/upload.php', 'files[]')
|
633 |
+
]
|
634 |
+
for i in range(3):
|
635 |
+
for server, file_key in servers:
|
636 |
+
try:
|
637 |
+
with open(file_path, 'rb') as f:
|
638 |
+
files = {file_key: f}
|
639 |
+
response = requests.post(server, files=files)
|
640 |
+
if response.status_code == 200:
|
641 |
+
if server == 'https://transfer.sh/':
|
642 |
+
return response.text.replace("https://transfer.sh/","https://transfer.sh/get/").replace("\n","")
|
643 |
+
elif server == 'https://tmpfiles.org/api/v1/upload':
|
644 |
+
response_json = response.json()
|
645 |
+
if response_json['status'] == 'success':
|
646 |
+
return response_json['data']['url'].replace("https://tmpfiles.org/", "https://tmpfiles.org/dl/")
|
647 |
+
elif server == 'https://uguu.se/upload.php':
|
648 |
+
response_json = response.json()
|
649 |
+
if response_json['success']:
|
650 |
+
return response_json['files'][0]['url']
|
651 |
+
else:
|
652 |
+
return response.text
|
653 |
+
except Exception as e:
|
654 |
+
print(f'{server}: {e}')
|
655 |
+
return None
|
656 |
+
|
657 |
+
|
658 |
+
def upload_image(image_path: str) -> str | None:
|
659 |
+
files = {'source': open(image_path, "rb")}
|
660 |
+
data = {'key': '6d207e02198a847aa98d0a2a901485a5', 'action': 'upload', 'format': 'json'}
|
661 |
+
response = requests.post('https://freeimage.host/api/1/upload', files=files, data=data)
|
662 |
+
if response.json()["status_code"] == 200:
|
663 |
+
return response.json()["image"]["url"]
|
664 |
+
else:
|
665 |
+
return temp_upload_file(image_path)
|
666 |
+
|
667 |
with gr.Blocks(analytics_enabled=False, css=radio_css) as demo:
|
668 |
+
with gr.Tab(label="апскейл", elem_id="upscale_tab"):
|
669 |
+
file_output = gr.Gallery(label="", container=True, object_fit="cover", columns=4, rows=4, allow_preview=True, preview=True, show_share_button=False, show_download_button=False, elem_id="upscaled_images")
|
670 |
+
upload_button = gr.UploadButton("выбор одного изображения для обработки", file_types=["image"], file_count="single", variant="primary")
|
671 |
+
upload_button.upload(fn=upscaler, inputs=[upload_button], outputs=file_output, api_name="upscale")
|
672 |
with gr.Tab(label="восстановление лиц", id=1, elem_id="restore_tab"):
|
673 |
restore_method = gr.Radio(["codeformer", "gfpgan", "оба"], value="codeformer", label="", interactive=True)
|
674 |
restore_method.change(fn=lambda x: print(f"restore_method value = {x}"), inputs=restore_method, api_name="show_selected_method")
|
675 |
file_output = gr.Gallery(label="", container=True, object_fit="cover", columns=4, rows=4, allow_preview=True, preview=True, show_share_button=False, show_download_button=False, elem_id="restored_images")
|
676 |
+
upload_button = gr.UploadButton("выбор нескольких изображений для обработки", file_types=["image"], file_count="multiple", variant="primary")
|
677 |
upload_button.upload(fn=restore_upscale, inputs=[upload_button, restore_method], outputs=file_output, api_name="face_restore")
|
678 |
with gr.Tab(label="наложение зернистости пленки и шума", id=2, elem_id="textures_tab"):
|
679 |
with gr.Row(variant="compact", elem_id="textures_tab_images"):
|
|
|
686 |
apply_button.click(fn=apply_texture, inputs=[input_image, textures_choice, opacity_slider], outputs=result_image, api_name="texturize")
|
687 |
|
688 |
|
689 |
+
|
690 |
app = FastAPI()
|
691 |
|
692 |
|