Skip to content

Fix ImportError by implementing get_zones_for_point and Zone class fo…#83

Open
dyutishmaan-das wants to merge 4 commits into
Devnil434:mainfrom
dyutishmaan-das:fix/detection-zone-import
Open

Fix ImportError by implementing get_zones_for_point and Zone class fo…#83
dyutishmaan-das wants to merge 4 commits into
Devnil434:mainfrom
dyutishmaan-das:fix/detection-zone-import

Conversation

@dyutishmaan-das
Copy link
Copy Markdown

@dyutishmaan-das dyutishmaan-das commented May 17, 2026

Description

This PR fixes the ImportError crash that occurs when running make demo or detection.py.

The detection service was failing because it relied on DEFAULT_ZONES and get_zones_for_point(), which were removed during the recent migration to the YAML-based ZoneConfigLoader.

Changes Made

  • Created a Zone class in zones.py to wrap the raw YAML dictionaries, providing the .name and .as_array() attributes expected by downstream code.
  • Implemented get_zones_for_point(x, y) using cv2.pointPolygonTest to accurately determine which zone a detected object is in.
  • Added the missing center and zones_present fields to the Pydantic DetectionSchema.
  • Fixed the missing SceneGraphBuilder and build_reasoning_prompt imports in detection.py.
  • Fixed a bug where BoundingBox was instantiated as a list instead of a Pydantic object.

Fixes #81


GSSoC 2026 Contribution

Summary by CodeRabbit

  • New Features

    • Detection output now includes center point coordinates and a list of zones present for each detection.
  • Refactor

    • Zone handling converted to validated zone objects with improved point-in-zone detection.
    • Detections now use structured bounding boxes, improving drawing accuracy and geometry handling.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a Zone wrapper with point-in-polygon queries, extends DetectionSchema with center and zones_present, and updates the detection service to use BoundingBox objects and runtime zone queries in detection and rendering.

Changes

Zone Geometry and Detection Integration

Layer / File(s) Summary
Zone class and point-in-polygon query
services/detection/zones.py
Zone class normalizes YAML zone data into integer polygons and OpenCV-ready colors; get_zones() returns list[Zone]; new get_zones_for_point(x,y, zones=...) uses cv2.pointPolygonTest to find zones containing a point.
Detection schema fields and import updates
libs/schemas/detection.py, services/detection/detection.py (imports)
DetectionSchema gains center: tuple[float,float] and zones_present: list[str]. Detection module imports BoundingBox, get_zones, get_zones_for_point, and reasoning utilities used by the CLI.
Detection runtime: BoundingBox construction and rendering
services/detection/detection.py (implementation)
Detector.detect sets active_zones = get_zones(), queries get_zones_for_point(...) per detection, and constructs detections with bbox=BoundingBox(x1,y1,x2,y2) and center; draw_detections uses active_zones, skips invalid zones, and reads bbox fields via det.bbox.x1/y1/x2/y2.

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Detector
  participant ZoneService
  participant Renderer
  participant SceneGraphBuilder
  CLI->>Detector: start frame loop
  Detector->>ZoneService: get_zones()
  ZoneService-->>Detector: active_zones
  Detector->>ZoneService: get_zones_for_point(cx,cy, zones=active_zones)
  ZoneService-->>Detector: zones_present
  Detector->>SceneGraphBuilder: add detection + zones
  SceneGraphBuilder-->>CLI: serialized reasoning graph (every 30 frames)
  Detector->>Renderer: draw_detections(detections, active_zones)
  Renderer->>ZoneService: get_zones()
  Renderer->>Renderer: render boxes using det.bbox.x1/y1/x2/y2 and zone.color_bgr
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through polygons, points in tow,
Mapped centers, boxes, and zones that show,
Colors flipped to BGR with gentle art,
Detections now know every zone and heart,
The demo hums — a tidy rabbit’s glow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly references the main implementation added: 'get_zones_for_point and Zone class', which are the core missing components restored in this PR to fix the ImportError.
Linked Issues check ✅ Passed All coding objectives from issue #81 are met: get_zones_for_point implemented [zones.py], Zone class with .name and .as_array() added [zones.py], DetectionSchema fields updated [detection.py], BoundingBox instantiation fixed [detection.py], and missing imports restored [detection.py].
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the ImportError and enabling the detection demo: Zone/get_zones_for_point in zones.py, DetectionSchema updates, and detection.py imports/logic align with issue #81 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
services/detection/zones.py (1)

56-67: ⚡ Quick win

Avoid rebuilding all zones on every point query in the hot path.

get_zones_for_point calls get_zones() each invocation, which reallocates Zone objects repeatedly during per-detection processing. Accept an optional preloaded zone list (or prefetch once per frame) to reduce allocation and loader churn.

