Merge pull request #1 from artegoser/new-features

New features
This commit is contained in:
Artemy Egorov 2023-04-16 10:47:01 +03:00 committed by GitHub
commit 1b259c886f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 273 additions and 88 deletions

2
.gitignore vendored
View file

@ -150,3 +150,5 @@ cython_debug/
# 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.
#.idea/
output

112
app.py
View file

@ -1,98 +1,34 @@
import datetime
import gradio as gr
from PIL import Image, ImageChops
from processing.stacking import stacking
import sys
import importlib
import pathlib
import os
from tqdm import tqdm
import copy
from tabs import tabs
tabs_dir = pathlib.Path(__file__).parent / "tabs"
def impluser(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]
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
all_tabs = []
tab = None
for tab_name in tabs:
old_path = copy.deepcopy(sys.path)
sys.path = [os.path.join(tabs_dir, tab_name)] + sys.path
try:
if tab is None:
tab = importlib.import_module(f"app")
else:
tab = importlib.reload(tab)
all_tabs.append((tab_name, tab.app))
except Exception as e:
print(f"Error loading tab ({tab_name}): {e}")
with gr.Blocks() as app:
with gr.Row():
with gr.Column():
directory = gr.Textbox(
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")
for tab_name, tab in all_tabs:
with gr.Tab(tab_name):
tab.render()
with gr.Column():
output = gr.Gallery()
submit.click(impluser, inputs=[directory, methods], outputs=[output])
app.launch()

14
methods/bulk_methods.py Normal file
View 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
View 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
View 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
View 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
View 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)

View file

@ -1,3 +1,4 @@
ffmpeg_python==0.2.0
gradio==3.27.0
Pillow==9.5.0
tqdm==4.65.0

View 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],
)

View 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
View 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])

View 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
View file

@ -0,0 +1,6 @@
tabs = [
"Stacking",
"Bulk processing",
"Images to video",
"Video to images"
]