pipeline/axo : extraction du Rhino, recalage sur la planche (1:640), maisons, arbres (positions réelles des blocs, couleurs de la planche), scène en mètres, sols depuis le PDF Illustrator vectoriel (calques pilotés), bulles de la page 15, planche de l'eau nettoyée. prototypes/axo-test : la page de test et son assembleur. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
3.2 KiB
Python
40 lines
3.2 KiB
Python
"""08 — La planche du réseau hydrique alternatif, nettoyée de ses textes, pour le zoom « cycle de l'eau ».
|
|
|
|
Source : le PDF d'impression du concours Habiter Demain 2020 (page 6, dessins à 417 dpi),
|
|
identique au pixel près à la page 13 de la présentation TMIP 2024 (décalage mesuré : 0).
|
|
Les blocs de texte sont effacés : en dégradé dans la bande haute (le fond y passe du blanc au crème),
|
|
en aplat clair ailleurs. Les numéros d'étape deviennent des points actifs de la page web.
|
|
Si Jules fournit les originaux sans texte, remplacer cette étape par eux.
|
|
|
|
Usage : python 08_planche_eau.py <concours_IMPRESSION.pdf>
|
|
Sorties : eau_crop.jpg (2422 x 1290), eau_crop.json (points actifs et trajets, repère 100 dpi recadré)
|
|
"""
|
|
import sys, json, subprocess
|
|
import numpy as np
|
|
from PIL import Image
|
|
from scipy.ndimage import median_filter
|
|
|
|
subprocess.run(["pdftoppm", "-f", "6", "-l", "6", "-r", "150", "-png", sys.argv[1], "c6_150"], check=True)
|
|
im = np.asarray(Image.open("c6_150-06.png").convert("RGB")).astype(np.float32); k = 1.5
|
|
haut = [(55,28,1210,118),(85,443,305,543),(205,452,640,462),(632,452,642,532),(950,430,1113,572),(1118,428,1342,567)]
|
|
bas = [(958,568,968,652),(958,645,1182,655),(1226,560,1236,640),(78,722,248,818),(222,724,325,736),(88,925,282,1098),(230,932,495,944),
|
|
(578,936,752,952),(578,954,803,1118),(897,938,995,952),(915,954,1098,1118),(751,896,763,936),(915,905,926,938),
|
|
(1438,493,1620,752),(1410,657,1442,667),(1445,745,1622,962),(1355,752,1450,762),(1445,980,1615,1078),(1275,868,1462,878),(1453,868,1463,992),
|
|
(1158,978,1372,1090),(1165,948,1175,986),(480,1112,1220,1152),(1520,1100,1615,1145)]
|
|
for x0, y0, x1, y1 in haut:
|
|
X0, Y0, X1, Y1 = int(x0 * k), int(y0 * k), int(x1 * k), int(y1 * k)
|
|
h = median_filter(np.median(im[max(0, Y0 - 5):Y0, X0:X1], axis=0), size=(41, 1))
|
|
b = median_filter(np.median(im[Y1:Y1 + 5, X0:X1], axis=0), size=(41, 1))
|
|
t = np.linspace(0, 1, Y1 - Y0)[:, None, None]; im[Y0:Y1, X0:X1] = h[None] * (1 - t) + b[None] * t
|
|
for x0, y0, x1, y1 in bas:
|
|
X0, Y0, X1, Y1 = int(x0 * k), int(y0 * k), int(x1 * k), int(y1 * k)
|
|
a = np.concatenate([im[max(0, Y0 - 8):Y0, X0:X1].reshape(-1, 3), im[Y1:Y1 + 8, X0:X1].reshape(-1, 3), im[Y0:Y1, max(0, X0 - 8):X0].reshape(-1, 3), im[Y0:Y1, X1:X1 + 8].reshape(-1, 3)])
|
|
clair = a[a.mean(1) > 228]; im[Y0:Y1, X0:X1] = np.median(clair if len(clair) > 20 else a, axis=0)
|
|
Image.fromarray(np.clip(im, 0, 255).astype(np.uint8)).crop((30, 195, 2452, 1485)).save("eau_crop.jpg", quality=78, optimize=True, progressive=True)
|
|
pts = {"h1": (430, 790), "h2": (610, 850), "h3": (637, 612), "h4": (840, 660), "h5": (855, 800), "h6": (1130, 700), "h7": (1215, 790), "h8": (1378, 625),
|
|
"h9": (1320, 780), "h10": (1255, 880), "h11": (1105, 875), "h1b": (630, 300), "h5b": (1025, 372)}
|
|
flux = {"usees": [(592,822),(640,872),(700,925),(760,948),(830,950),(885,935),(940,895),(1000,850),(1050,805),(1090,765)], "pluie": [(585,748),(630,750),(690,758)]}
|
|
off = (20, 130)
|
|
json.dump({"W": 1615, "H": 860, "pts": {n: [x - off[0], y - off[1]] for n, (x, y) in pts.items()}, "flux": {n: [[x - off[0], y - off[1]] for x, y in l] for n, l in flux.items()}}, open("eau_crop.json", "w"))
|
|
print("planche de l'eau écrite")
|