-
-
Notifications
You must be signed in to change notification settings - Fork 614
Add Anima regional control support #2524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
da8f931
a702110
8e98cd4
050d178
9fa5755
dc7dbc4
9b5e085
f51f547
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,12 +5,13 @@ | |||||||
| from typing import Any, NamedTuple | ||||||||
|
|
||||||||
| from PyQt5.QtCore import QObject, Qt, QUuid, pyqtSignal | ||||||||
| from PyQt5.QtGui import QColor | ||||||||
|
|
||||||||
| from .. import util | ||||||||
| from ..backend import resources | ||||||||
| from ..backend.api import ControlInput | ||||||||
| from ..backend.resources import Arch, ControlMode, ResourceKind, resource_id | ||||||||
| from ..image import Bounds, Extent, Image | ||||||||
| from ..image import BlendMode, Bounds, Extent, Image | ||||||||
| from ..layer import Layer, LayerType | ||||||||
| from ..localization import translate as _ | ||||||||
| from ..util import PluginError | ||||||||
|
|
@@ -23,6 +24,20 @@ | |||||||
| max_preset_value = 4 | ||||||||
| strength_multiplier = 50 | ||||||||
| clip_vision_extent = Extent(224, 224) | ||||||||
| segmentation_colors = [ | ||||||||
| (120, 120, 120), | ||||||||
| (180, 120, 120), | ||||||||
| (120, 180, 120), | ||||||||
| (120, 120, 180), | ||||||||
| (180, 180, 120), | ||||||||
| (180, 120, 180), | ||||||||
| (120, 180, 180), | ||||||||
| (220, 140, 100), | ||||||||
| (140, 220, 100), | ||||||||
| (100, 140, 220), | ||||||||
| (220, 100, 140), | ||||||||
| (100, 220, 140), | ||||||||
| ] | ||||||||
|
Check failure on line 40 in ai_diffusion/model/control.py
|
||||||||
|
|
||||||||
| mode = Property(ControlMode.reference, persist=True, setter="set_mode") | ||||||||
| layer_id = Property(QUuid(), persist=True) | ||||||||
|
|
@@ -125,6 +140,9 @@ | |||||||
|
|
||||||||
| image = layer.get_pixels(bounds, time) | ||||||||
|
|
||||||||
| if self.mode is ControlMode.segmentation: | ||||||||
| image.make_opaque(background=Qt.GlobalColor.white) | ||||||||
|
|
||||||||
| if self.mode.is_lines or self.mode is ControlMode.stencil: | ||||||||
| image.make_opaque(background=Qt.GlobalColor.white) | ||||||||
|
|
||||||||
|
|
@@ -139,7 +157,63 @@ | |||||||
| strength = self.strength / self.strength_multiplier | ||||||||
| return ControlInput(self.mode, image, strength, (self.start, self.end)) | ||||||||
|
|
||||||||
| def generate_segmentation(self): | ||||||||
| if self.mode is not ControlMode.segmentation: | ||||||||
| return | ||||||||
|
|
||||||||
| ok, msg = self._model.document.check_color_mode() | ||||||||
| if not ok and msg: | ||||||||
| self._model.report_error(msg) | ||||||||
| return | ||||||||
|
|
||||||||
| try: | ||||||||
| bounds = Bounds.from_extent(self._model.document.extent) | ||||||||
| image = self._segmentation_image_from_regions(bounds) | ||||||||
| if image is None: | ||||||||
| self._model.report_error(_("Text prompt regions have not been set up.")) | ||||||||
| return | ||||||||
|
|
||||||||
| layer = self._model.layers.create(f"[Control] {self.mode.text}", image, bounds) | ||||||||
| self.layer_id = layer.id | ||||||||
| except Exception as e: | ||||||||
| self._model.report_error(util.log_error(e)) | ||||||||
| else: | ||||||||
| self._model.clear_error() | ||||||||
|
|
||||||||
| def _segmentation_image_from_regions(self, bounds: Bounds): | ||||||||
| from .region import RegionLink | ||||||||
|
|
||||||||
| image = Image.create(bounds.extent, fill=Qt.GlobalColor.white) | ||||||||
| has_region_layer = False | ||||||||
| root = self._model.active_regions | ||||||||
|
|
||||||||
| layers = [ | ||||||||
| layer | ||||||||
| for layer in root.layers.all | ||||||||
| if root.find_linked(layer, RegionLink.direct) is not None | ||||||||
| and layer.compute_bounds().area > 0 | ||||||||
| and Bounds.intersection(bounds, layer.bounds).area > 0 | ||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| ] | ||||||||
|
|
||||||||
| for index, layer in enumerate(layers): | ||||||||
| color = self.segmentation_colors[index % len(self.segmentation_colors)] | ||||||||
| region_image = self._segmentation_region_image(layer, bounds, color) | ||||||||
| image.draw_image(region_image, blend=BlendMode.alpha) | ||||||||
| has_region_layer = True | ||||||||
|
|
||||||||
| return image if has_region_layer else None | ||||||||
|
|
||||||||
| def _segmentation_region_image( | ||||||||
| self, layer: Layer, bounds: Bounds, color: tuple[int, int, int] | ||||||||
| ): | ||||||||
| mask = layer.get_mask(bounds) | ||||||||
| image = Image.create(bounds.extent, fill=QColor(*color, 255)) | ||||||||
| image._qimage.setAlphaChannel(mask._qimage) | ||||||||
| return image | ||||||||
|
|
||||||||
| def generate(self): | ||||||||
| if not self.can_generate: | ||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any particular reason this was added?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. safeguard for unintended calls
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what unintended calls? if there is no way to hit this code please remove it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea sorry about that, i didnt check there were only two calls for this, and they would be hidden. Removed it. |
||||||||
| return | ||||||||
| self._generate_job = self._model.generate_control_layer(self) | ||||||||
| self.has_active_job = True | ||||||||
|
|
||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed this, but assertion can be disabled right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically yes, but they are not disabled in Krita (and I'm not sure what your point is?)