Lidar_Muxa/tools/viz_object.py

100 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Крупный план участка дальностного образа вокруг заданной точки пространства.
Нужен, чтобы понять, как реальный объект выглядит в ретинотопической решётке:
размер в лучах, контраст по дальности, окклюзионная тень за ним.
python tools/viz_object.py --bag data/for_hackathon/doubleT_obstacle \
--frame 40 --dist 55 --lat -0.8
"""
from __future__ import annotations
import argparse
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt # noqa: E402
import numpy as np # noqa: E402
import _bootstrap as B # noqa: F401,E402
from flyguard.bag import Bag # noqa: E402
from flyguard.retina import ScanLayout # noqa: E402
def main() -> None:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("--bag", required=True)
ap.add_argument("--frame", type=int, default=40)
ap.add_argument("--dist", type=float, required=True, help="расстояние вперёд, м")
ap.add_argument("--lat", type=float, default=0.0, help="смещение поперёк, м")
ap.add_argument("--pad-az", type=float, default=4.0, help="окно по азимуту, °")
ap.add_argument("--pad-el", type=float, default=4.0, help="окно по элевации, °")
args = ap.parse_args()
bag = Bag(args.bag)
layout = ScanLayout.calibrate([pc for _, pc in bag.frames(start=2, stop=14)])
_, pc = next(bag.frames(start=args.frame, stop=args.frame + 1))
img = layout.project(pc)
az_c = np.degrees(np.arctan2(args.lat, args.dist))
el_c = 0.0
ja = np.flatnonzero(np.abs(layout.az_grid_deg - az_c) <= args.pad_az)
ie = np.flatnonzero(np.abs(layout.el_deg - el_c) <= args.pad_el)
js, je = slice(ja[0], ja[-1] + 1), slice(ie[0], ie[-1] + 1)
r = np.where(img.valid, img.r_near, np.nan)[je, js]
it = np.where(img.valid, img.inten, np.nan)[je, js]
gap = np.where(img.valid, img.r_far - img.r_near, np.nan)[je, js]
az = layout.az_grid_deg[js]
el = layout.el_deg[je]
ext = [az[0], az[-1], el[-1], el[0]]
print(f"окно: азимут {az.min():.2f}…{az.max():.2f}° ({az.size} стлб), "
f"элевация {el.min():.2f}…{el.max():.2f}° ({el.size} колец)")
band = r[np.isfinite(r)]
print(f"дальности в окне: p5={np.percentile(band, 5):.1f} p50={np.percentile(band, 50):.1f} "
f"p95={np.percentile(band, 95):.1f} max={band.max():.1f}")
near = np.isfinite(r) & (np.abs(r - args.dist) < 5)
print(f"лучей на дистанции {args.dist}±5 м: {near.sum()}, "
f"доля окна {near.mean():.1%}")
print(f"пустых лучей в окне: {np.mean(~np.isfinite(r)):.1%}")
fig, axes = plt.subplots(2, 2, figsize=(15, 9), dpi=110)
fig.suptitle(f"{bag.path.name} кадр {args.frame}: окрестность точки "
f"({args.dist:.0f} м вперёд, {args.lat:+.1f} м поперёк)")
ax = axes[0, 0]
im = ax.imshow(r, extent=ext, aspect="auto", cmap="turbo", interpolation="nearest")
ax.set_title("дальность, м"); fig.colorbar(im, ax=ax, fraction=0.04)
ax = axes[0, 1]
lo, hi = np.nanpercentile(r, [2, 98])
im = ax.imshow(r, extent=ext, aspect="auto", cmap="turbo", vmin=lo, vmax=hi,
interpolation="nearest")
ax.set_title(f"дальность, растянутая шкала {lo:.0f}…{hi:.0f} м")
fig.colorbar(im, ax=ax, fraction=0.04)
ax = axes[1, 0]
im = ax.imshow(it, extent=ext, aspect="auto", cmap="magma", interpolation="nearest")
ax.set_title("интенсивность"); fig.colorbar(im, ax=ax, fraction=0.04)
ax = axes[1, 1]
im = ax.imshow(gap, extent=ext, aspect="auto", cmap="cividis", vmin=0, vmax=10,
interpolation="nearest")
ax.set_title("разнос эх (дальнее − ближнее), м")
fig.colorbar(im, ax=ax, fraction=0.04)
for ax in axes.ravel():
ax.set_xlabel("азимут, °"); ax.set_ylabel("элевация, °")
ax.invert_xaxis()
ax.axvline(az_c, color="w", lw=0.6, ls=":")
ax.axhline(el_c, color="w", lw=0.6, ls=":")
B.FIGURES.mkdir(parents=True, exist_ok=True)
out = B.FIGURES / f"object_{bag.path.name}_{args.frame:04d}_{int(args.dist)}m.png"
fig.tight_layout(rect=(0, 0, 1, 0.95))
fig.savefig(out)
print("сохранено:", out)
if __name__ == "__main__":
main()