fix: absolute OUTPUT_DIR, resolution scaling for zones, full reference repo values
This commit is contained in:
1 parent
2b462318ac
commit
35cccd03b3
4 files changed
+39
-10
No files matched your search
@@ -29,7 +29,7 @@ app.config["MAX_CONTENT_LENGTH"] = 2 * 1024 * 1024 * 1024 # 2GB
|
|||||||
|
|
||||||
MODELS_DIR = os.getenv("MODELS_DIR", "./models")
|
MODELS_DIR = os.getenv("MODELS_DIR", "./models")
|
||||||
UPLOAD_DIR = os.getenv("UPLOAD_DIR", "./uploads")
|
UPLOAD_DIR = os.getenv("UPLOAD_DIR", "./uploads")
|
||||||
OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./output")
|
OUTPUT_DIR = os.path.abspath(os.getenv("OUTPUT_DIR", "./output"))
|
||||||
|
|
||||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
|||||||
+15
-8
@@ -22,31 +22,38 @@ def save_zone_config(config: dict[str, Any], path: str) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def build_static_roi(zone: dict[str, Any], video_w: int, video_h: int) -> TruckROI:
|
def build_static_roi(zone: dict[str, Any], video_w: int, video_h: int) -> TruckROI:
|
||||||
"""Build a TruckROI from a zone config dict.
|
"""Build a TruckROI from a zone config dict, scaling from reference resolution.
|
||||||
|
|
||||||
The zone dict should have:
|
The zone dict should have:
|
||||||
- truck_area: [[x1,y1], [x2,y2], [x3,y3], [x4,y4]] (4-point polygon)
|
- truck_area: [[x1,y1], [x2,y2], [x3,y3], [x4,y4]] (4-point polygon)
|
||||||
- count_line: {"x_start": int, "x_end": int, "y": int}
|
- count_line: {"x_start": int, "x_end": int, "y": int}
|
||||||
Coordinates are in the video's native resolution (no scaling needed
|
- reference_resolution: [w, h] (optional, default [1920, 1080])
|
||||||
if the zone was calibrated for this resolution).
|
|
||||||
|
Coordinates are stored at reference_resolution and scaled to actual video_w/video_h.
|
||||||
"""
|
"""
|
||||||
truck_pts = zone.get("truck_area", [])
|
truck_pts = zone.get("truck_area", [])
|
||||||
count_line = zone.get("count_line", {})
|
count_line = zone.get("count_line", {})
|
||||||
|
ref_w, ref_h = zone.get("reference_resolution", [1920, 1080])
|
||||||
|
|
||||||
# Compute bounding box of truck_area polygon
|
# Scale factors from reference resolution to actual video
|
||||||
|
sx = video_w / ref_w if ref_w else 1.0
|
||||||
|
sy = video_h / ref_h if ref_h else 1.0
|
||||||
|
|
||||||
|
# Compute bounding box of truck_area polygon (scaled)
|
||||||
if truck_pts and len(truck_pts) >= 4:
|
if truck_pts and len(truck_pts) >= 4:
|
||||||
xs = [p[0] for p in truck_pts]
|
xs = [int(p[0] * sx) for p in truck_pts]
|
||||||
ys = [p[1] for p in truck_pts]
|
ys = [int(p[1] * sy) for p in truck_pts]
|
||||||
x1 = max(0, min(xs))
|
x1 = max(0, min(xs))
|
||||||
y1 = max(0, min(ys))
|
y1 = max(0, min(ys))
|
||||||
x2 = min(video_w, max(xs))
|
x2 = min(video_w, max(xs))
|
||||||
y2 = min(video_h, max(ys))
|
y2 = min(video_h, max(ys))
|
||||||
else:
|
else:
|
||||||
# Fallback: use 50% of frame
|
|
||||||
x1, y1 = int(video_w * 0.3), int(video_h * 0.1)
|
x1, y1 = int(video_w * 0.3), int(video_h * 0.1)
|
||||||
x2, y2 = int(video_w * 0.75), int(video_h * 0.95)
|
x2, y2 = int(video_w * 0.75), int(video_h * 0.95)
|
||||||
|
|
||||||
line_y = count_line.get("y", int((y1 + y2) / 2))
|
line_y = int(count_line.get("y", (y1 + y2) // 2) * sy)
|
||||||
|
line_x_start = int(count_line.get("x_start", x1) * sx)
|
||||||
|
line_x_end = int(count_line.get("x_end", x2) * sx)
|
||||||
|
|
||||||
return TruckROI(
|
return TruckROI(
|
||||||
x1=x1, y1=y1, x2=x2, y2=y2,
|
x1=x1, y1=y1, x2=x2, y2=y2,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ def test_build_static_roi_from_zone_config():
|
|||||||
zone = {
|
zone = {
|
||||||
"truck_area": [[100, 50], [110, 300], [400, 310], [390, 40]],
|
"truck_area": [[100, 50], [110, 300], [400, 310], [390, 40]],
|
||||||
"count_line": {"x_start": 110, "x_end": 400, "y": 150},
|
"count_line": {"x_start": 110, "x_end": 400, "y": 150},
|
||||||
|
"reference_resolution": [640, 480],
|
||||||
}
|
}
|
||||||
roi = build_static_roi(zone, video_w=640, video_h=480)
|
roi = build_static_roi(zone, video_w=640, video_h=480)
|
||||||
assert roi.line_y == 150
|
assert roi.line_y == 150
|
||||||
@@ -36,6 +37,18 @@ def test_build_static_roi_scales_coords():
|
|||||||
assert roi.x2 == 1404
|
assert roi.x2 == 1404
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_static_roi_scales_from_1080p_to_720p():
|
||||||
|
zone = {
|
||||||
|
"truck_area": [[600, 385], [609, 1076], [1404, 1078], [1381, 343]],
|
||||||
|
"count_line": {"x_start": 577, "x_end": 1401, "y": 330},
|
||||||
|
"reference_resolution": [1920, 1080],
|
||||||
|
}
|
||||||
|
roi = build_static_roi(zone, video_w=1280, video_h=720)
|
||||||
|
assert roi.line_y == int(330 * 720 / 1080)
|
||||||
|
assert roi.x1 == int(600 * 1280 / 1920)
|
||||||
|
assert roi.x2 == int(1404 * 1280 / 1920)
|
||||||
|
|
||||||
|
|
||||||
def test_list_zone_presets(tmp_path):
|
def test_list_zone_presets(tmp_path):
|
||||||
cfg = {"presets": {"p1": {"description": "Zone 1"}, "p2": {"description": "Zone 2"}}}
|
cfg = {"presets": {"p1": {"description": "Zone 1"}, "p2": {"description": "Zone 2"}}}
|
||||||
p = tmp_path / "zones.json"
|
p = tmp_path / "zones.json"
|
||||||
|
|||||||
+10
-1
@@ -3,11 +3,20 @@
|
|||||||
"default": {
|
"default": {
|
||||||
"truck_area": [[600, 385], [609, 1076], [1404, 1078], [1381, 343]],
|
"truck_area": [[600, 385], [609, 1076], [1404, 1078], [1381, 343]],
|
||||||
"counting_area": [[574, 50], [586, 1077], [1418, 1076], [1397, 50]],
|
"counting_area": [[574, 50], [586, 1077], [1418, 1076], [1397, 50]],
|
||||||
|
"palet": [[612, 628], [1454, 630], [1458, 1074], [608, 1071]],
|
||||||
"count_line": {"x_start": 577, "x_end": 1401, "y": 330},
|
"count_line": {"x_start": 577, "x_end": 1401, "y": 330},
|
||||||
|
"reference_resolution": [1920, 1080],
|
||||||
"left_limit": 0.27578,
|
"left_limit": 0.27578,
|
||||||
"right_limit": 0.72578,
|
"right_limit": 0.72578,
|
||||||
"duplicate_circle_radius": 30,
|
"duplicate_circle_radius": 30,
|
||||||
"description": "Default zone for 1920x1080 camera"
|
"min_valid_area": 15000,
|
||||||
|
"jarak_toleransi_duplikat": 30,
|
||||||
|
"max_reid_transit_distance": 400,
|
||||||
|
"circle_stay_timeout_sec": 10.0,
|
||||||
|
"inference_stride": 2,
|
||||||
|
"confirm_delay_sec": 0.5,
|
||||||
|
"exit_confirm_delay_sec": 6.0,
|
||||||
|
"description": "Default zone from karung-counting-feedmill-semarang (1920x1080 native)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active_preset": "default"
|
"active_preset": "default"
|
||||||
|
|||||||
Reference in new issue
Block a user