Proposed refactor
-def get_zones_for_point(x: float, y: float) -> list[Zone]:
+def get_zones_for_point(x: float, y: float, zones: list[Zone] | None = None) -> list[Zone]:
@@
-    for z in get_zones():
+    for z in (zones if zones is not None else get_zones()):
         pts = z.as_array()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/detection/zones.py` around lines 56 - 67, get_zones_for_point
currently calls get_zones() on every invocation causing repeated Zone
allocations; change the function signature (get_zones_for_point) to accept an
optional preloaded list parameter (e.g., zones: list[Zone] | None = None), then
inside the function use the provided zones if not None else call get_zones();
keep the existing filtering logic (check pts length and cv2.pointPolygonTest)
and update hot-path callers to pass a per-frame preloaded zones list to avoid
rebuilding Zones each detection.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/detection/detection.py`:
- Line 23: The code currently imports and uses the snapshot DEFAULT_ZONES for
rendering, which can drift from live membership; update rendering and any uses
of zones_present/overlays to call get_zones_for_point(...) or otherwise fetch
the live zones instead of referencing DEFAULT_ZONES. Locate references to
DEFAULT_ZONES in services/detection/detection.py (and any functions that compute
zones_present or draw overlays) and replace them so they query
get_zones_for_point(point) at render time, ensuring overlays and zones_present
use up-to-date zone data after config reloads.

In `@services/detection/zones.py`:
- Around line 24-37: The Zone constructor currently trusts data["polygon"] and
can crash later; update the Zone __init__ to validate and coerce polygon points:
iterate over data.get("polygon", []), accept only iterable points of length >=2,
coerce each coordinate to int (or drop the point on failure), and only keep
points with exactly two numeric ints; if fewer than 3 valid points, set
self.polygon = [] and set a flag like self.valid = False (True otherwise) and
ensure self.color_bgr is still computed as before; also make as_array() return
an empty np.ndarray when self.polygon is empty to avoid OpenCV errors.

---

Nitpick comments:
In `@services/detection/zones.py`:
- Around line 56-67: get_zones_for_point currently calls get_zones() on every
invocation causing repeated Zone allocations; change the function signature
(get_zones_for_point) to accept an optional preloaded list parameter (e.g.,
zones: list[Zone] | None = None), then inside the function use the provided
zones if not None else call get_zones(); keep the existing filtering logic
(check pts length and cv2.pointPolygonTest) and update hot-path callers to pass
a per-frame preloaded zones list to avoid rebuilding Zones each detection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91c9ba42-4930-4881-9c40-c0ffae24c274

📥 Commits

Reviewing files that changed from the base of the PR and between 4616ca6 and 9ccbcd8.

📒 Files selected for processing (3)
  • libs/schemas/detection.py
  • services/detection/detection.py
  • services/detection/zones.py

Comment thread services/detection/detection.py Outdated
Comment thread services/detection/zones.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
services/detection/zones.py (1)

27-43: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard nullable YAML fields before iterating or stripping.

polygon: null still raises on Line 27, and color_hex: null still raises before the fallback on Line 36. Both cases can break module import instead of degrading to an invalid/defaulted zone.

Proposed fix
-        for point in data.get("polygon", []):
+        for point in data.get("polygon") or []:
             if isinstance(point, (list, tuple)) and len(point) == 2:
                 try:
                     self.polygon.append([int(point[0]), int(point[1])])
                 except (ValueError, TypeError):
                     pass
         self.valid = len(self.polygon) >= 3
         
         # Convert hex color to BGR for OpenCV
-        hex_color = data.get("color_hex", "`#FF0000`").lstrip("#")
+        hex_color = str(data.get("color_hex") or "`#FF0000`").lstrip("#")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/detection/zones.py` around lines 27 - 43, Guard against explicit
nulls in YAML by treating None as missing: when iterating polygon use a
falsy-coalesce (e.g., for point in (data.get("polygon") or [])) so None doesn't
get iterated, and when reading color_hex check/coerce before calling lstrip
(e.g., hex_src = data.get("color_hex") or "`#FF0000`" and only call
hex_src.lstrip("#") or ensure isinstance(hex_src, str)); update the code that
sets self.polygon, self.valid, hex_color, and self.color_bgr accordingly so null
polygon/color_hex degrade to the empty polygon/default color fallback instead of
raising.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@services/detection/zones.py`:
- Around line 27-43: Guard against explicit nulls in YAML by treating None as
missing: when iterating polygon use a falsy-coalesce (e.g., for point in
(data.get("polygon") or [])) so None doesn't get iterated, and when reading
color_hex check/coerce before calling lstrip (e.g., hex_src =
data.get("color_hex") or "`#FF0000`" and only call hex_src.lstrip("#") or ensure
isinstance(hex_src, str)); update the code that sets self.polygon, self.valid,
hex_color, and self.color_bgr accordingly so null polygon/color_hex degrade to
the empty polygon/default color fallback instead of raising.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 18ce928d-c709-4fcd-86a5-034d70421444

📥 Commits

Reviewing files that changed from the base of the PR and between 9ccbcd8 and ee9f3a5.

📒 Files selected for processing (2)
  • services/detection/detection.py
  • services/detection/zones.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/detection/detection.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: ImportError get_zones_for_point missing in detection.py

2 participants