Bildfehler, falsch plazierte Arucos

This commit is contained in:
chk
2026-06-02 07:29:14 +02:00
parent 33a70c60c9
commit ac81c2e0cb
45 changed files with 22562 additions and 22063 deletions

View File

@@ -2,6 +2,7 @@ from unicodedata import name
import bpy
import math
import random
import mathutils
import json
from pathlib import Path
@@ -75,7 +76,17 @@ dof_enabled = as_bool(rendering_info.get("dofEnabled", True))
dof_fstop = float(rendering_info.get("dofFStop", 7.5))
aruco_dust = as_bool(rendering_info.get("arucoDust", False))
aruco_dust_strength = float(rendering_info.get("arucoDustStrength", 0.0005))
aruco_dust_strength = float(rendering_info.get("arucoDustStrength", 0.5))
# ── Realismus-Störungen ────────────────────────────────────────────
# Marker leicht "falsch aufgeklebt": tangentiale Verschiebung (mm). Deterministisch
# pro Marker-ID, damit der Marker in ALLEN Kameraansichten konsistent versetzt ist.
marker_offset_max_mm = float(rendering_info.get("markerOffsetMaxMm", 0.0))
marker_offset_seed = int(rendering_info.get("markerOffsetSeed", 0))
marker_rot_max_deg = float(rendering_info.get("markerRotationMaxDeg", 0.0))
# Leichtes Verwackeln: pro Aufnahme zufällig gerichteter, kleiner Blur (Pixel).
motion_blur = as_bool(rendering_info.get("motionBlur", False))
motion_blur_max_px = float(rendering_info.get("motionBlurMaxPx", 1.5))
state: Dict[str, float] = {k: 0.0 for k in STATE_KEYS}
for source_name in ("defaultPosition", "recognized", "movements"):
@@ -698,32 +709,38 @@ for link_name, link_info in links_def.items():
tex.image = image
if aruco_dust:
# Wenige feine Staubkörner: hoch aufgelöstes Noise, hohe Schwelle in der
# Ramp (nur Spitzen -> wenige kleine Punkte), Stärke als echter Faktor.
noise = nodes.new("ShaderNodeTexNoise")
ramp = nodes.new("ShaderNodeValToRGB")
mix = nodes.new("ShaderNodeMixRGB")
ramp = nodes.new("ShaderNodeValToRGB")
mult = nodes.new("ShaderNodeMath")
mix = nodes.new("ShaderNodeMixRGB")
noise.location = (-600, -220)
ramp.location = (-360, -220)
mix.location = (-120, -120)
noise.location = (-700, -220)
ramp.location = (-480, -220)
mult.location = (-280, -220)
mix.location = (-120, -120)
noise.inputs["Scale"].default_value = 80.0
noise.inputs["Detail"].default_value = 1.0
noise.inputs["Scale"].default_value = 220.0 # feine Körnung
noise.inputs["Detail"].default_value = 2.0
ramp.color_ramp.elements[0].position = 0.49
ramp.color_ramp.elements[1].position = 0.51
# nur die obersten ~5-8 % der Noise-Werte werden zu Staub
ramp.color_ramp.elements[0].position = 0.82
ramp.color_ramp.elements[1].position = 0.90
mult.operation = "MULTIPLY"
mult.inputs[1].default_value = max(0.0, min(1.0, aruco_dust_strength))
mix.blend_type = "MIX"
mix.inputs["Fac"].default_value = aruco_dust_strength
mix.inputs["Color2"].default_value = (0.97, 0.97, 0.97, 1.0)
mix.inputs["Color2"].default_value = (0.78, 0.76, 0.72, 1.0) # heller, matter Staub
if aruco_dust:
links.new(tex.outputs["Color"], mix.inputs["Color1"])
links.new(noise.outputs["Fac"], ramp.inputs["Fac"])
links.new(ramp.outputs["Color"], mix.inputs["Fac"])
links.new(ramp.outputs["Color"], mult.inputs[0])
links.new(mult.outputs["Value"], mix.inputs["Fac"])
links.new(mix.outputs["Color"], bsdf.inputs["Base Color"])
else:
links.new(tex.outputs["Color"], bsdf.inputs["Base Color"])
links.new(tex.outputs["Color"], bsdf.inputs["Base Color"])
links.new(bsdf.outputs["BSDF"], out.inputs["Surface"])
@@ -805,9 +822,29 @@ for link_name, link_info in links_def.items():
)
normal_local.normalize()
# Marker "falsch aufgeklebt": deterministische tangentiale Verschiebung
# (gleicher Versatz in allen Kameraansichten -> konsistente Geometrie).
place_offset = mathutils.Vector((0.0, 0.0, 0.0))
if marker_offset_max_mm > 0.0:
rng = random.Random(marker_id + 1000 * marker_offset_seed)
ref = mathutils.Vector((1.0, 0.0, 0.0))
if abs(normal_local.dot(ref)) > 0.9:
ref = mathutils.Vector((0.0, 1.0, 0.0))
u = normal_local.cross(ref).normalized()
v = normal_local.cross(u).normalized()
r_m = mm_to_m(marker_offset_max_mm * math.sqrt(rng.random())) # gleichvert. in Kreisfläche
ang = rng.uniform(0.0, 2.0 * math.pi)
place_offset = u * (r_m * math.cos(ang)) + v * (r_m * math.sin(ang))
if marker_rot_max_deg > 0.0:
d_ang = math.radians(rng.uniform(-marker_rot_max_deg, marker_rot_max_deg))
marker_obj.rotation_quaternion = (
mathutils.Quaternion(normal_local, d_ang) @ marker_obj.rotation_quaternion
)
# minimal vorziehen gegen Z-Fighting (lokaler Versatz)
marker_obj.location = (
mathutils.Vector(marker_pos)
+ place_offset
+ normal_local * mm_to_m(0.5)
)
@@ -1008,6 +1045,28 @@ enable_best_device(scene)
# RENDER
# ============================================================
# ── leichtes Verwackeln: pro Aufnahme zufällig gerichteter kleiner Blur ──
if motion_blur and motion_blur_max_px > 0.0:
scene.use_nodes = True
tree = scene.node_tree
for _n in list(tree.nodes):
tree.nodes.remove(_n)
rl = tree.nodes.new("CompositorNodeRLayers")
blur = tree.nodes.new("CompositorNodeBlur")
comp = tree.nodes.new("CompositorNodeComposite")
blur.filter_type = "GAUSS"
blur.use_relative = False
_ang = random.uniform(0.0, math.pi) # zufällige Verwackel-Richtung
_amp = random.uniform(0.35, 1.0) * motion_blur_max_px
blur.size_x = max(0, int(round(abs(_amp * math.cos(_ang)))))
blur.size_y = max(0, int(round(abs(_amp * math.sin(_ang)))))
rl.location = (-300, 0)
blur.location = (0, 0)
comp.location = (300, 0)
tree.links.new(rl.outputs["Image"], blur.inputs["Image"])
tree.links.new(blur.outputs["Image"], comp.inputs["Image"])
print(f"[render] motion blur size=({blur.size_x},{blur.size_y}) px")
bpy.ops.render.render(write_still=True)
print("Finished rendering:", OUTPUT_FILE)