From 5a1d3ea977a11c0ddedcd6004b0a56bc9cf2074a Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Thu, 21 May 2026 16:05:47 +0800 Subject: [PATCH] refactor(verification): extract shared text_labels cell and hash codec - Move inline _text_labels lists into a shared text_labels cell - Replace inline np.packbits hash encoding with bits_tensor_to_hash_bytes - Add static tests to verify notebook API usage patterns --- notebooks/verification.py | 56 +++++++++++----------- tests/test_notebook_verification_static.py | 20 ++++++++ 2 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 tests/test_notebook_verification_static.py diff --git a/notebooks/verification.py b/notebooks/verification.py index 0fef577..98ec317 100644 --- a/notebooks/verification.py +++ b/notebooks/verification.py @@ -39,6 +39,7 @@ def project_imports(): ObjectNode, RoomNode, SimpleSceneGraph, + bits_tensor_to_hash_bytes, query_image_against_scene_graph, ) from simulator import ( @@ -59,6 +60,7 @@ def project_imports(): RoomNode, SimpleSceneGraph, TopDownSceneElements, + bits_tensor_to_hash_bytes, cfg_manager, collect_room_views_by_room, create_habitat_simulator, @@ -70,6 +72,24 @@ def project_imports(): ) +@app.cell +def text_labels(): + """Shared text labels for detection during graph build and query.""" + text_labels = [ + "a chair", + "a table", + "a sofa", + "a cabinet", + "a shelf", + "a lamp", + "a picture", + "a window", + "a door", + "a plant", + ] + return (text_labels,) + + @app.cell def habitat_setup(HabitatSimulatorConfig, RoomNode, create_habitat_simulator, np): """Initialize Habitat simulator and sample room nodes.""" @@ -170,6 +190,7 @@ def collect_views( def build_scene_graph( ObjectNode, SimpleSceneGraph, + bits_tensor_to_hash_bytes, cfg_manager, mo, np, @@ -178,6 +199,7 @@ def build_scene_graph( room_view_dataset, save_object_image, save_room_view, + text_labels, torch, ): scene_graph = SimpleSceneGraph( @@ -194,18 +216,6 @@ def build_scene_graph( _images = [item[2] for item in room_view_dataset] _metadata = [(item[0], item[1]) for item in room_view_dataset] - _text_labels = [ - "a chair", - "a table", - "a sofa", - "a cabinet", - "a shelf", - "a lamp", - "a picture", - "a window", - "a door", - "a plant", - ] inference_batch_size = 4 image_batches = [ _images[index : index + inference_batch_size] @@ -229,7 +239,7 @@ def build_scene_graph( ): _batch_output = pipeline.process_batch( _batch_images, - _text_labels, + text_labels, batch_size=inference_batch_size, return_debug_details=True, ) @@ -296,9 +306,7 @@ def build_scene_graph( _obj_id = f"{_room_id}_v{_view_idx:03d}_m{_mask_idx:02d}" - _bits_array = _hash_bits.detach().cpu().numpy().reshape(-1) - _bits_binary = (_bits_array > 0).astype(np.uint8) - _hash_bytes = np.packbits(_bits_binary).tobytes() + _hash_bytes = bits_tensor_to_hash_bytes(_hash_bits) object_images[_obj_id] = _cropped save_object_image(output_dir, _room_id, _obj_id, _view_idx, _mask_idx, _cropped) @@ -372,6 +380,7 @@ def query_matching( pipeline, query_image_against_scene_graph, scene_graph, + text_labels, ): from io import BytesIO @@ -384,23 +393,11 @@ def query_matching( _query_image = Image.open(BytesIO(_file_contents)).convert("RGB") - _text_labels = [ - "a chair", - "a table", - "a sofa", - "a cabinet", - "a shelf", - "a lamp", - "a picture", - "a window", - "a door", - "a plant", - ] _query_results = query_image_against_scene_graph( image=_query_image, pipeline=pipeline, scene_graph=scene_graph, - text_labels=_text_labels, + text_labels=text_labels, top_k=5, batch_size=1, ) @@ -425,6 +422,7 @@ def query_matching( "query_cropped": query_cropped, "query_hash_hex": _best_result.query_hash.hex(), "top_matches": top_matches, + "num_query_results": len(_query_results), } return query_cropped, query_result, top_matches diff --git a/tests/test_notebook_verification_static.py b/tests/test_notebook_verification_static.py new file mode 100644 index 0000000..ddfa7f4 --- /dev/null +++ b/tests/test_notebook_verification_static.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from pathlib import Path + + +NOTEBOOK = Path(__file__).resolve().parents[1] / "notebooks" / "verification.py" + + +def test_verification_notebook_uses_scenegraph_query_api(): + source = NOTEBOOK.read_text() + + assert "query_image_against_scene_graph" in source + assert "text_labels=text_labels" in source + + +def test_verification_notebook_uses_hash_codec_for_object_hashes(): + source = NOTEBOOK.read_text() + + assert "bits_tensor_to_hash_bytes" in source + assert "np.packbits" not in source