Browse Source

Transformation steps v2

* modify --altered path of the directory where steps images transformation are write
* unchangerd --steps add -s, --steps <starting step>:<ending step option>
* rescale options are now handle
master
PommeDroid 3 years ago
parent
commit
b19727a734
  1. 1
      .gitignore
  2. 10
      argv.py
  3. 46
      main.py
  4. 52
      processing/image.py
  5. 17
      utils.py

1
.gitignore vendored

@ -6,6 +6,7 @@ logs @@ -6,6 +6,7 @@ logs
*.png
*.jpg
*.gif
altered/
# Runtime data
pids

10
argv.py

@ -46,10 +46,8 @@ def config_args(parser, args): @@ -46,10 +46,8 @@ def config_args(parser, args):
if args.steps and not args.altered:
parser.error("--steps requires --altered.")
elif args.steps and args.altered:
if not os.path.isfile(args.altered):
parser.error("{} file doesn't exist".format(args.input))
elif not args.steps:
args.altered = args.input
if not os.path.isdir(args.altered):
parser.error("{} directory doesn't exist".format(args.input))
if args.func == main:
conf.args = vars(args)
@ -60,7 +58,6 @@ def config_args(parser, args): @@ -60,7 +58,6 @@ def config_args(parser, args):
config_args_altered()
def run():
"""
Run argparse for Dreampower
@ -235,7 +232,6 @@ def run(): @@ -235,7 +232,6 @@ def run():
return type_func
# TODO See conflicts and handle combination with scale options (they are ignored atm when use this option)
parser.add_argument(
"-s",
"--steps",
@ -254,7 +250,7 @@ def run(): @@ -254,7 +250,7 @@ def run():
parser.add_argument(
"-a",
"--altered",
help="path of the photo to transform (default: altered.<input extension>)"
help="path of the directory where steps images transformation are write"
)
# Register Command Handlers

46
main.py

@ -43,19 +43,41 @@ def select_phases(): @@ -43,19 +43,41 @@ def select_phases():
Select the transformation phases to use following args parameters
:return: <ImageTransform[]> list of image transformation
"""
def shift_step(shift_starting=0, shift_ending=0):
if not conf.args['steps']:
conf.args['steps'] = (0, 5)
conf.args['steps'] = (
conf.args['steps'][0] + shift_starting,
conf.args['steps'][1] + shift_ending
)
def add_tail(phases, phase):
phases = [phase] + phases
if conf.args['steps'] and conf.args['steps'][0] != 0:
shift_step(shift_starting=1)
return phases
def add_head(phases, phase):
phases = phases + [phase]
if conf.args['steps'] and conf.args['steps'][0] == len(phases):
shift_step(shift_ending=1)
return phases
phases = [DressToCorrect(), CorrectToMask(), MaskToMaskref(),
MaskrefToMaskdet(), MaskdetToMaskfin(), MaskfinToMaskdet()]
if conf.args['steps']:
phases = phases[conf.args['steps'][0]:conf.args['steps'][1]]
elif conf.args['overlay']:
phases = [ImageToCrop(), ImageToResized()] + phases + [ImageToOverlay()]
if conf.args['overlay']:
phases = add_tail(phases, ImageToResized())
phases = add_tail(phases, ImageToCrop())
phases = add_head(phases, ImageToOverlay())
elif conf.args['auto_resize']:
phases = [ImageToResized()] + phases
phases = add_tail(phases, ImageToResized())
elif conf.args['auto_resize_crop']:
phases = [ImageToResizedCrop()] + phases
phases = add_tail(phases, ImageToResizedCrop())
elif conf.args['auto_rescale']:
phases = [ImageToRescale()] + phases
conf.log.debug("Phases to execute : {}".format(phases))
phases = add_tail(phases, ImageToRescale())
return phases
@ -83,7 +105,7 @@ def simple_gif_processing(phases): @@ -83,7 +105,7 @@ def simple_gif_processing(phases):
:param phases: <ImageTransform[]> list of image transformation
:return: <SimpleGIFTransform> a gif process run ready
"""
return SimpleGIFTransform(conf.args['altered'], phases, conf.args['output'])
return SimpleGIFTransform(conf.args['input'], phases, conf.args['output'])
def multiple_gif_processing(phases, n):
@ -95,7 +117,7 @@ def multiple_gif_processing(phases, n): @@ -95,7 +117,7 @@ def multiple_gif_processing(phases, n):
"""
filename, extension = os.path.splitext(conf.args['output'])
return MultipleImageTransform(
[conf.args['altered'] for _ in range(n)],
[conf.args['input'] for _ in range(n)],
phases,
["{}{}{}".format(filename, i, extension) for i in range(n)],
SimpleGIFTransform
@ -108,7 +130,7 @@ def simple_image_processing(phases): @@ -108,7 +130,7 @@ def simple_image_processing(phases):
:param phases: <ImageTransform[]> list of image transformation
:return: <SimpleImageTransform> a image process run ready
"""
return SimpleImageTransform(conf.args['altered'], phases, conf.args['output'])
return SimpleImageTransform(conf.args['input'], phases, conf.args['output'])
def multiple_image_processing(phases, n):
@ -120,7 +142,7 @@ def multiple_image_processing(phases, n): @@ -120,7 +142,7 @@ def multiple_image_processing(phases, n):
"""
filename, extension = os.path.splitext(conf.args['output'])
return MultipleImageTransform(
[conf.args['altered'] for _ in range(n)],
[conf.args['input'] for _ in range(n)],
phases,
["{}{}{}".format(filename, i, extension) for i in range(n)]
)

52
processing/image.py

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
import os
import sys
from multiprocessing.pool import ThreadPool
from config import Config as conf
from processing import Process
from utils import read_image, write_image
from utils import read_image, write_image, camel_case_to_str
class SimpleImageTransform(Process):
@ -13,34 +15,62 @@ class SimpleImageTransform(Process): @@ -13,34 +15,62 @@ class SimpleImageTransform(Process):
def __init__(self, input_path, phases, output_path):
"""
ProcessImage Constructor
:param input_path: <string> image path to process
:param input_path: <string> original image path to process
:param output_path: <string> image path to write the result.
:param phases: <ImageTransform[]> list of transformation each image
:param altered_path: <string[]> list of image path of already step done
:param steps: <int,int> starting phase,ending phase
"""
super().__init__()
self.__phases = phases
self.__input_path = input_path
self.__output_path = output_path
self.__image_steps = []
self.__altered_path = conf.args['altered']
self.__starting_step = conf.args['steps'][0] if conf.args['steps'] else 0
self.__ending_step = conf.args['steps'][1] if conf.args['steps'] else None
conf.log.debug("All Phases : {}".format(self.__phases))
conf.log.debug("To Be Executed Phases : {}".format(self.__phases[self.__starting_step:self.__ending_step]))
self.__image_steps = [input_path] + [
os.path.join(self.__altered_path, "{}.png".format(p.__class__.__name__))
for p in self.__phases[:self.__starting_step]
]
def info_start_run(self):
super().info_start_run()
conf.log.debug("Processing on {}".format(self.__input_path))
conf.log.debug("Processing on {}".format(self.__image_steps))
def setup(self):
self.__image_steps.append(read_image(self.__input_path))
try:
self.__image_steps = [read_image(x) if isinstance(x, str) else x for x in self.__image_steps]
except FileNotFoundError as e:
conf.log.error(e)
conf.log.error("{} is not able to resume because it not able to load required images. "
.format(camel_case_to_str(self.__class__.__name__)))
conf.log.error("Possible source of this error is that --altered argument is not a correct "
"directory path that contains valid images.")
sys.exit(1)
def execute(self):
"""
Execute all phases on the image
:return: None
"""
for p in self.__phases:
self.__image_steps.append(p.run(*[self.__image_steps[i] for i in p.input_index]))
for p in self.__phases[len(self.__image_steps) - 1:]:
r = p.run(*[self.__image_steps[i] for i in p.input_index])
self.__image_steps.append(r)
if self.__altered_path:
write_image(r, os.path.join(self.__altered_path, "{}.png".format(p.__class__.__name__)))
conf.log.debug("Writing {}, Result of the Execution of {}"
.format(
os.path.join(self.__altered_path, "{}.png".format(p.__class__.__name__)),
camel_case_to_str(p.__class__.__name__),
))
write_image(self.__image_steps[-1], self.__output_path)
conf.log.debug("{} Image Created ".format(self.__output_path))
conf.log.debug("Writing {}, Result Image Of {} Execution"
.format(self.__output_path, camel_case_to_str(self.__class__.__name__)))
return self.__image_steps[-1]
@ -88,4 +118,4 @@ class MultipleImageTransform(Process): @@ -88,4 +118,4 @@ class MultipleImageTransform(Process):
pool = ThreadPool(conf.args['n_cores'])
pool.map(process_one_image, zip(self.__process_list, range(len(self.__process_list))))
pool.close()
pool.join()
pool.join()

17
utils.py

@ -31,12 +31,17 @@ def read_image(path): @@ -31,12 +31,17 @@ def read_image(path):
def write_image(image, path):
"""
Write a file image to the path
Write a file image to the path (create the directory if needed)
:param image: <RGB> image to write
:param path: <string> location where write the image
:return: <RGB> None
:return: None
"""
dir = os.path.dirname(path)
if dir != '':
os.makedirs(os.path.dirname(path), exist_ok=True)
cv2.imwrite(path, image)
if not check_image_file_validity(path):
conf.log.error(
"Something gone wrong writing {} image file. The final result is not a valid image file.".format(path))
@ -61,16 +66,12 @@ def check_image_file_validity(image_path): @@ -61,16 +66,12 @@ def check_image_file_validity(image_path):
:param image_path: <string> Path to the file to check
:return: <Boolean> True if it's an image file
"""
im, r = None, True
try:
im = Image.open(image_path)
im.verify()
except Exception:
r = False
finally:
if im:
im.close()
return r
return False
return True
def start_rook():

Loading…
Cancel
Save