Add support for training with an alpha channel for Qwen Image 2.1
This commit is contained in:
1 parent
31ddc709c3
commit
086b663bba
8 files changed
+114
-17
No files matched your search
@@ -206,11 +206,11 @@ class QwenImage2Model(BaseModel):
|
||||
self.print_and_status_update("Model Loaded")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# VAE. The latents are RGBA; toolkit images are RGB, so encode pads an
|
||||
# opaque alpha channel and decode drops it again (unless model_kwargs.rgba).
|
||||
# VAE. The latents are RGBA. Images without alpha get an opaque one on
|
||||
# encode, and decode drops it again unless RGBA output is on.
|
||||
# ------------------------------------------------------------------
|
||||
@property
|
||||
def output_rgba(self) -> bool:
|
||||
def load_rgba(self) -> bool:
|
||||
return bool(self.model_config.model_kwargs.get("rgba", False))
|
||||
|
||||
def _latent_stats(self, device, dtype):
|
||||
@@ -242,7 +242,7 @@ class QwenImage2Model(BaseModel):
|
||||
|
||||
def decode_latents(self, latents: torch.Tensor, device=None, dtype=None):
|
||||
images = self._decode_rgba(latents, device=device, dtype=dtype)
|
||||
if not self.output_rgba:
|
||||
if not self.load_rgba:
|
||||
images = images[:, :3]
|
||||
return images
|
||||
|
||||
@@ -277,7 +277,7 @@ class QwenImage2Model(BaseModel):
|
||||
return images.squeeze(2).to(device, dtype=dtype)
|
||||
|
||||
def decode_to_images(self, latents: torch.Tensor) -> List[Image.Image]:
|
||||
"""Decode to PIL, keeping the alpha channel when model_kwargs.rgba is set."""
|
||||
"""Decode to PIL, keeping the alpha channel when load_rgba is set."""
|
||||
return [
|
||||
self.image_tensor_to_pil(image) for image in self.decode_latents(latents)
|
||||
]
|
||||
@@ -521,9 +521,12 @@ class QwenImage2Model(BaseModel):
|
||||
]
|
||||
condition_images = None
|
||||
if paths:
|
||||
# same channels the dataloader gives training references, so a
|
||||
# transparent reference behaves the same way in both
|
||||
mode = "RGBA" if self.load_rgba else "RGB"
|
||||
tensors = [
|
||||
torch.from_numpy(
|
||||
np.array(Image.open(path).convert("RGBA"), dtype=np.float32) / 255.0
|
||||
np.array(Image.open(path).convert(mode), dtype=np.float32) / 255.0
|
||||
)
|
||||
.permute(2, 0, 1)
|
||||
.unsqueeze(0)
|
||||
|
||||
@@ -556,6 +556,13 @@ export const AI_TOOLKIT_UI_MODELS: ModelArch[] = [
|
||||
"config.process[0].model.qtype": ["convrot8", "qfloat8"],
|
||||
"config.process[0].model.qtype_te": ["convrot8", "qfloat8"],
|
||||
"config.process[0].sample.guidance_scale": [3.0, 4.0],
|
||||
// the VAE is RGBA: images load, encode and decode with their alpha
|
||||
"config.process[0].model.model_kwargs": [
|
||||
{
|
||||
rgba: false,
|
||||
},
|
||||
{},
|
||||
],
|
||||
},
|
||||
disableSections: ["network.conv", "train.unload_text_encoder"],
|
||||
// one model: it edits when the dataset has control paths, and is plain
|
||||
@@ -566,6 +573,52 @@ export const AI_TOOLKIT_UI_MODELS: ModelArch[] = [
|
||||
"model.low_vram",
|
||||
"model.layer_offloading",
|
||||
],
|
||||
customModelSelectOptions: [
|
||||
{
|
||||
type: "checkbox",
|
||||
label: "Transparency (RGBA)",
|
||||
getValue: (config: JobConfig) =>
|
||||
config?.config?.process?.[0]?.model?.model_kwargs?.rgba ?? false,
|
||||
onChange: (
|
||||
value: boolean,
|
||||
config: JobConfig,
|
||||
setJobConfig: (value: any, key: string) => void,
|
||||
) => {
|
||||
const kwargs = {
|
||||
...(config?.config?.process?.[0]?.model?.model_kwargs ?? {}),
|
||||
};
|
||||
if (value) {
|
||||
kwargs.rgba = true;
|
||||
} else {
|
||||
delete kwargs.rgba;
|
||||
}
|
||||
setJobConfig(kwargs, "config.process[0].model.model_kwargs");
|
||||
},
|
||||
doc: {
|
||||
title: "Transparency (RGBA)",
|
||||
description: (
|
||||
<div className="space-y-2">
|
||||
<p>
|
||||
This model's VAE is natively RGBA, so alpha can be carried
|
||||
end to end. When on, dataset images and reference images load
|
||||
with their alpha channel, the VAE encodes all four channels, and
|
||||
samples are saved as PNGs with their transparency intact.
|
||||
</p>
|
||||
<p>
|
||||
Images with no alpha of their own get a fully opaque one, so a
|
||||
mixed dataset is fine. Turn this off to train and sample flat
|
||||
RGB: alpha is dropped on the way in and added back as opaque.
|
||||
</p>
|
||||
<p>
|
||||
Changing this re-caches latents, and it cannot be combined with
|
||||
a dataset using <code>alpha_mask</code>, which consumes the
|
||||
alpha channel as a loss mask instead.
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "hidream",
|
||||
|
||||
Reference in new issue
Block a user