1- using StabilityMatrix . Avalonia . Models . Inference ;
2- using StabilityMatrix . Avalonia . Services ;
1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
34using StabilityMatrix . Core . Models . Inference ;
45
56namespace StabilityMatrix . Avalonia . Services ;
67
8+ public enum SceneType
9+ {
10+ Unknown ,
11+ People ,
12+ Landscape ,
13+ Architecture
14+ }
15+
716public static class PromptInjectionOutpaint
817{
918 public static void ApplyOutpaintPromptInjection (
1019 GenerationParameters parameters ,
1120 string modelName ,
21+ IEnumerable < string > availableModels ,
1222 ref string positivePrompt ,
1323 ref string negativePrompt )
1424 {
15- // 1) Pose suppression
16- var poseSuppression = GetPoseSuppression ( parameters . OutpaintTop , parameters . OutpaintBottom ) ;
25+ // 1) Auto-switch model if it's bad for outpaint (RV6, Hyper-Inpaint, etc.)
26+ modelName = AutoSwitchModelIfNeeded ( modelName , availableModels ) ;
27+
28+ // 2) Pose suppression (vertical vs horizontal)
29+ var poseSuppression = GetPoseSuppression (
30+ parameters . OutpaintTop ,
31+ parameters . OutpaintBottom ) ;
1732
18- // 2 ) Model-aware injection
33+ // 3 ) Model-aware injection (RV6, Hyper, Inpaint)
1934 var modelInjection = GetModelAwareInjection ( modelName ) ;
2035
21- // 3) Scene-aware injection
22- var sceneInjection = GetSceneAwareInjection (
36+ // 4) Scene-aware injection (people / landscape / architecture)
37+ var sceneTypeInjection = GetSceneTypeInjection ( parameters . SceneType ) ;
38+
39+ // 5) Outpaint-direction-aware injection (horizontal vs vertical)
40+ var sceneDirectionInjection = GetSceneDirectionInjection (
2341 parameters . OutpaintLeft ,
2442 parameters . OutpaintRight ,
2543 parameters . OutpaintTop ,
2644 parameters . OutpaintBottom ) ;
2745
28- // 4 ) Strength-aware injection
46+ // 6 ) Strength-aware injection (if too low for RV6, reinforce)
2947 var strengthInjection = GetStrengthAwareInjection (
3048 parameters . SmartOutpaintInjectionStrength ,
3149 modelName ) ;
3250
3351 // Build final positive
34- positivePrompt = string . Join ( ", " ,
52+ positivePrompt = JoinNonEmpty (
3553 positivePrompt ,
3654 poseSuppression ,
3755 modelInjection . Positive ,
38- sceneInjection . Positive ,
56+ sceneTypeInjection . Positive ,
57+ sceneDirectionInjection . Positive ,
3958 strengthInjection . Positive
4059 ) ;
4160
4261 // Build final negative
43- negativePrompt = string . Join ( ", " ,
62+ negativePrompt = JoinNonEmpty (
4463 negativePrompt ,
4564 poseSuppression ,
4665 modelInjection . Negative ,
47- sceneInjection . Negative ,
66+ sceneTypeInjection . Negative ,
67+ sceneDirectionInjection . Negative ,
4868 strengthInjection . Negative
4969 ) ;
70+
71+ // Debug overlay
72+ parameters . DebugFinalPositive = positivePrompt ;
73+ parameters . DebugFinalNegative = negativePrompt ;
74+ parameters . DebugFinalModelName = modelName ;
75+ }
76+
77+ // ------------------------------------------------------------
78+ // HELPERS
79+ // ------------------------------------------------------------
80+
81+ private static string JoinNonEmpty ( params string ? [ ] parts )
82+ {
83+ return string . Join ( ", " ,
84+ parts . Where ( p => ! string . IsNullOrWhiteSpace ( p ) ) ! ) ;
85+ }
86+
87+ // ------------------------------------------------------------
88+ // AUTO-SWITCH MODEL
89+ // ------------------------------------------------------------
90+
91+ private static bool HasPoseCompletionBias ( string modelName )
92+ {
93+ var n = modelName . ToLowerInvariant ( ) ;
94+ return n . Contains ( "v6" )
95+ || n . Contains ( "hyper" )
96+ || n . Contains ( "inpaint" )
97+ || n . Contains ( "b1" ) ;
98+ }
99+
100+ public static string AutoSwitchModelIfNeeded ( string modelName , IEnumerable < string > availableModels )
101+ {
102+ if ( ! HasPoseCompletionBias ( modelName ) )
103+ return modelName ;
104+
105+ // Prefer Realistic Vision V5.1
106+ var rv51 = availableModels . FirstOrDefault ( m =>
107+ m . Contains ( "Realistic Vision V5.1" , StringComparison . InvariantCultureIgnoreCase ) ) ;
108+
109+ if ( ! string . IsNullOrWhiteSpace ( rv51 ) )
110+ return rv51 ! ;
111+
112+ // Fallback: any Realistic Vision V5
113+ var rv5 = availableModels . FirstOrDefault ( m =>
114+ m . Contains ( "Realistic Vision V5" , StringComparison . InvariantCultureIgnoreCase ) ) ;
115+
116+ return string . IsNullOrWhiteSpace ( rv5 ) ? modelName : rv5 ! ;
50117 }
51118
52119 // ------------------------------------------------------------
53120 // POSE SUPPRESSION
54121 // ------------------------------------------------------------
122+
55123 private static string GetPoseSuppression ( int expandTop , int expandBottom )
56124 {
57125 bool vertical = expandTop > 0 || expandBottom > 0 ;
@@ -67,6 +135,7 @@ private static string GetPoseSuppression(int expandTop, int expandBottom)
67135 // ------------------------------------------------------------
68136 // MODEL-AWARE INJECTION
69137 // ------------------------------------------------------------
138+
70139 private static ( string Positive , string Negative ) GetModelAwareInjection ( string modelName )
71140 {
72141 var name = modelName . ToLowerInvariant ( ) ;
@@ -89,9 +158,43 @@ private static (string Positive, string Negative) GetModelAwareInjection(string
89158 }
90159
91160 // ------------------------------------------------------------
92- // SCENE-AWARE INJECTION
161+ // SCENE-TYPE INJECTION (people / landscape / architecture)
162+ // ------------------------------------------------------------
163+
164+ private static ( string Positive , string Negative ) GetSceneTypeInjection ( SceneType scene )
165+ {
166+ return scene switch
167+ {
168+ SceneType . People => (
169+ Positive :
170+ "maintain facial structure, maintain body proportions, match skin tone, match lighting, natural anatomy" ,
171+ Negative :
172+ "distorted anatomy, extra limbs, stretched body, incorrect face, uncanny face"
173+ ) ,
174+
175+ SceneType . Landscape => (
176+ Positive :
177+ "extend environment, extend horizon, match sky gradient, match terrain, seamless background continuation" ,
178+ Negative :
179+ "warped horizon, mismatched lighting, inconsistent terrain"
180+ ) ,
181+
182+ SceneType . Architecture => (
183+ Positive :
184+ "extend building structure, maintain straight lines, maintain perspective, match materials, match lighting" ,
185+ Negative :
186+ "warped geometry, bent lines, incorrect perspective, broken architecture"
187+ ) ,
188+
189+ _ => ( "" , "" )
190+ } ;
191+ }
192+
193+ // ------------------------------------------------------------
194+ // SCENE-DIRECTION INJECTION (horizontal vs vertical)
93195 // ------------------------------------------------------------
94- private static ( string Positive , string Negative ) GetSceneAwareInjection (
196+
197+ private static ( string Positive , string Negative ) GetSceneDirectionInjection (
95198 int left , int right , int top , int bottom )
96199 {
97200 bool horizontal = left > 0 || right > 0 ;
@@ -102,13 +205,22 @@ private static (string Positive, string Negative) GetSceneAwareInjection(
102205
103206 if ( horizontal )
104207 {
105- pos += "extend background, extend environment, match lighting, match perspective, seamless continuation" ;
208+ pos = JoinNonEmpty (
209+ pos ,
210+ "extend background, extend environment, match lighting, match perspective, seamless continuation"
211+ ) ;
106212 }
107213
108214 if ( vertical )
109215 {
110- pos += ", extend composition, maintain proportions, avoid stretching body" ;
111- neg += ", distorted proportions, stretched anatomy" ;
216+ pos = JoinNonEmpty (
217+ pos ,
218+ "extend composition, maintain proportions, avoid stretching body"
219+ ) ;
220+ neg = JoinNonEmpty (
221+ neg ,
222+ "distorted proportions, stretched anatomy"
223+ ) ;
112224 }
113225
114226 return ( pos , neg ) ;
@@ -117,6 +229,7 @@ private static (string Positive, string Negative) GetSceneAwareInjection(
117229 // ------------------------------------------------------------
118230 // STRENGTH-AWARE INJECTION
119231 // ------------------------------------------------------------
232+
120233 private static ( string Positive , string Negative ) GetStrengthAwareInjection (
121234 double strength ,
122235 string modelName )
0 commit comments