gengxin
This commit is contained in:
1 parent
60d973fd25
commit
33d87ac9d9
1 file changed
+42
-16
+42
-16
@@ -63,7 +63,10 @@ def camera_ptz() -> dict[str, int]:
|
||||
|
||||
def remove_session_snapshots(paths: set[str]) -> None:
|
||||
for path in sorted(paths):
|
||||
if not path.startswith("/smart-cam/data/scan/calibration/"):
|
||||
if not path.startswith((
|
||||
"/smart-cam/data/scan/manual/",
|
||||
"/smart-cam/data/scan/calibration/",
|
||||
)):
|
||||
continue
|
||||
subprocess.run(
|
||||
["docker", "exec", "smart-cam", "rm", "-f", "--", path],
|
||||
@@ -109,20 +112,31 @@ def choose_direction(axis: str, origin: dict[str, int], points: dict) -> int:
|
||||
return 1 if high - origin["tilt"] >= origin["tilt"] - low else -1
|
||||
|
||||
|
||||
def consistent_samples(reliable: list[tuple[int, float, float, dict]]) -> list:
|
||||
"""Return the largest group that estimates one mutually consistent FOV."""
|
||||
def consistent_samples(reliable: list[tuple[int, float, float, dict]],
|
||||
maximum_spread: float = 0.15) -> list:
|
||||
"""Return the largest group with a bounded end-to-end FOV spread.
|
||||
|
||||
The previous seed-radius clustering allowed one sample at -12% and
|
||||
another at +12% into the same cluster. That cluster could therefore have
|
||||
nearly 24% end-to-end spread and was immediately rejected by the later
|
||||
15% check. Use sorted contiguous windows so membership and validation
|
||||
apply the same definition of consistency.
|
||||
"""
|
||||
if not reliable:
|
||||
return []
|
||||
clusters = [
|
||||
[
|
||||
sample for sample in reliable
|
||||
if abs(sample[2] - seed[2]) / max(seed[2], 1.0) <= 0.12
|
||||
]
|
||||
for seed in reliable
|
||||
]
|
||||
return max(
|
||||
clusters, key=lambda cluster: (len(cluster), -max(x[2] for x in cluster))
|
||||
)
|
||||
ordered = sorted(reliable, key=lambda sample: sample[2])
|
||||
candidates = []
|
||||
for begin in range(len(ordered)):
|
||||
for end in range(begin, len(ordered)):
|
||||
window = ordered[begin:end + 1]
|
||||
_, spread = fov_statistics(window)
|
||||
if spread <= maximum_spread:
|
||||
candidates.append(window)
|
||||
return max(candidates, key=lambda group: (
|
||||
len(group),
|
||||
-fov_statistics(group)[1],
|
||||
sum(int(sample[3].get("inliers") or 0) for sample in group),
|
||||
))
|
||||
|
||||
|
||||
def fov_statistics(samples: list[tuple[int, float, float, dict]]) -> tuple[float, float]:
|
||||
@@ -321,8 +335,17 @@ def estimate_axis(axis: str, origin: dict[str, int], points: dict,
|
||||
result.get("match_method") == "phase_correlation"
|
||||
and float(result.get("phase_response") or 0) >= core.PHASE_MIN_RESPONSE
|
||||
)
|
||||
if (feature_reliable or phase_reliable) and 0.08 <= overlap <= 0.80:
|
||||
reliable.append((delta, overlap, delta / (1.0 - overlap), result))
|
||||
if (feature_reliable or phase_reliable) and 0.08 <= overlap <= 0.90:
|
||||
# Hikvision absolute PTZ movement is quantized and can also have
|
||||
# backlash. At high optical zoom, using the requested delta
|
||||
# instead of the SDK-reported actual movement creates a large,
|
||||
# systematic FOV error. Shortfall samples have already been
|
||||
# rejected above, so the actual movement is authoritative here.
|
||||
actual_delta = int(result.get("actual_axis_motion") or delta)
|
||||
reliable.append((
|
||||
actual_delta, overlap,
|
||||
actual_delta / (1.0 - overlap), result,
|
||||
))
|
||||
if len(reliable) >= 4:
|
||||
provisional = consistent_samples(reliable)
|
||||
if len(provisional) >= 4:
|
||||
@@ -372,7 +395,10 @@ def estimate_axis(axis: str, origin: dict[str, int], points: dict,
|
||||
for sample in consistent
|
||||
)
|
||||
allowed_spread = 0.08
|
||||
if not strong_pair:
|
||||
# Two independently measured FOVs that agree within 5% are already a
|
||||
# strong geometric cross-check. Do not reject such a pair merely
|
||||
# because a natural scene supplied 74 rather than 100 ORB inliers.
|
||||
if not strong_pair and spread > 0.05:
|
||||
core.move(origin)
|
||||
core.fail(
|
||||
f"{axis}方向目前只有2个一致样本,但特征质量不足以使用双样本规则;"
|
||||
|
||||
Reference in new issue
Block a user