|
| 1 | +using StabilityMatrix.Avalonia.Models.Inference; |
1 | 2 | using StabilityMatrix.Avalonia.Services; |
| 3 | +using StabilityMatrix.Core.Models.Inference; |
2 | 4 |
|
| 5 | +namespace StabilityMatrix.Avalonia.Services; |
3 | 6 |
|
4 | | -namespace StabilityMatrix.Avalonia.Services |
| 7 | +public static class PromptInjectionOutpaint |
5 | 8 | { |
6 | | - public readonly struct OutpaintPromptInjection |
| 9 | + public static void ApplyOutpaintPromptInjection( |
| 10 | + GenerationParameters parameters, |
| 11 | + string modelName, |
| 12 | + ref string positivePrompt, |
| 13 | + ref string negativePrompt) |
7 | 14 | { |
8 | | - public string Positive { get; } |
9 | | - public string Negative { get; } |
| 15 | + // 1) Pose suppression |
| 16 | + var poseSuppression = GetPoseSuppression(parameters.OutpaintTop, parameters.OutpaintBottom); |
| 17 | + |
| 18 | + // 2) Model-aware injection |
| 19 | + var modelInjection = GetModelAwareInjection(modelName); |
| 20 | + |
| 21 | + // 3) Scene-aware injection |
| 22 | + var sceneInjection = GetSceneAwareInjection( |
| 23 | + parameters.OutpaintLeft, |
| 24 | + parameters.OutpaintRight, |
| 25 | + parameters.OutpaintTop, |
| 26 | + parameters.OutpaintBottom); |
| 27 | + |
| 28 | + // 4) Strength-aware injection |
| 29 | + var strengthInjection = GetStrengthAwareInjection( |
| 30 | + parameters.SmartOutpaintInjectionStrength, |
| 31 | + modelName); |
| 32 | + |
| 33 | + // Build final positive |
| 34 | + positivePrompt = string.Join(", ", |
| 35 | + positivePrompt, |
| 36 | + poseSuppression, |
| 37 | + modelInjection.Positive, |
| 38 | + sceneInjection.Positive, |
| 39 | + strengthInjection.Positive |
| 40 | + ); |
| 41 | + |
| 42 | + // Build final negative |
| 43 | + negativePrompt = string.Join(", ", |
| 44 | + negativePrompt, |
| 45 | + poseSuppression, |
| 46 | + modelInjection.Negative, |
| 47 | + sceneInjection.Negative, |
| 48 | + strengthInjection.Negative |
| 49 | + ); |
| 50 | + } |
| 51 | + |
| 52 | + // ------------------------------------------------------------ |
| 53 | + // POSE SUPPRESSION |
| 54 | + // ------------------------------------------------------------ |
| 55 | + private static string GetPoseSuppression(int expandTop, int expandBottom) |
| 56 | + { |
| 57 | + bool vertical = expandTop > 0 || expandBottom > 0; |
| 58 | + |
| 59 | + if (vertical) |
| 60 | + { |
| 61 | + return "avoid pose continuation, avoid extending limbs, avoid extending torso, avoid adding hands above head, avoid adding arms, disconnected limbs, extra arms, extra hands, incorrect anatomy"; |
| 62 | + } |
| 63 | + |
| 64 | + return "avoid pose continuation, avoid extending limbs, disconnected limbs, extra arms, extra hands"; |
| 65 | + } |
| 66 | + |
| 67 | + // ------------------------------------------------------------ |
| 68 | + // MODEL-AWARE INJECTION |
| 69 | + // ------------------------------------------------------------ |
| 70 | + private static (string Positive, string Negative) GetModelAwareInjection(string modelName) |
| 71 | + { |
| 72 | + var name = modelName.ToLowerInvariant(); |
| 73 | + |
| 74 | + bool isRv6 = |
| 75 | + name.Contains("v6") || |
| 76 | + name.Contains("hyper") || |
| 77 | + name.Contains("inpaint") || |
| 78 | + name.Contains("b1"); |
| 79 | + |
| 80 | + if (!isRv6) |
| 81 | + return ("", ""); |
| 82 | + |
| 83 | + return ( |
| 84 | + Positive: |
| 85 | + "avoid HDR contrast, avoid clarity boost, avoid stylized anatomy, maintain natural lighting, maintain original proportions", |
| 86 | + Negative: |
| 87 | + "HDR, overprocessed, oversharpened, extra limbs, pose completion, distorted anatomy" |
| 88 | + ); |
| 89 | + } |
| 90 | + |
| 91 | + // ------------------------------------------------------------ |
| 92 | + // SCENE-AWARE INJECTION |
| 93 | + // ------------------------------------------------------------ |
| 94 | + private static (string Positive, string Negative) GetSceneAwareInjection( |
| 95 | + int left, int right, int top, int bottom) |
| 96 | + { |
| 97 | + bool horizontal = left > 0 || right > 0; |
| 98 | + bool vertical = top > 0 || bottom > 0; |
| 99 | + |
| 100 | + string pos = ""; |
| 101 | + string neg = ""; |
| 102 | + |
| 103 | + if (horizontal) |
| 104 | + { |
| 105 | + pos += "extend background, extend environment, match lighting, match perspective, seamless continuation"; |
| 106 | + } |
10 | 107 |
|
11 | | - public OutpaintPromptInjection(string positive, string negative) |
| 108 | + if (vertical) |
12 | 109 | { |
13 | | - Positive = positive; |
14 | | - Negative = negative; |
| 110 | + pos += ", extend composition, maintain proportions, avoid stretching body"; |
| 111 | + neg += ", distorted proportions, stretched anatomy"; |
15 | 112 | } |
16 | 113 |
|
17 | | - public static readonly OutpaintPromptInjection Empty = new("", ""); |
| 114 | + return (pos, neg); |
18 | 115 | } |
19 | 116 |
|
20 | | - public static class PromptInjectionOutpaint |
| 117 | + // ------------------------------------------------------------ |
| 118 | + // STRENGTH-AWARE INJECTION |
| 119 | + // ------------------------------------------------------------ |
| 120 | + private static (string Positive, string Negative) GetStrengthAwareInjection( |
| 121 | + double strength, |
| 122 | + string modelName) |
21 | 123 | { |
22 | | - public static OutpaintPromptInjection Build( |
23 | | - int expandLeft, |
24 | | - int expandRight, |
25 | | - int expandTop, |
26 | | - int expandBottom, |
27 | | - double strength // 0.0 – 1.0 |
28 | | - ) |
| 124 | + var name = modelName.ToLowerInvariant(); |
| 125 | + bool isRv6 = name.Contains("v6") || name.Contains("hyper"); |
| 126 | + |
| 127 | + if (!isRv6) |
| 128 | + return ("", ""); |
| 129 | + |
| 130 | + if (strength < 0.6) |
29 | 131 | { |
30 | | - if (strength <= 0.0) |
31 | | - return OutpaintPromptInjection.Empty; |
32 | | - |
33 | | - var pos = new List<string>(); |
34 | | - var neg = new List<string>(); |
35 | | - |
36 | | - // scale factor ovisno o veličini outpainta |
37 | | - var total = expandLeft + expandRight + expandTop + expandBottom; |
38 | | - var sizeFactor = total <= 0 ? 0.0 : Math.Clamp(total / 512.0, 0.25, 1.5); |
39 | | - var w = strength * sizeFactor; // ukupna “težina” injekcije |
40 | | - |
41 | | - // helper za weight |
42 | | - string W(string text, double weight) |
43 | | - => weight == 0.0 ? text : $"{text}::{weight:0.##}"; |
44 | | - |
45 | | - bool down = expandBottom > 0; |
46 | | - bool up = expandTop > 0; |
47 | | - bool left = expandLeft > 0; |
48 | | - bool right = expandRight > 0; |
49 | | - bool horizontal = left || right; |
50 | | - bool vertical = up || down; |
51 | | - |
52 | | - // DOLJE – noge, donji dio tijela |
53 | | - if (down) |
54 | | - { |
55 | | - pos.Add("full body continuation"); |
56 | | - pos.Add("anatomically correct legs"); |
57 | | - pos.Add("natural posture"); |
58 | | - pos.Add("consistent proportions"); |
59 | | - |
60 | | - neg.Add(W("disfigured legs", -1.0 * w)); |
61 | | - neg.Add(W("broken anatomy", -1.0 * w)); |
62 | | - neg.Add(W("extra limbs", -1.2 * w)); |
63 | | - neg.Add(W("distorted proportions", -0.8 * w)); |
64 | | - } |
65 | | - |
66 | | - // GORE – gornji dio tijela, glava |
67 | | - if (up) |
68 | | - { |
69 | | - pos.Add("upper body continuation"); |
70 | | - pos.Add("head and shoulders"); |
71 | | - pos.Add("natural anatomy"); |
72 | | - pos.Add("consistent proportions"); |
73 | | - |
74 | | - neg.Add(W("deformed head", -1.0 * w)); |
75 | | - neg.Add(W("broken neck", -1.0 * w)); |
76 | | - neg.Add(W("extra faces", -1.2 * w)); |
77 | | - } |
78 | | - |
79 | | - // LIJEVO / DESNO – scena, pozadina |
80 | | - if (horizontal) |
81 | | - { |
82 | | - pos.Add("scene continuation"); |
83 | | - pos.Add("consistent background"); |
84 | | - pos.Add("matching lighting"); |
85 | | - pos.Add("seamless environment"); |
86 | | - |
87 | | - neg.Add(W("mismatched lighting", -1.0 * w)); |
88 | | - neg.Add(W("warped background", -1.0 * w)); |
89 | | - neg.Add(W("duplicate objects", -1.0 * w)); |
90 | | - } |
91 | | - |
92 | | - // KOMBINACIJE – ako je sve, naglasi koherenciju |
93 | | - if (horizontal && vertical) |
94 | | - { |
95 | | - pos.Add("coherent composition"); |
96 | | - pos.Add("consistent perspective"); |
97 | | - pos.Add("seamless extension of the original image"); |
98 | | - |
99 | | - neg.Add(W("incoherent composition", -0.8 * w)); |
100 | | - neg.Add(W("perspective distortion", -0.8 * w)); |
101 | | - } |
102 | | - |
103 | | - if (pos.Count == 0 && neg.Count == 0) |
104 | | - return OutpaintPromptInjection.Empty; |
105 | | - |
106 | | - var positive = " " + string.Join(", ", pos.Distinct()); |
107 | | - var negative = " " + string.Join(", ", neg.Distinct()); |
108 | | - |
109 | | - return new OutpaintPromptInjection(positive, negative); |
| 132 | + return ( |
| 133 | + Positive: "strong scene continuation, strong composition preservation", |
| 134 | + Negative: "pose completion, stylized anatomy" |
| 135 | + ); |
110 | 136 | } |
| 137 | + |
| 138 | + return ("", ""); |
111 | 139 | } |
112 | 140 | } |
0 commit comments