| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| import re |
| from .load_images import get_mask_from_file, check_mask_for_errors, blank_if_none |
| from .word_masking import get_word_mask |
| from PIL import ImageChops |
| from modules.shared import opts |
|
|
| |
| |
| def compose_mask(root, args, mask_seq, val_masks, frame_image, inner_idx:int = 0): |
| |
| |
| |
| |
| |
|
|
| seq = "" |
| inner_seq = "" |
| parentheses_counter = 0 |
|
|
| for c in mask_seq: |
| if c == ')': |
| parentheses_counter = parentheses_counter - 1 |
| if parentheses_counter > 0: |
| inner_seq += c |
| if c == '(': |
| parentheses_counter = parentheses_counter + 1 |
| if parentheses_counter == 0: |
| if len(inner_seq) > 0: |
| inner_idx += 1 |
| seq += compose_mask(root, args, inner_seq, val_masks, frame_image, inner_idx) |
| inner_seq = "" |
| else: |
| seq += c |
| |
| if parentheses_counter != 0: |
| raise Exception('Mismatched parentheses in {mask_seq}!') |
|
|
| mask_seq = seq |
|
|
| |
| |
| |
| |
| pattern = r'\[(?P<inner>[\S\s]*?)\]' |
| |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner'] |
| val_masks[str(inner_idx)] = get_mask_from_file(content, args).convert('1') |
| return f"{{{inner_idx}}}" |
| |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| |
| |
| pattern = r'<(?P<inner>[\S\s]*?)>' |
| |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner'] |
| val_masks[str(inner_idx)] = get_word_mask(root, frame_image, content).convert('1') |
| return f"{{{inner_idx}}}" |
| |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| |
| |
| |
| |
| |
| |
| |
| |
| pattern = r'![\S\s]*{(?P<inner>[\S\s]*?)}' |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner'] |
| savename = content |
| if content in root.mask_preset_names: |
| inner_idx += 1 |
| savename = str(inner_idx) |
| val_masks[savename] = ImageChops.invert(val_masks[content]) |
| return f"{{{savename}}}" |
| |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| |
| |
| |
| while True: |
| pattern = r'{(?P<inner1>[\S\s]*?)}[\s]*&[\s]*{(?P<inner2>[\S\s]*?)}' |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner1'] |
| content_second = match_object.groupdict()['inner2'] |
| savename = content |
| if content in root.mask_preset_names: |
| inner_idx += 1 |
| savename = str(inner_idx) |
| val_masks[savename] = ImageChops.logical_and(val_masks[content], val_masks[content_second]) |
| return f"{{{savename}}}" |
| |
| prev_mask_seq = mask_seq |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| if mask_seq is prev_mask_seq: |
| break |
| |
| |
| while True: |
| pattern = r'{(?P<inner1>[\S\s]*?)}[\s]*?\|[\s]*?{(?P<inner2>[\S\s]*?)}' |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner1'] |
| content_second = match_object.groupdict()['inner2'] |
| savename = content |
| if content in root.mask_preset_names: |
| inner_idx += 1 |
| savename = str(inner_idx) |
| val_masks[savename] = ImageChops.logical_or(val_masks[content], val_masks[content_second]) |
| return f"{{{savename}}}" |
| |
| prev_mask_seq = mask_seq |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| if mask_seq is prev_mask_seq: |
| break |
| |
| |
| while True: |
| pattern = r'{(?P<inner1>[\S\s]*?)}[\s]*\^[\s]*{(?P<inner2>[\S\s]*?)}' |
| def parse(match_object): |
| nonlocal inner_idx |
| inner_idx += 1 |
| content = match_object.groupdict()['inner1'] |
| content_second = match_object.groupdict()['inner2'] |
| savename = content |
| if content in root.mask_preset_names: |
| inner_idx += 1 |
| savename = str(inner_idx) |
| val_masks[savename] = ImageChops.logical_xor(val_masks[content], val_masks[content_second]) |
| return f"{{{savename}}}" |
| |
| prev_mask_seq = mask_seq |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| if mask_seq is prev_mask_seq: |
| break |
| |
| |
| while True: |
| pattern = r'{(?P<inner1>[\S\s]*?)}[\s]*\\[\s]*{(?P<inner2>[\S\s]*?)}' |
| def parse(match_object): |
| content = match_object.groupdict()['inner1'] |
| content_second = match_object.groupdict()['inner2'] |
| savename = content |
| if content in root.mask_preset_names: |
| nonlocal inner_idx |
| inner_idx += 1 |
| savename = str(inner_idx) |
| val_masks[savename] = ImageChops.logical_and(val_masks[content], ImageChops.invert(val_masks[content_second])) |
| return f"{{{savename}}}" |
| |
| prev_mask_seq = mask_seq |
| mask_seq = re.sub(pattern, parse, mask_seq) |
| if mask_seq is prev_mask_seq: |
| break |
| |
| |
| |
| |
| pattern = r'{(?P<inner>[\S\s]*?)}' |
| matches = re.findall(pattern, mask_seq) |
| |
| if len(matches) != 1: |
| raise Exception(f'Wrong composable mask expression format! Broken mask sequence: {mask_seq}') |
| |
| return f"{{{matches[0]}}}" |
|
|
| def compose_mask_with_check(root, args, mask_seq, val_masks, frame_image): |
| for k, v in val_masks.items(): |
| val_masks[k] = blank_if_none(v, args.W, args.H, '1').convert('1') |
| return check_mask_for_errors(val_masks[compose_mask(root, args, mask_seq, val_masks, frame_image, 0)[1:-1]].convert('L')) |
|
|