From bd19b46d7544ff94be0e8eaccb4e1bd18d44b996 Mon Sep 17 00:00:00 2001 From: xAlpharax <42233094+xAlpharax@users.noreply.github.com> Date: Mon, 27 Feb 2023 22:44:09 +0200 Subject: Multi-threaded renderer implemented successfully. Better error handling. Minor changes in multiple areas --- Images/Azzalee.jpg | Bin 233885 -> 231884 bytes Images/Jitter_Doll.jpg | Bin 288950 -> 323415 bytes Images/Monet.jpg | Bin 8412856 -> 9424899 bytes Images/Starry_Night.jpg | Bin 2684897 -> 2114264 bytes Images/bunnies.jpg | Bin 110654 -> 104028 bytes Images/colorful.jpg | Bin 296376 -> 277561 bytes Images/cute.jpg | Bin 48794 -> 37477 bytes Images/demon.jpg | Bin 145801 -> 151759 bytes Images/kanade.png | Bin 251615 -> 255323 bytes Images/kek.png | Bin 25833 -> 25727 bytes README.md | 14 ++++++++--- clear_dir.sh | 4 +-- preview/Starry_Night_in_Jitter_Doll.mp4 | Bin 298125 -> 0 bytes preview/bunnies_in_Azzalee.mp4 | Bin 324140 -> 1861866 bytes preview/bunnies_in_Jitter_Doll.mp4 | Bin 0 -> 1479507 bytes preview/colorful_in_Azzalee.mp4 | Bin 309791 -> 0 bytes preview/cute_in_Azzalee.mp4 | Bin 0 -> 1871323 bytes preview/cute_in_Jitter_Doll.mp4 | Bin 1484421 -> 1518058 bytes renderer.py | 43 ++++++++++++++++++++++++-------- requirements.txt | 0 stylize.sh | 26 +++++++++++++------ 21 files changed, 64 insertions(+), 23 deletions(-) mode change 100755 => 100644 Images/Jitter_Doll.jpg mode change 100755 => 100644 Images/cute.jpg mode change 100755 => 100644 Images/demon.jpg mode change 100755 => 100644 Images/kanade.png mode change 100755 => 100644 Images/kek.png delete mode 100644 preview/Starry_Night_in_Jitter_Doll.mp4 create mode 100644 preview/bunnies_in_Jitter_Doll.mp4 delete mode 100644 preview/colorful_in_Azzalee.mp4 create mode 100644 preview/cute_in_Azzalee.mp4 create mode 100644 requirements.txt diff --git a/Images/Azzalee.jpg b/Images/Azzalee.jpg index 355c3c2..d7a1283 100644 Binary files a/Images/Azzalee.jpg and b/Images/Azzalee.jpg differ diff --git a/Images/Jitter_Doll.jpg b/Images/Jitter_Doll.jpg old mode 100755 new mode 100644 index 644f8b7..4f772c3 Binary files a/Images/Jitter_Doll.jpg and b/Images/Jitter_Doll.jpg differ diff --git a/Images/Monet.jpg b/Images/Monet.jpg index d9a560a..5bd061e 100644 Binary files a/Images/Monet.jpg and b/Images/Monet.jpg differ diff --git a/Images/Starry_Night.jpg b/Images/Starry_Night.jpg index 873b050..3f76d19 100644 Binary files a/Images/Starry_Night.jpg and b/Images/Starry_Night.jpg differ diff --git a/Images/bunnies.jpg b/Images/bunnies.jpg index 0ba2238..aa39762 100644 Binary files a/Images/bunnies.jpg and b/Images/bunnies.jpg differ diff --git a/Images/colorful.jpg b/Images/colorful.jpg index a4b5cf6..9c4a499 100644 Binary files a/Images/colorful.jpg and b/Images/colorful.jpg differ diff --git a/Images/cute.jpg b/Images/cute.jpg old mode 100755 new mode 100644 index d039de4..a262f6d Binary files a/Images/cute.jpg and b/Images/cute.jpg differ diff --git a/Images/demon.jpg b/Images/demon.jpg old mode 100755 new mode 100644 index 84aba91..b52ece4 Binary files a/Images/demon.jpg and b/Images/demon.jpg differ diff --git a/Images/kanade.png b/Images/kanade.png old mode 100755 new mode 100644 index 9ce09aa..9b069e4 Binary files a/Images/kanade.png and b/Images/kanade.png differ diff --git a/Images/kek.png b/Images/kek.png old mode 100755 new mode 100644 index 6234f73..7eb5d9c Binary files a/Images/kek.png and b/Images/kek.png differ diff --git a/README.md b/README.md index 3a2e442..7d85cf0 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,23 @@ # neural-art Neural Style Transfer done from the CLI using a VGG backbone and presented as an MP4. -Weights can be downloaded from [here](https://m1.afileditch.ch/ajjMsHrRhnikrrCiUXgY.pth). The downloaded file should be placed in `./weights/` and will be ignored when pushing as per `./.gitignore` +Weights can be downloaded from [here](https://m1.afileditch.ch/ajjMsHrRhnikrrCiUXgY.pth). The downloaded file should be placed in `./weights/` and will be ignored when pushing as seen in `./.gitignore` ### Why use this in 2023 ? -Because style transfer hasn't changed drastically in terms of actual results in the past years. I personally find a certain beauty in inputing an image with a desired style rather than a well curated prompt with a dozen of switches. Consider using this repo as a quick *just works* solution that can run on both CPU and GPU. +Because style transfer hasn't changed drastically in terms of actual results in the past years. I personally find a certain beauty in inputing a style and content image rather than a well curated prompt with a dozen of switches. Consider this repo as a quick *just works* solution that can run on both CPU and GPU effectively. ## Usage -The script sits comfortably in `./stylize.sh` so just run it from the project directory: +The script sits comfortably in `./stylize.sh` so just run it in the project directory: ```bash ./stylize.sh path/to/style_image path/to/content_image ``` + +### Requirements + +All requirements are specified in `./requirements.txt` as per python etiquette: + +```bash +pip install -r requirements.txt +``` diff --git a/clear_dir.sh b/clear_dir.sh index 57f891a..fef1764 100755 --- a/clear_dir.sh +++ b/clear_dir.sh @@ -1,7 +1,7 @@ -#!/bin/zsh +#!/bin/bash ### clearing up the directory ### from temporary files rm -rf __pycache__ # Output* future proof -rm -f Output/* *.npy +rm -f Output/*.png *.npy diff --git a/preview/Starry_Night_in_Jitter_Doll.mp4 b/preview/Starry_Night_in_Jitter_Doll.mp4 deleted file mode 100644 index bc75f35..0000000 Binary files a/preview/Starry_Night_in_Jitter_Doll.mp4 and /dev/null differ diff --git a/preview/bunnies_in_Azzalee.mp4 b/preview/bunnies_in_Azzalee.mp4 index 08974da..1cdf496 100644 Binary files a/preview/bunnies_in_Azzalee.mp4 and b/preview/bunnies_in_Azzalee.mp4 differ diff --git a/preview/bunnies_in_Jitter_Doll.mp4 b/preview/bunnies_in_Jitter_Doll.mp4 new file mode 100644 index 0000000..0ad194c Binary files /dev/null and b/preview/bunnies_in_Jitter_Doll.mp4 differ diff --git a/preview/colorful_in_Azzalee.mp4 b/preview/colorful_in_Azzalee.mp4 deleted file mode 100644 index 8b78d66..0000000 Binary files a/preview/colorful_in_Azzalee.mp4 and /dev/null differ diff --git a/preview/cute_in_Azzalee.mp4 b/preview/cute_in_Azzalee.mp4 new file mode 100644 index 0000000..18f2780 Binary files /dev/null and b/preview/cute_in_Azzalee.mp4 differ diff --git a/preview/cute_in_Jitter_Doll.mp4 b/preview/cute_in_Jitter_Doll.mp4 index 897b989..7eed718 100644 Binary files a/preview/cute_in_Jitter_Doll.mp4 and b/preview/cute_in_Jitter_Doll.mp4 differ diff --git a/renderer.py b/renderer.py index 7eaae9a..992b4ab 100644 --- a/renderer.py +++ b/renderer.py @@ -1,32 +1,55 @@ #!/bin/python -### very slow step that will be assigned to multiple -### jobs later in the development of this tool - ### data loading import numpy as np -image_array = np.load("images.npy", allow_pickle=True) +# will need some added functionality there for *.npy +image_array = np.load("images.npy") ### progress bar from tqdm import tqdm +import sys -pbar = tqdm(total = len(image_array)) +if len(sys.argv) == 1: + pbar = tqdm(total=len(image_array), miniters=0, smoothing=0) -### rendering of images +### image rendering from raw data import matplotlib.pyplot as plt +dpi = 258 # dpi 258 -> 720p ; dpi 387 -> 1080p output image resolution + def render(index): + pbar.update(1) + name = 'Output/neural_art_{:04d}.png'.format(index + 1) plt.axis('off') plt.imshow(image_array[index]) - plt.savefig(name, bbox_inches='tight', pad_inches=0) # dpi 258 -> 720p ; dpi 387 -> 1080p output image resolution + plt.savefig(name, dpi=dpi, bbox_inches='tight', pad_inches=0) plt.close('all') -for index in range(0, len(image_array)): - render(index) - pbar.update(1) +### multi-threading + +import os ; n_cores = os.cpu_count() // 2 ; + +if len(sys.argv) == 1: + from concurrent.futures import ThreadPoolExecutor + + with ThreadPoolExecutor(max_workers=n_cores) as executor: + executor.map(render, range(0, len(image_array))) + + exit() + +if sys.argv[1] == "--fix": + for index in range(0, 32): + ### some artifacts may have slipped + ### because of the thread pool + name = 'Output/neural_art_{:04d}.png'.format(index + 1) + + plt.axis('off') + plt.imshow(image_array[index]) + plt.savefig(name, dpi=dpi, bbox_inches='tight', pad_inches=0) + plt.close('all') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/stylize.sh b/stylize.sh index 434c079..ac9beba 100755 --- a/stylize.sh +++ b/stylize.sh @@ -1,25 +1,35 @@ -#!/bin/zsh +#!/bin/bash ### You must be in the 'neural-art' directory when you run this -if [ $# -eq 0 ] - then +cwd=$(pwd | sed -r 's%.*/%%g') +if [ $cwd != "neural-art" ] ; then + echo "You must be in the 'neural-art' directory when you run this" + exit 1 +fi + +if [ $# -eq 0 ] ; then echo "Style Image and Content Image need to be specified as arguments" echo "Example: ./stylize.sh Images/Jitter_Doll.jpg Images/cute.jpg" exit 1 fi -if [ $# -eq 1 ] - then - echo "Content image needs to be specified" +if [ $# -eq 1 ] ; then + echo "Content image needs to be specified as well" + echo "Example: ./stylize.sh Images/Jitter_Doll.jpg Images/cute.jpg" exit 1 fi +./clear_dir.sh + # stylize data [pair (style, content)] python neuralart.py $1 $2 # render images (actual frames) from (an) images.npy -python renderer.py $1 $2 +python renderer.py + +# render fix +python renderer.py --fix # turn everything into a video -ffmpeg -framerate 60 -pattern_type glob -i 'Output/neural_art_*.png' -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" ${${2/*\/}/.*}_in_${${1/*\/}/.*}.mp4 +ffmpeg -framerate 60 -pattern_type glob -i 'Output/neural_art_*.png' -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" $(basename ${2%.*})'_in_'$(basename ${1%.*})'.mp4' -- cgit v1.2.3