From 6cccd67ecd67ee268f79263333fa28addf688b88 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Wed, 30 Oct 2024 07:04:25 +1000
Subject: [PATCH] feat(ui): update SAM module to w/ minor improvements from
filter module
---
.../components/SelectObject/SelectObject.tsx | 2 +-
.../konva/CanvasSegmentAnythingModule.ts | 34 ++++++++++---------
2 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/invokeai/frontend/web/src/features/controlLayers/components/SelectObject/SelectObject.tsx b/invokeai/frontend/web/src/features/controlLayers/components/SelectObject/SelectObject.tsx
index 5fb3cc7dca..eeee461209 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/SelectObject/SelectObject.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/SelectObject/SelectObject.tsx
@@ -115,7 +115,7 @@ const SelectObjectContent = memo(
onClick={adapter.segmentAnything.processImmediate}
loadingText={t('controlLayers.selectObject.process')}
variant="ghost"
- isDisabled={isProcessing || !hasPoints || autoProcess}
+ isDisabled={isProcessing || !hasPoints || (autoProcess && hasImageState)}
>
{t('controlLayers.selectObject.process')}
{isProcessing && }
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasSegmentAnythingModule.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasSegmentAnythingModule.ts
index 2a127b060d..171907b0d8 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasSegmentAnythingModule.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasSegmentAnythingModule.ts
@@ -114,7 +114,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
subscriptions = new Set<() => void>();
/**
- * The AbortController used to cancel the filter processing.
+ * The AbortController used to cancel the segment processing.
*/
abortController: AbortController | null = null;
@@ -178,16 +178,16 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
$invert = atom(false);
/**
- * The masked image object, if it exists.
+ * The masked image object module, if it exists.
*/
- maskedImage: CanvasObjectImage | null = null;
+ imageModule: CanvasObjectImage | null = null;
/**
* The Konva nodes for the module.
*/
konva: {
/**
- * The main Konva group node for the module.
+ * The main Konva group node for the module. This is added to the parent layer on start, and removed on teardown.
*/
group: Konva.Group;
/**
@@ -488,7 +488,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
};
/**
- * Adds event listeners needed while segmenting the entity.
+ * Removes event listeners used while segmenting the entity.
*/
unsubscribe = () => {
this.subscriptions.forEach((unsubscribe) => unsubscribe());
@@ -607,18 +607,18 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
this.$imageState.set(imageState);
// Destroy any existing masked image and create a new one
- if (this.maskedImage) {
- this.maskedImage.destroy();
+ if (this.imageModule) {
+ this.imageModule.destroy();
}
if (this.konva.maskTween) {
this.konva.maskTween.destroy();
this.konva.maskTween = null;
}
- this.maskedImage = new CanvasObjectImage(imageState, this);
+ this.imageModule = new CanvasObjectImage(imageState, this);
// Force update the masked image - after awaiting, the image will be rendered (in memory)
- await this.maskedImage.update(imageState, true);
+ await this.imageModule.update(imageState, true);
// Update the compositing rect to match the image size
this.konva.compositingRect.setAttrs({
@@ -629,7 +629,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
// Now we can add the masked image to the mask group. It will be rendered above the compositing rect, but should be
// under it, so we will move the compositing rect to the top
- this.konva.maskGroup.add(this.maskedImage.konva.group);
+ this.konva.maskGroup.add(this.imageModule.konva.group);
this.konva.compositingRect.moveToTop();
// Cache the group to ensure the mask is rendered correctly w/ opacity
@@ -666,7 +666,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
process = debounce(this.processImmediate, this.config.PROCESS_DEBOUNCE_MS);
/**
- * Applies the segmented image to the entity.
+ * Applies the segmented image to the entity, replacing the entity's objects with the masked image.
*/
apply = () => {
const imageState = this.$imageState.get();
@@ -676,7 +676,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
}
this.log.trace('Applying');
- // Rasterize the entity, this time replacing the objects with the masked image
+ // Rasterize the entity, replacing the objects with the masked image
const rect = this.parent.transformer.getRelativeRect();
this.manager.stateApi.rasterizeEntity({
entityIdentifier: this.parent.entityIdentifier,
@@ -694,7 +694,8 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
};
/**
- * Applies the segmented image to the entity.
+ * Saves the segmented image as a new entity of the given type.
+ * @param type The type of entity to save the segmented image as.
*/
saveAs = (type: Exclude) => {
const imageState = this.$imageState.get();
@@ -795,8 +796,9 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
for (const point of this.$points.get()) {
point.konva.circle.destroy();
}
- if (this.maskedImage) {
- this.maskedImage.destroy();
+ if (this.imageModule) {
+ this.imageModule.destroy();
+ this.imageModule = null;
}
if (this.konva.maskTween) {
this.konva.maskTween.destroy();
@@ -878,7 +880,7 @@ export class CanvasSegmentAnythingModule extends CanvasModuleBase {
circle: getKonvaNodeDebugAttrs(konva.circle),
})),
imageState: deepClone(this.$imageState.get()),
- maskedImage: this.maskedImage?.repr(),
+ imageModule: this.imageModule?.repr(),
config: deepClone(this.config),
$isSegmenting: this.$isSegmenting.get(),
$lastProcessedHash: this.$lastProcessedHash.get(),