La profondeur de la scène est estimée à partir de la photo (MiDaS small ou Depth Anything V2 Small) et mélangée aux gris : les planches suivent les volumes du sujet plutôt que ses lumières et ses ombres. - Onglet « Profondeur » : part de la carte de profondeur, modèle, et détails fins de la photo gravés dans la profondeur (yeux, bouche). - Répartition des niveaux : rapproche les planches d'aires égales quand les valeurs sont tassées sur quelques gris. - Images 16 bits lues sur toute leur plage (elles étaient écrêtées à 255). - Le Python d'Inkscape (MinGW, sans pip) ne peut pas charger onnxruntime : le calcul tourne dans un environnement à part, installé par deploy.ps1 -Depth, lancé en sous-processus, résultat gardé en cache. - Depth Anything sur la carte graphique (DirectML) avec repli sur le processeur ; MiDaS small toujours sur le processeur, DirectML lui faisant rendre une carte fausse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AumyrbcuQobB3GbPrFjG9i
202 lines
8.1 KiB
PowerShell
202 lines
8.1 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Déploie l'extension « Iso-couches par nuances de gris » dans Inkscape.
|
|
|
|
.DESCRIPTION
|
|
Copie gray_iso_layers.inx, gray_iso_layers.py, gray_iso_layers_core.py, le schéma de l'onglet
|
|
« Help » (images\parameters_en.png) et les traductions
|
|
compilées (locale\<langue>\LC_MESSAGES\grayisolayers.mo) dans un
|
|
sous-dossier dédié du répertoire des extensions utilisateur d'Inkscape
|
|
(Inkscape explore récursivement ce répertoire). Refuse de s'exécuter si
|
|
Inkscape est ouvert : les extensions ne sont chargées qu'au démarrage.
|
|
|
|
.PARAMETER ExtensionsDir
|
|
Répertoire des extensions Inkscape. Par défaut : %APPDATA%\inkscape\extensions
|
|
|
|
.PARAMETER FolderName
|
|
Nom du sous-dossier de l'extension. Par défaut : GrayIsoLayers
|
|
|
|
.PARAMETER Depth
|
|
Installe aussi de quoi calculer les cartes de profondeur, dans
|
|
%LOCALAPPDATA%\GrayIsoLayers : un environnement Python (onnxruntime-directml,
|
|
numpy, pillow) et les deux modèles (MiDaS small, Depth Anything V2 Small,
|
|
environ 165 Mo à télécharger). Le Python d'Inkscape ne peut pas charger
|
|
onnxruntime : il faut un Python 3 installé sur la machine.
|
|
|
|
.PARAMETER Python
|
|
Python qui crée l'environnement de -Depth. Par défaut : « python » du PATH,
|
|
sinon le lanceur « py ». À indiquer si le Python trouvé est trop récent
|
|
pour onnxruntime.
|
|
|
|
.PARAMETER Uninstall
|
|
Supprime le sous-dossier de l'extension au lieu de le créer, ainsi que
|
|
%LOCALAPPDATA%\GrayIsoLayers (environnement, modèles, cache).
|
|
|
|
.PARAMETER Force
|
|
Déploie même si Inkscape est en cours d'exécution.
|
|
|
|
.EXAMPLE
|
|
.\deploy.ps1
|
|
.\deploy.ps1 -Depth
|
|
.\deploy.ps1 -Uninstall
|
|
.\deploy.ps1 -FolderName 'autre-nom'
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[string] $ExtensionsDir = (Join-Path $env:APPDATA 'inkscape\extensions'),
|
|
[string] $FolderName = 'GrayIsoLayers',
|
|
[switch] $Depth,
|
|
[string] $Python,
|
|
[switch] $Uninstall,
|
|
[switch] $Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$files = @('gray_iso_layers.inx', 'gray_iso_layers.py', 'gray_iso_layers_core.py',
|
|
'gray_iso_layers_depth.py', 'depth_estimate.py', 'images\parameters_en.png')
|
|
$localeDir = 'locale'
|
|
$source = $PSScriptRoot
|
|
$destination = Join-Path $ExtensionsDir $FolderName
|
|
|
|
# Cartes de profondeur : environnement Python, modèles et cache, hors du
|
|
# dossier des extensions (Inkscape le parcourt en entier au démarrage).
|
|
# Mêmes noms que dans gray_iso_layers_depth.py.
|
|
$dataDir = Join-Path $env:LOCALAPPDATA 'GrayIsoLayers'
|
|
$packages = @('onnxruntime-directml', 'numpy', 'pillow')
|
|
$models = [ordered]@{
|
|
'midas_v21_small_256.onnx' = 'https://github.com/isl-org/MiDaS/releases/download/v2_1/model-small.onnx'
|
|
'depth_anything_v2_small.onnx' = 'https://huggingface.co/onnx-community/depth-anything-v2-small/resolve/main/onnx/model.onnx'
|
|
}
|
|
|
|
# --- Inkscape doit être fermé : les extensions sont lues au démarrage ---------
|
|
$running = Get-Process -Name 'inkscape' -ErrorAction SilentlyContinue
|
|
if ($running -and -not $Force) {
|
|
Write-Error "Inkscape est ouvert. Fermez-le puis relancez le script (ou utilisez -Force)."
|
|
exit 1
|
|
}
|
|
|
|
# --- Désinstallation ---------------------------------------------------------
|
|
if ($Uninstall) {
|
|
if (Test-Path -LiteralPath $destination) {
|
|
Remove-Item -LiteralPath $destination -Recurse -Force
|
|
Write-Host "Supprimé : $destination" -ForegroundColor Green
|
|
}
|
|
else {
|
|
Write-Host "Rien à supprimer : $destination n'existe pas." -ForegroundColor Yellow
|
|
}
|
|
if (Test-Path -LiteralPath $dataDir) {
|
|
Remove-Item -LiteralPath $dataDir -Recurse -Force
|
|
Write-Host "Supprimé : $dataDir" -ForegroundColor Green
|
|
}
|
|
exit 0
|
|
}
|
|
|
|
# --- Vérification des sources ------------------------------------------------
|
|
$missing = $files | Where-Object { -not (Test-Path -LiteralPath (Join-Path $source $_)) }
|
|
if (-not (Test-Path -LiteralPath (Join-Path $source $localeDir))) {
|
|
$missing = @($missing) + "$localeDir\ (lancer : python i18n.py)"
|
|
}
|
|
if ($missing) {
|
|
Write-Error "Fichier(s) introuvable(s) dans $source : $($missing -join ', ')"
|
|
exit 1
|
|
}
|
|
|
|
# --- Copie -------------------------------------------------------------------
|
|
if (-not (Test-Path -LiteralPath $destination)) {
|
|
New-Item -ItemType Directory -Path $destination -Force | Out-Null
|
|
Write-Host "Dossier créé : $destination"
|
|
}
|
|
|
|
foreach ($file in $files) {
|
|
$from = Join-Path $source $file
|
|
$to = Join-Path $destination $file
|
|
$action = if (Test-Path -LiteralPath $to) { 'remplacé' } else { 'copié ' }
|
|
New-Item -ItemType Directory -Path (Split-Path $to) -Force | Out-Null
|
|
Copy-Item -LiteralPath $from -Destination $to -Force
|
|
Write-Host " $action $file"
|
|
}
|
|
|
|
# Traductions : le dossier est remplacé en entier (langue retirée => supprimée)
|
|
$localeTo = Join-Path $destination $localeDir
|
|
if (Test-Path -LiteralPath $localeTo) {
|
|
Remove-Item -LiteralPath $localeTo -Recurse -Force
|
|
}
|
|
Copy-Item -LiteralPath (Join-Path $source $localeDir) -Destination $localeTo -Recurse
|
|
$languages = Get-ChildItem -LiteralPath $localeTo -Directory | ForEach-Object Name
|
|
Write-Host " copié $localeDir\ ($($languages -join ', '))"
|
|
|
|
# Le cache Python d'une version précédente peut masquer les fichiers copiés
|
|
$pycache = Join-Path $destination '__pycache__'
|
|
if (Test-Path -LiteralPath $pycache) {
|
|
Remove-Item -LiteralPath $pycache -Recurse -Force
|
|
}
|
|
|
|
# --- Cartes de profondeur ----------------------------------------------------
|
|
if ($Depth) {
|
|
Write-Host ""
|
|
Write-Host "Cartes de profondeur : $dataDir"
|
|
$venvPython = Join-Path $dataDir 'venv\Scripts\python.exe'
|
|
if (-not (Test-Path -LiteralPath $venvPython)) {
|
|
# « python » avant le lanceur « py » : ce dernier prend la version la
|
|
# plus récente, parfois une préversion pour laquelle onnxruntime
|
|
# n'est pas encore publié.
|
|
$command = @()
|
|
if ($Python) {
|
|
$command = @($Python)
|
|
}
|
|
elseif (Get-Command python -ErrorAction SilentlyContinue) {
|
|
$command = @((Get-Command python).Source)
|
|
}
|
|
elseif (Get-Command py -ErrorAction SilentlyContinue) {
|
|
$command = @((Get-Command py).Source, '-3')
|
|
}
|
|
if ($command.Count -eq 0) {
|
|
Write-Error "Aucun Python 3 trouvé (python ou py) : installez-le depuis python.org, ou indiquez-le avec -Python."
|
|
exit 1
|
|
}
|
|
$arguments = @($command | Select-Object -Skip 1) + @('-m', 'venv', (Join-Path $dataDir 'venv'))
|
|
& $command[0] $arguments
|
|
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $venvPython)) {
|
|
Write-Error "Création de l'environnement Python impossible avec $($command -join ' ')."
|
|
exit 1
|
|
}
|
|
Write-Host " créé venv\"
|
|
}
|
|
& $venvPython -m pip install --quiet --disable-pip-version-check --upgrade @packages
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Error "Installation de $($packages -join ', ') impossible."
|
|
exit 1
|
|
}
|
|
Write-Host " installé $($packages -join ', ')"
|
|
|
|
$modelsDir = Join-Path $dataDir 'models'
|
|
New-Item -ItemType Directory -Path $modelsDir -Force | Out-Null
|
|
foreach ($name in $models.Keys) {
|
|
$to = Join-Path $modelsDir $name
|
|
if (Test-Path -LiteralPath $to) {
|
|
Write-Host " présent models\$name"
|
|
continue
|
|
}
|
|
# Téléchargement dans un fichier provisoire : un modèle tronqué par une
|
|
# coupure ne passe pas pour un modèle installé.
|
|
$partial = "$to.part"
|
|
$previous = $ProgressPreference
|
|
$ProgressPreference = 'SilentlyContinue' # la barre ralentit beaucoup PowerShell 5.1
|
|
try {
|
|
Invoke-WebRequest -Uri $models[$name] -OutFile $partial -UseBasicParsing
|
|
}
|
|
finally {
|
|
$ProgressPreference = $previous
|
|
}
|
|
Move-Item -LiteralPath $partial -Destination $to -Force
|
|
$size = [math]::Round((Get-Item -LiteralPath $to).Length / 1MB)
|
|
Write-Host " téléchargé models\$name ($size Mo)"
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Extension déployée dans $destination" -ForegroundColor Green
|
|
Write-Host "Redémarrez Inkscape, puis : Extensions > AlexDesign > Iso-couches par nuances de gris..."
|