Sous-titres avec évitement du personnage (totalement / autant que possible sans obstruction)
0. Distinguer les deux objectifs
- "Totalement sans obstruction" : L'intersection de chaque boîte de caractère avec le masque du personnage pour chaque image est zéro. Le prix à payer est que le texte ne peut être placé que dans des colonnes étroites sur les côtés ou en haut, avec une taille de police limitée.
- "Autant que possible sans obstruction" : Permet de chevaucher les bords des ailes ou l'arrière-plan, mais le visage et le corps doivent être propres. On peut continuer à utiliser un style de grande police (S4/S6, etc.), en ne vérifiant que les plans rapprochés.
Par défaut, cette compétence exécute la version "totalement sans obstruction" et fournit des données vérifiables ; si l'utilisateur demande "explosif/gros caractères/art", il s'agit probablement de la seconde option.
1. Algorithme principal (version rapide : seulement la boîte englobante)
On n'a plus besoin de calculer un matte pixel par pixel, seulement la boîte englobante du personnage. On utilise 1/4 de résolution, c'est très rapide :
- Image de fond
bg_half.npy(1280×540, voir 2.1/3.1 de la compétence subject-color-grade). - Chaque image réduite à 640×270, différence avec l'image de fond :
d = |frame-bg|.max(axis=2), seuil 38 (un seuil plus bas inclurait les panneaux LOVE ou les taches lumineuses). MaxFilter(5)dilatation → plus grand composant connexe (BFS, très rapide en 640×270) → prendre la boîte englobante ×4 pour revenir à la résolution d'origine.- Par fenêtre de réplique de parole, fusionner les boîtes de chaque image (le personnage bouge pendant une réplique, on utilise la plage la plus large de la réplique entière), obtenir pour chaque réplique
bounds = (left,right,top,bottom). - Mise en page : placer le texte à gauche de
left-50/ à droite deright+50/ en haut / en bas ; réduire la taille de police en fonction de la largeur disponible. - Vérification image par image : mapper chaque boîte de caractère en 640×270, calculer l'intersection avec le masque de chaque image, rapporter le pire hit ; s'il n'est pas zéro, réduire globalement la taille de police et vérifier à nouveau jusqu'à obtenir zéro.
2. Implémentation directement réutilisable
字幕\build\avoid_side2.py (recommandé, version complète : pass1 calcul boîte → layout → vérification → rendu → images clés) :
$py='C:\Users\35530\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\python\python.exe'
& $py '字幕\build\avoid_side2.py'
Il traite fixement un ancien clip (frames 0001-4956, 15.4 s) ; pour changer de clip ou segment, modifier ces constantes :
SRC/OUT/T0,T1CUES(début/fin de chaque réplique, relatif au segment)- Dans
EL, les propositions de taille/position (L/Rcolonne, y, fs) LEFT_MARGIN/ logique de largeur disponible à droite Produit :NEON_avoid_15s.ass+ vidéo rendue + table d'images clés. Versions plus anciennes (démo combinée) :avoid_demo.py,avoid_debug.py,avoid_layout.py(carte de zone occupée分析_占位与选位.jpg).
3. Données mesurées sur ce projet (ancien clip, 0:51–1:06.4)
- Mise en page fixe en bas : 6/6 répliques obstruent le personnage, taux d'occlusion du personnage 7 %–12 %.
- Évitement par colonne latérale : 0/6 répliques obstruent le personnage, occlusion par réplique ≤ 0.2 % ; vérification image par image : 0 pixel.
- Colonnes latérales disponibles par réplique (ancien clip, pleine largeur 2560) : colonne gauche environ 0–500 px, colonne droite environ 2100–2560 px, différentes pour chaque réplique, doivent être calculées en direct.
- Le personnage au centre du cadre, ailes déployées, occupe environ 48 %–82 % de la largeur ; en plan rapproché/gros plan, il remplit presque tout → les images en gros plan ne peuvent placer le texte que dans les coins haut/bas.
4. Stratégie de mise en page (esthétique même sans obstruction)
- Mettre la parole principale dans la colonne gauche, les mots décoratifs dans la colonne droite, créant une impression de "dialogue gauche-droite" ;
- Placer les longues phrases (comme "MAKING EVERYBODY GO") en haut, ne laisser que du petit texte ou des informations de largeur fixe en bas ;
- Chaque réplique n'a qu'un protagoniste visuel, les autres mots sont en petit texte, éviter qu'une phrase entière en grande police ne tienne pas dans la colonne latérale ;
- L'estimation de la boîte de caractère doit être conservatrice : largeur ASCII ≈ fs×0.66, CJK ≈ fs×1.06 ; laisser 10–14 px de marge.
5. Liste de vérification
- La boîte englobante par fenêtre de réplique a-t-elle oublié l'extrémité des ailes ou le sommet de la tête (voir
分析_占用区域.jpg) ? - Vérification image par image : worst hit = 0 (le script l'affiche).
- Regarder 3–4 images : le texte touche-t-il les bords / est-il rogné ? Obstrue-t-il un petit doigt ou une aile ?
- Vérifier séparément les plans rapprochés / gros plans.
- Si la version "autant que possible sans obstruction" est autorisée, noter quelles images obstruent les ailes (acceptable).
6. Pièges connus
- Les panneaux LOL ou les taches lumineuses en arrière-plan sont mal détectés par la différence d'image → le seuil 38 + le plus grand composant connexe les éliminent généralement ; si cela ne suffit pas, ajouter une connaissance spatiale a priori (le personnage est au centre).
- L'ombre du personnage peut être prise pour le personnage (boîte plus grande) → c'est sûr pour l'évitement (vous éviterez l'ombre), mais rend les colonnes latérales plus étroites.
- Le filtre
MaxFilteren 640×270 ≈ agrandissement de 8 px en pleine résolution, ne pas ajouter de marge supplémentaire lors de la vérification. - Si un nouveau clip / une nouvelle position de caméra est utilisée, toutes les boîtes doivent être recalculées, ne pas réutiliser les chiffres de l'ancien clip.