mirror of
https://github.com/artegoser/image-pluser-webui.git
synced 2024-11-25 04:56:22 +03:00
commit
1b259c886f
13 changed files with 273 additions and 88 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -150,3 +150,5 @@ cython_debug/
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
output
|
112
app.py
112
app.py
|
@ -1,98 +1,34 @@
|
||||||
import datetime
|
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
from PIL import Image, ImageChops
|
from processing.stacking import stacking
|
||||||
|
import sys
|
||||||
|
import importlib
|
||||||
|
import pathlib
|
||||||
import os
|
import os
|
||||||
from tqdm import tqdm
|
import copy
|
||||||
|
from tabs import tabs
|
||||||
|
|
||||||
|
tabs_dir = pathlib.Path(__file__).parent / "tabs"
|
||||||
|
|
||||||
|
|
||||||
def impluser(dir, method):
|
all_tabs = []
|
||||||
|
tab = None
|
||||||
files = os.listdir(dir)
|
for tab_name in tabs:
|
||||||
files = list(map(lambda x: os.path.join(dir, x), files))
|
old_path = copy.deepcopy(sys.path)
|
||||||
files = list(filter(lambda x: x.endswith(".png"), files))
|
sys.path = [os.path.join(tabs_dir, tab_name)] + sys.path
|
||||||
|
try:
|
||||||
if method == "denoise":
|
if tab is None:
|
||||||
img = denoise(files)
|
tab = importlib.import_module(f"app")
|
||||||
elif method == "startracks":
|
else:
|
||||||
img = startracks(files)
|
tab = importlib.reload(tab)
|
||||||
elif method == "noise extractor":
|
all_tabs.append((tab_name, tab.app))
|
||||||
img = noise_extractor(files)
|
|
||||||
elif method == "untrack":
|
|
||||||
img = untrack(files)
|
|
||||||
|
|
||||||
name = generate_name()
|
|
||||||
img.save(name)
|
|
||||||
|
|
||||||
return [name]
|
|
||||||
|
|
||||||
|
|
||||||
def generate_name():
|
|
||||||
# if not exists output create it
|
|
||||||
if not os.path.exists("./output"):
|
|
||||||
os.mkdir("./output")
|
|
||||||
|
|
||||||
return f"./output/{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.png"
|
|
||||||
|
|
||||||
|
|
||||||
def denoise(files):
|
|
||||||
bias = 1
|
|
||||||
image = Image.open(files[0])
|
|
||||||
for file in tqdm(files):
|
|
||||||
|
|
||||||
alpha = 1/bias
|
|
||||||
|
|
||||||
im2 = Image.open(file)
|
|
||||||
im3 = Image.blend(image, im2, alpha)
|
|
||||||
|
|
||||||
image = im3
|
|
||||||
|
|
||||||
bias += 1
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def startracks(files):
|
|
||||||
image = Image.open(files[0])
|
|
||||||
for file in tqdm(files):
|
|
||||||
im2 = Image.open(file)
|
|
||||||
im3 = ImageChops.lighter(image, im2)
|
|
||||||
image = im3
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def noise_extractor(files):
|
|
||||||
image = Image.open(files[0])
|
|
||||||
for file in tqdm(files, unit=' images'):
|
|
||||||
im2 = Image.open(file)
|
|
||||||
im3 = ImageChops.difference(image, im2)
|
|
||||||
image = im3
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def untrack(files):
|
|
||||||
image = Image.open(files[0])
|
|
||||||
for file in tqdm(files, unit=' images'):
|
|
||||||
im2 = Image.open(file)
|
|
||||||
im3 = ImageChops.darker(image, im2)
|
|
||||||
image = im3
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading tab ({tab_name}): {e}")
|
||||||
|
|
||||||
with gr.Blocks() as app:
|
with gr.Blocks() as app:
|
||||||
with gr.Row():
|
for tab_name, tab in all_tabs:
|
||||||
with gr.Column():
|
with gr.Tab(tab_name):
|
||||||
directory = gr.Textbox(
|
tab.render()
|
||||||
placeholder="A directory on the same machine where the server is running.", lines=1, label="Directory")
|
|
||||||
methods = gr.Dropdown(
|
|
||||||
choices=["denoise", "startracks", "noise extractor", "untrack"], value="denoise", label="Method")
|
|
||||||
submit = gr.Button("Submit")
|
|
||||||
|
|
||||||
with gr.Column():
|
|
||||||
output = gr.Gallery()
|
|
||||||
|
|
||||||
submit.click(impluser, inputs=[directory, methods], outputs=[output])
|
|
||||||
|
|
||||||
app.launch()
|
app.launch()
|
||||||
|
|
14
methods/bulk_methods.py
Normal file
14
methods/bulk_methods.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from PIL import Image, ImageFilter
|
||||||
|
|
||||||
|
|
||||||
|
def canny_edge(file_name):
|
||||||
|
image = Image.open(file_name)
|
||||||
|
|
||||||
|
image = image.convert("L")
|
||||||
|
|
||||||
|
return image.filter(ImageFilter.FIND_EDGES)
|
||||||
|
|
||||||
|
|
||||||
|
def sharpen(file_name):
|
||||||
|
image = Image.open(file_name)
|
||||||
|
return image.filter(ImageFilter.SHARPEN)
|
49
methods/stack_methods.py
Normal file
49
methods/stack_methods.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
from PIL import Image, ImageChops
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
|
def denoise(files):
|
||||||
|
bias = 1
|
||||||
|
image = Image.open(files[0])
|
||||||
|
for file in tqdm(files):
|
||||||
|
|
||||||
|
alpha = 1/bias
|
||||||
|
|
||||||
|
im2 = Image.open(file)
|
||||||
|
im3 = Image.blend(image, im2, alpha)
|
||||||
|
|
||||||
|
image = im3
|
||||||
|
|
||||||
|
bias += 1
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def startracks(files):
|
||||||
|
image = Image.open(files[0])
|
||||||
|
for file in tqdm(files):
|
||||||
|
im2 = Image.open(file)
|
||||||
|
im3 = ImageChops.lighter(image, im2)
|
||||||
|
image = im3
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def noise_extractor(files):
|
||||||
|
image = Image.open(files[0])
|
||||||
|
for file in tqdm(files, unit=' images'):
|
||||||
|
im2 = Image.open(file)
|
||||||
|
im3 = ImageChops.difference(image, im2)
|
||||||
|
image = im3
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def untrack(files):
|
||||||
|
image = Image.open(files[0])
|
||||||
|
for file in tqdm(files, unit=' images'):
|
||||||
|
im2 = Image.open(file)
|
||||||
|
im3 = ImageChops.darker(image, im2)
|
||||||
|
image = im3
|
||||||
|
|
||||||
|
return image
|
45
processing/bulk.py
Normal file
45
processing/bulk.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
import ffmpeg
|
||||||
|
import os
|
||||||
|
from processing.utils import generate_name, get_date_text, generate_name_with_file_name
|
||||||
|
from methods.bulk_methods import canny_edge, sharpen
|
||||||
|
|
||||||
|
|
||||||
|
def images_to_video(directory, fps, img_ext, img_name_format, video_name, video_ext, video_dir):
|
||||||
|
images_pattern = os.path.join(directory, f"{img_name_format}.{img_ext}")
|
||||||
|
|
||||||
|
if video_dir:
|
||||||
|
video_path = os.path.join(video_dir, f"{video_name}.{video_ext}")
|
||||||
|
else:
|
||||||
|
video_path = generate_name(
|
||||||
|
extension=video_ext, name=video_name, subfolder="videos")
|
||||||
|
|
||||||
|
ffmpeg.input(images_pattern,
|
||||||
|
framerate=fps).output(video_path, pix_fmt='yuv420p').global_args("-y").run()
|
||||||
|
|
||||||
|
|
||||||
|
def video_to_images(video_path, img_ext):
|
||||||
|
|
||||||
|
images_pattern = generate_name(
|
||||||
|
extension=img_ext, name=f"%d", subfolder=os.path.join("images", get_date_text()))
|
||||||
|
|
||||||
|
ffmpeg.input(video_path).output(images_pattern).run()
|
||||||
|
|
||||||
|
|
||||||
|
def bulk_processing(directory, out_directory, method):
|
||||||
|
date = get_date_text()
|
||||||
|
if method == "canny edge":
|
||||||
|
run_bulk(canny_edge, directory, out_directory, date)
|
||||||
|
elif method == "sharpen":
|
||||||
|
run_bulk(sharpen, directory, out_directory, date)
|
||||||
|
|
||||||
|
|
||||||
|
def run_bulk(func, directory, out_directory, date):
|
||||||
|
for file in os.listdir(directory):
|
||||||
|
img = func(os.path.join(directory, file))
|
||||||
|
if out_directory:
|
||||||
|
img_out_path = os.path.join(out_directory, file)
|
||||||
|
else:
|
||||||
|
img_out_path = generate_name_with_file_name(
|
||||||
|
name=file, subfolder=os.path.join("images", date))
|
||||||
|
img.save(img_out_path)
|
24
processing/stacking.py
Normal file
24
processing/stacking.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
from methods.stack_methods import denoise, startracks, noise_extractor, untrack
|
||||||
|
import os
|
||||||
|
from processing.utils import generate_name
|
||||||
|
|
||||||
|
|
||||||
|
def stacking(dir, method):
|
||||||
|
|
||||||
|
files = os.listdir(dir)
|
||||||
|
files = list(map(lambda x: os.path.join(dir, x), files))
|
||||||
|
files = list(filter(lambda x: x.endswith(".png"), files))
|
||||||
|
|
||||||
|
if method == "denoise":
|
||||||
|
img = denoise(files)
|
||||||
|
elif method == "startracks":
|
||||||
|
img = startracks(files)
|
||||||
|
elif method == "noise extractor":
|
||||||
|
img = noise_extractor(files)
|
||||||
|
elif method == "untrack":
|
||||||
|
img = untrack(files)
|
||||||
|
|
||||||
|
name = generate_name()
|
||||||
|
img.save(name)
|
||||||
|
|
||||||
|
return [name]
|
23
processing/utils.py
Normal file
23
processing/utils.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def generate_name(name=False, subfolder="stacked", extension="png", format='%Y-%m-%d_%H-%M-%S'):
|
||||||
|
|
||||||
|
os.makedirs(os.path.join(".", "output", subfolder), exist_ok=True)
|
||||||
|
|
||||||
|
if name is False or name == "":
|
||||||
|
name = get_date_text(format)
|
||||||
|
|
||||||
|
return os.path.join(".", "output", subfolder, f"{name}.{extension}")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_name_with_file_name(name, subfolder):
|
||||||
|
|
||||||
|
os.makedirs(os.path.join(".", "output", subfolder), exist_ok=True)
|
||||||
|
|
||||||
|
return os.path.join(".", "output", subfolder, name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_date_text(format='%Y-%m-%d_%H-%M-%S'):
|
||||||
|
return datetime.datetime.now().strftime(format)
|
|
@ -1,3 +1,4 @@
|
||||||
|
ffmpeg_python==0.2.0
|
||||||
gradio==3.27.0
|
gradio==3.27.0
|
||||||
Pillow==9.5.0
|
Pillow==9.5.0
|
||||||
tqdm==4.65.0
|
tqdm==4.65.0
|
||||||
|
|
21
tabs/Bulk processing/app.py
Normal file
21
tabs/Bulk processing/app.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import gradio as gr
|
||||||
|
from processing.bulk import bulk_processing
|
||||||
|
|
||||||
|
with gr.Blocks() as app:
|
||||||
|
gr.Markdown(
|
||||||
|
"Mass processing of images one at a time and saving to video if needed. # **WIP, not working**")
|
||||||
|
with gr.Row():
|
||||||
|
with gr.Column():
|
||||||
|
directory = gr.Text(
|
||||||
|
placeholder="A directory with many images.", lines=1, label="Directory")
|
||||||
|
method = gr.Dropdown(
|
||||||
|
choices=["canny edge", "sharpen"], value="canny edge", label="Method")
|
||||||
|
|
||||||
|
with gr.Accordion("Advanced settings", open=False) as acc:
|
||||||
|
out_dir = gr.Text(
|
||||||
|
label="Output directory", placeholder="The directory where the processed photos will be saved. If not specified `./output/images`")
|
||||||
|
submit = gr.Button("Submit")
|
||||||
|
submit.click(
|
||||||
|
fn=bulk_processing,
|
||||||
|
inputs=[directory, out_dir, method],
|
||||||
|
)
|
30
tabs/Images to video/app.py
Normal file
30
tabs/Images to video/app.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import gradio as gr
|
||||||
|
from processing.bulk import images_to_video
|
||||||
|
|
||||||
|
with gr.Blocks() as app:
|
||||||
|
gr.Markdown("Convert images to video.")
|
||||||
|
directory = gr.Text(
|
||||||
|
placeholder="A directory with many images of the same size", label="Directory")
|
||||||
|
|
||||||
|
fps = gr.Number(label="FPS", value=30, min=0)
|
||||||
|
|
||||||
|
with gr.Accordion("Advanced settings", open=False) as acc:
|
||||||
|
video_name = gr.Text(
|
||||||
|
label="Video name", placeholder="Video name e.g. video. If not specified will be generated by time")
|
||||||
|
video_ext = gr.Dropdown(label="Video extension", choices=[
|
||||||
|
"mp4"], value="mp4")
|
||||||
|
video_dir = gr.Text(
|
||||||
|
label="Video directory", placeholder="The directory where the video will be saved. If not specified `./output/videos`")
|
||||||
|
|
||||||
|
img_ext = gr.Dropdown(label="Image extension", choices=[
|
||||||
|
"png", "jpg"], value="png")
|
||||||
|
img_name_format = gr.Text(
|
||||||
|
label="Image name format", placeholder="ffmpeg pattern e.g. %04d is (0000.png)", value="%d")
|
||||||
|
|
||||||
|
submit = gr.Button("Submit")
|
||||||
|
|
||||||
|
submit.click(
|
||||||
|
fn=images_to_video,
|
||||||
|
inputs=[directory, fps, img_ext, img_name_format,
|
||||||
|
video_name, video_ext, video_dir],
|
||||||
|
)
|
18
tabs/Stacking/app.py
Normal file
18
tabs/Stacking/app.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import gradio as gr
|
||||||
|
from processing.stacking import stacking
|
||||||
|
|
||||||
|
with gr.Blocks() as app:
|
||||||
|
gr.Markdown("Stacking images.")
|
||||||
|
with gr.Row():
|
||||||
|
with gr.Column():
|
||||||
|
directory = gr.Text(
|
||||||
|
placeholder="A directory with many images of the same size", lines=1, label="Directory")
|
||||||
|
methods = gr.Dropdown(
|
||||||
|
choices=["denoise", "startracks", "noise extractor", "untrack"], value="denoise", label="Method")
|
||||||
|
submit = gr.Button("Submit")
|
||||||
|
|
||||||
|
with gr.Column():
|
||||||
|
output = gr.Gallery()
|
||||||
|
|
||||||
|
submit.click(stacking, inputs=[
|
||||||
|
directory, methods], outputs=[output])
|
16
tabs/Video to images/app.py
Normal file
16
tabs/Video to images/app.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import gradio as gr
|
||||||
|
from processing.bulk import video_to_images
|
||||||
|
|
||||||
|
with gr.Blocks() as app:
|
||||||
|
gr.Markdown(
|
||||||
|
"Convert video to images.")
|
||||||
|
with gr.Row():
|
||||||
|
with gr.Column():
|
||||||
|
|
||||||
|
video = gr.Video(label="Video")
|
||||||
|
|
||||||
|
with gr.Column():
|
||||||
|
format = gr.Radio(
|
||||||
|
choices=["png", "jpg"], value="png", label="Format of image")
|
||||||
|
submit = gr.Button("Submit")
|
||||||
|
submit.click(fn=video_to_images, inputs=[video, format])
|
6
tabs/__init__.py
Normal file
6
tabs/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
tabs = [
|
||||||
|
"Stacking",
|
||||||
|
"Bulk processing",
|
||||||
|
"Images to video",
|
||||||
|
"Video to images"
|
||||||
|
]
|
Loading…
Add table
Reference in a new issue