Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ The detector also has a **SocketIO** upload endpoint that can be used to upload
- `metadata`: a dictionary representing the image metadata. If metadata contains detections and/or annotations, UUIDs for the classes are automatically determined based on the category names. Metadata should follow the schema of the `ImageMetadata` data class.
- `upload_priority`: Optional boolean flag to prioritize the upload (defaults to False)

The endpoint returns None if the upload was successful and an error message otherwise.
The endpoint returns `{'status': 'OK'}` if the upload was successful and `{'error': '<message>'}` otherwise.

Besides detections and annotations, the metadata may carry `tags`, `source`, `created` and `state`.
`state` names the state the image should enter the loop in (e.g. `trash`); when it is omitted the loop applies its own default (`inbox`).

For both ways to upload an image, the tag `picked_by_system` is automatically added to the image metadata.

Expand Down
2 changes: 2 additions & 0 deletions learning_loop_node/data_classes/image_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class ImageMetadata():
'description': 'Creation date of the image'})
source: Optional[str] = field(default=None, metadata={
'description': 'Source of the image'})
state: str | None = field(default=None, metadata={
'description': 'State the image should enter the loop in (e.g. "trash"); None uses the loop default'})
Comment thread
HannesDeittert marked this conversation as resolved.

def __len__(self):
return len(self.box_detections) + len(self.point_detections) + len(self.segmentation_detections) + len(self.classification_detections)
Expand Down
4 changes: 3 additions & 1 deletion learning_loop_node/detector/detector_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,9 @@ async def upload(sid, data: Dict) -> Dict:
- bytes: bytes of the ndarray (retrieved via `ndarray.tobytes(order='C')`)
- dtype: data type of the ndarray as string (e.g. `uint8`, `float32`, etc.)
- shape: shape of the ndarray as tuple of ints (e.g. `(480, 640, 3)`)
- metadata: The metadata for the image (optional)
- metadata: The metadata for the image (optional). Besides detections and annotations it
may carry `tags`, `source`, `created` and `state`. A `state` of e.g. "trash" makes the
loop file the image into that state instead of its default one.
- upload_priority: Whether to upload with priority (optional)
"""
self.log.debug('Processing upload via socketio.')
Expand Down
17 changes: 17 additions & 0 deletions learning_loop_node/tests/detector/test_client_communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ async def test_sio_upload(test_detector_node: DetectorNode, sio_client):
assert len(get_outbox_files(test_detector_node.outbox)) == 2, 'There should be one image and one .json file.'


async def test_sio_upload_with_state(test_detector_node: DetectorNode, sio_client):
"""The state from the metadata has to reach the json file the outbox uploads to the loop."""
assert len(get_outbox_files(test_detector_node.outbox)) == 0

image = np.array(Image.open(test_image_path))
result = await sio_client.call('upload', {
'image': {'bytes': image.tobytes(), 'shape': image.shape, 'dtype': str(image.dtype)},
'metadata': {'state': 'trash'},
})
assert result.get('status') == 'OK'

json_files = [file for file in get_outbox_files(test_detector_node.outbox) if file.endswith('.json')]
assert len(json_files) == 1
with open(json_files[0]) as f:
assert json.load(f)['state'] == 'trash'


# NOTE: This test seems to be flaky.
async def test_about_endpoint(test_detector_node: DetectorNode):
await asyncio.sleep(16)
Expand Down
Loading