MMD Étagement Chromatique Conscient du Sujet (Mettre le Personnage en Valeur)
0. Conclusion Préliminaire
- Pour les vidéos de danse MMD qui souhaitent « mettre le personnage en valeur », deux voies :
- Modelage par zone lumineuse (recommandé, propre) : un dégradé radial/elliptique doux centré sur le personnage — à l'intérieur de l'ellipse, le personnage est éclairci/réchauffé/accentué/effet bloom ; à l'extérieur, l'arrière-plan est assombri/froid/désaturé/légèrement flou. La transition est large, presque invisible.
- Séparation par masque dur (potentiel élevé mais sale) : différence d'images avec un fond de référence pour obtenir un masque du personnage, étalonnage séparé du personnage et de l'arrière-plan, puis recomposition. La difficulté réside dans l'ombre portée (cast shadow) qui suit le personnage et se confond avec lui → le masque inclut de grandes zones d'ombre → apparition de taches lumineuses ; une érosion forcée endommage les ailes/plumes.
- Choisissez la méthode 1 pour le rendu final ; choisissez la méthode 2 (qualité maximale) si vous pouvez re-rendre depuis Blender/MMD avec un canal alpha pour le personnage.
1. Matériel et Outils
| Élément | Chemin |
|---|---|
| Vidéo source | D:\mmd.mp4\0002-4956.mkv (complet 165.166s) / 字幕\0001-4956 - 副本.mkv (tronqué à ~137s) |
| Scripts d'étalonnage | 字幕\build\grade_ffmpeg.py (zone lumineuse/douce), grade_final5s.py (paramètres du rendu 5s), color_grade.py (ancien masquage par différence), gothic_art.py (étalonnage gothique sur image fixe) |
| Scripts de validation | avoid_layout.py (analyse d'occupation), avoid_side2.py (occupation + bbox) |
| ffmpeg | C:\Users\35530\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-9.0-full_build\bin\ffmpeg.exe |
| Python | C:\Users\35530\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\python\python.exe (PIL/numpy, pas de cv2/apprentissage profond) |
2. Route A : Modelage par Zone Lumineuse (Méthode par Défaut de ce Projet)
2.1 Génération du Masque Lumineux Doux (PNG unique)
import numpy as np
from PIL import Image
W,H = 2560,1080
yy,xx = np.mgrid[0:H,0:W].astype(np.float32)
cx,cy = 0.515,0.565 # centre du personnage (environ ici pour une composition verticale 2560x1080 ; pour d'autres sources, vérifier sur une image clé)
rx,ry = 0.245,0.47 # demi-largeur/demi-hauteur (en proportion) ; trop petit → cercle visible, trop grand → pas de séparation
q = ((xx-W*cx)/(W*rx))**2 + ((yy-H*cy)/(H*ry))**2
mask = np.clip(1.0-q,0,1)**0.55 # 0.5–0.7 donne un rendu très doux
Image.fromarray((mask*255).astype(np.uint8)).save("_mask_final.png")
Références de rendu : 字幕\输出\调色测试\_mask_final.png, 字幕\输出\字幕小样\_mask_final.png.
2.2 Composition avec ffmpeg (Personnage Rehaussé + Arrière-plan Assombri)
Principe : version étalonnée du personnage + version étalonnée de l'arrière-plan, fusion alpha via le masque :
[0:v]split=2[sv][bv];
[sv]eq=brightness=0.050:contrast=1.06:saturation=1.15,
colorbalance=rs=0.02:bs=-0.02:rm=0.05:bm=-0.06:rh=0.02:bh=-0.02,
split=2[sm][sh];[sh]gblur=sigma=14[blur];
[sm][blur]blend=all_mode=screen:all_opacity=0.34[sub];
[sub]format=yuva420p[suba];
[1:v]format=gray[gm];[suba][gm]alphamerge[subj];
[bv]eq=brightness=-0.045:contrast=1.07:saturation=0.87,
colorbalance=rm=-0.03:bm=0.05,gblur=sigma=0.6[bg];
[bg][subj]overlay=0:0,format=yuv420p[v]
Commande :
& $ff -v error -y -ss 36.5 -t 30 -i src.mkv -loop 1 -i _mask_final.png `
-filter_complex "<graphe ci-dessus>" -map "[v]" -t 30 `
-c:v libx264 -preset medium -crf 16 -pix_fmt yuv420p OUT.mp4
Note : avec
-loop 1 -i mask.png, le masque est un flux statique ; aprèsoverlay, n'oubliez pas-tpour limiter la durée. Signification des paramètres : brightness négatif pour l'arrière-plan = assombrir, saturation<1 = désaturer,bm>0= arrière-plan bleuté (froid),gblur= léger flou ; pour le sujet, brightness/saturation/couleurs chaudes/blend screendonne l'effet bloom.
2.3 Jeux de Paramètres Mesurés (2560×1080, MMD scène violette)
| Série | bg brightness | bg sat | subj gain | subj sat | bloom | vignette | Effet |
|---|---|---|---|---|---|---|---|
| A Naturel | −0.035 | 0.82 | +0.030 | 1.08 | 0.20 | 0.30 | Rehaussement léger du personnage, quasi inchangé |
| B Renforcé | −0.075 | 0.70 | +0.055 | 1.16 | 0.34 | 0.42 | Séparation nette, bord de la zone lumineuse légèrement visible |
| Direction finale | −0.085 | 0.68 | +0.050 | 1.15 | 0.30 | 0.38 | Lumière très douce, recommandé pour le fond de la vidéo entière |
Testez les paramètres sur 5s, puis appliquez directement sur 30s/la vidéo entière (ffmpeg traite tout d'un coup, plus rapide que Python image par image).
3. Route B : Masquage Dur (Lorsque vous Avez Besoin d'un Masque Plus Propre)
3.1 Fond de Référence
- Échantillonnez des images toutes les 1/2s de la vidéo entière, réduisez à 1280×540, prenez la médiane pixel par pixel = fond de référence
bg_half.npy. - Commande/récapitulatif :
build_background()dans字幕\build\color_grade.py. - Problème connu : si le personnage reste longtemps au centre, la médiane est « contaminée » par le personnage (certains pixels du personnage sont fréquemment présents) → la différence avec le personnage est trop faible à ces endroits → trous dans le masque. Utilisez
fill_holesou une bbox de secours.
3.2 Masque par Différence d'Images (Résolution 1/4 pour la Rapidité)
m = |frame_q - bg_q|.max(axis=2) > 38
m = MaxFilter(5) (dilatation) → plus grand composant connexe → boucher les trous, adoucir en option
- Utilisé pour l'analyse d'occupation/évitement (voir avoid-subtitles) ; pour l'étalonnage, ajoutez une contrainte de « similarité au personnage », sinon les ombres/taches lumineuses se mélangent.
3.3 Modes d'Échec Connus (Testés sur ce Projet)
- Contamination par les ombres portées : l'ombre du personnage bouge avec lui, le masque devient continu → après étalonnage, des taches lumineuses/colored blocks apparaissent autour du personnage. Solution : n'utilisez pas la différence d'images comme matte précis ; soit acceptez « éclaircir l'ombre aussi » (très étrange), soit revenez au modelage par zone lumineuse.
- Contamination du fond médian : le masque a des trous à l'endroit où le personnage reste immobile → le torse n'est pas étalonné, donnant un aspect tacheté. Solution : bouchez les trous/ utilisez une bbox.
- Banding 8 bits : après une forte poussée des couleurs, le ciel/les dégradés peuvent présenter du banding → ajoutez 1 à 3 niveaux de bruit (ffmpeg
noise=alls=6:allf=t+u) ou sortez en 10 bits/HEVC. - Contraste des sous-titres : un fond assombri rend les caractères blancs plus lisibles ; si l'assombrissement est trop fort, le personnage devient aussi plus sombre, nécessitant un rehaussement supplémentaire ou un bloom.
4. Étalonnages Stylisés (Gothique, Néon, etc.) pour Images Fixes
- Gothique rouge et noir (déjà rejeté par l'utilisateur, conservé pour archive) :
gothic_grade()dans字幕\build\gothic_art.py: assombrir 0.42–0.52, désaturer 0.30–0.42, tons moyens violets/rouges, fort vignettage, brouillard. - Version aux couleurs du thème (ce que l'utilisateur a finalement demandé) : blanc/os blanc principal + lavande/magenta rose en bloom, arrière-plan en violet foncé ; voir les constantes d'étalonnage dans
gothic_art.py(BLOOD/LAV/PINK/VIOLET). - Version néon :
neon_wide.py(dessine le néon directement via ASS, pas d'étalonnage). - Application rapide d'une teinte : le trio
eq+colorbalance+vignettesuffit pour transformer une scène violette en n'importe quelle tonalité :- Cyan froid :
colorbalance=bs=0.10:bm=0.12:bm...(décalage bleu), désaturation ; - Braise chaude :
colorbalance=rs=0.10:rm=0.08,eq=saturation=1.1.
- Cyan froid :
5. Liste de Vérification
- Prélevez 3 à 5 images : la luminosité du personnage et la séparation avec l'arrière-plan sont-elles naturelles ? Le bord de la zone lumineuse est-il visible ?
- Plans rapprochés/gros plans : le visage est-il surexposé ? Le teint est-il dévié ?
- Les zones sombres présentent-elles du noir mort/du banding (8 bits) ?
- Vérifiez avec les sous-titres : les caractères blancs sont-ils suffisamment lisibles ?
- La sortie
ffprobedonne-t-elle la bonne durée/taux d'images ? Pour une sortie 10 bits, utilisez-pix_fmt yuv420p10le -c:v libx265
6. Ressources
- Paramètres du rendu 5s et comparaison :
字幕\输出\调色测试\(A Naturel/B Renforcé/Direction Finale + vidéo de comparaison) - Fond 30s :
字幕\输出\S4S6_30s\_base_30s.mp4(légèrement assombri seulement, pas d'étalonnage complet) - Directions précédemment essayées mais rejetées : gothique (
字幕\输出\字幕设计\G1…G3), FLARE explosive, néon (字幕\输出\字幕小样) — conservées pour référence des paramètres.