Skip to content

Commit

Permalink
add Tilt adjustment threshold option
Browse files Browse the repository at this point in the history
  • Loading branch information
ototadana committed Jul 13, 2023
1 parent 6243c30 commit 3fe6a6e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ If the value is too small, facial collapse cannot be corrected, but if it is too
</details>


##### Tilt adjustment threshold (0-180)
This option defines the angle, in degrees, above which tilt correction will be automatically applied to detected faces. For instance, if set to 20, any face detected with a tilt greater than 20 degrees will be adjusted. However, if the "Adjust tilt for detected faces" option in the Face Editor section of the "Settings" tab is enabled, tilt correction will always be applied, regardless of the tilt adjustment threshold value.

#### Step 4. Paste the Faces
##### Apply inside mask only
Paste an image cut out in the shape of a face instead of a square image.
Expand Down
7 changes: 7 additions & 0 deletions scripts/entities/option.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Option:
DEFAULT_AFFECTED_AREAS = ["Face"]
DEFAULT_WORKFLOW = open(os.path.join(workflows_dir, "default.json")).read()
DEFAULT_UPSCALER = "None"
DEFAULT_TILT_ADJUSTMENT_THRESHOLD = 40

def __init__(self, *args) -> None:
self.extra_options: Dict[str, Dict[str, str]] = {}
Expand All @@ -46,6 +47,7 @@ def __init__(self, *args) -> None:
self.show_original_image = Option.DEFAULT_SHOW_ORIGINAL_IMAGE
self.workflow = Option.DEFAULT_WORKFLOW
self.upscaler = Option.DEFAULT_UPSCALER
self.tilt_adjustment_threshold = Option.DEFAULT_TILT_ADJUSTMENT_THRESHOLD

if len(args) > 0 and isinstance(args[0], dict):
self.update_by_dict(args[0])
Expand Down Expand Up @@ -81,6 +83,9 @@ def update_by_list(self, args: tuple) -> None:
self.show_original_image = args[16] if arg_len > 16 and isinstance(args[16], bool) else self.show_original_image
self.workflow = args[17] if arg_len > 17 and isinstance(args[17], str) else self.workflow
self.upscaler = args[18] if arg_len > 18 and isinstance(args[18], str) else self.upscaler
self.tilt_adjustment_threshold = (
args[19] if arg_len > 19 and isinstance(args[19], int) else self.tilt_adjustment_threshold
)

def update_by_dict(self, params: dict) -> None:
self.face_margin = params.get("face_margin", self.face_margin)
Expand All @@ -102,6 +107,7 @@ def update_by_dict(self, params: dict) -> None:
self.show_original_image = params.get("show_original_image", self.show_original_image)
self.workflow = params.get("workflow", self.workflow)
self.upscaler = params.get("upscaler", self.upscaler)
self.tilt_adjustment_threshold = params.get("tilt_adjustment_threshold", self.tilt_adjustment_threshold)

for k, v in params.items():
if isinstance(v, dict):
Expand All @@ -126,6 +132,7 @@ def to_dict(self) -> dict:
Option.add_prefix("affected_areas"): str.join(";", self.affected_areas),
Option.add_prefix("workflow"): self.workflow,
Option.add_prefix("upscaler"): self.upscaler,
Option.add_prefix("tilt_adjustment_threshold"): self.tilt_adjustment_threshold,
}

for option_group_name, options in self.extra_options.items():
Expand Down
10 changes: 10 additions & 0 deletions scripts/ui/ui_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ def __build(self, workflow_selector: gr.Dropdown):
)
self.infotext_fields.append((strength1, Option.add_prefix("strength1")))

tilt_adjustment_threshold = gr.Slider(
label="Tilt adjustment threshold",
minimum=0,
maximum=180,
step=10,
value=Option.DEFAULT_TILT_ADJUSTMENT_THRESHOLD,
)
self.infotext_fields.append((tilt_adjustment_threshold, Option.add_prefix("tilt_adjustment_threshold")))

apply_scripts_to_faces = gr.Checkbox(
label="Apply scripts to faces", visible=False, value=Option.DEFAULT_APPLY_SCRIPTS_TO_FACES
)
Expand Down Expand Up @@ -173,6 +182,7 @@ def __build(self, workflow_selector: gr.Dropdown):
show_original_image,
workflow,
upscaler,
tilt_adjustment_threshold,
]


Expand Down
20 changes: 15 additions & 5 deletions scripts/use_cases/workflow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,22 @@ def process(self, jobs: List[Job], face: Face, p: StableDiffusionProcessingImg2I
params["strength1"] = option.strength1

angle = face.get_angle()
face.image = rotate_image(face.image, angle) if self.correct_tilt else face.image
correct_tilt = self.__correct_tilt(option, angle)
face.image = rotate_image(face.image, angle) if correct_tilt else face.image

image = face_processor.process(face, p, **params)

face.image = rotate_image(image, -angle) if self.correct_tilt else image
face.image = rotate_image(image, -angle) if correct_tilt else image
return face.image

def __correct_tilt(self, option: Option, angle: float) -> bool:
if self.correct_tilt:
return True
angle = abs(angle)
if angle > 180:
angle = 360 - angle
return angle > option.tilt_adjustment_threshold

def generate_mask(self, jobs: List[Job], face_image: np.ndarray, face: Face, option: Option) -> np.ndarray:
mask = None
for job in jobs:
Expand All @@ -160,10 +169,11 @@ def generate_mask(self, jobs: List[Job], face_image: np.ndarray, face: Face, opt
params["tag"] = face.face_area.tag

angle = face.get_angle()
image = rotate_array(face_image, angle) if self.correct_tilt else face_image
face_area_on_image = face.rotate_face_area_on_image(angle) if self.correct_tilt else face.face_area_on_image
correct_tilt = self.__correct_tilt(option, angle)
image = rotate_array(face_image, angle) if correct_tilt else face_image
face_area_on_image = face.rotate_face_area_on_image(angle) if correct_tilt else face.face_area_on_image
m = mask_generator.generate_mask(image, face_area_on_image, **params)
m = rotate_array(m, -angle) if self.correct_tilt else m
m = rotate_array(m, -angle) if correct_tilt else m

if mask is None:
mask = m
Expand Down

0 comments on commit 3fe6a6e

Please sign in to comment.