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
9 changes: 1 addition & 8 deletions src/viam/components/camera/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,7 @@ async def get_image(
...

@abc.abstractmethod
async def get_images(
self,
*,
filter_source_names: Optional[List[str]] = None,
extra: Optional[Dict[str, Any]] = None,
timeout: Optional[float] = None,
**kwargs,
) -> Tuple[List[NamedImage], ResponseMetadata]:
async def get_images(self, *, timeout: Optional[float] = None, **kwargs) -> Tuple[List[NamedImage], ResponseMetadata]:
"""Get simultaneous images from different imagers, along with associated metadata.
This should not be used for getting a time series of images from the same imager.

Expand Down
12 changes: 3 additions & 9 deletions src/viam/components/camera/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,20 @@ async def get_image(
md = kwargs.get("metadata", self.Metadata()).proto
request = GetImageRequest(name=self.name, mime_type=mime_type, extra=dict_to_struct(extra))
response: GetImageResponse = await self.client.GetImage(request, timeout=timeout, metadata=md)
return ViamImage(response.image, response.mime_type)
return ViamImage(response.image, CameraMimeType.from_string(response.mime_type))

async def get_images(
self,
*,
filter_source_names: Optional[List[str]] = None,
extra: Optional[Dict[str, Any]] = None,
timeout: Optional[float] = None,
**kwargs,
) -> Tuple[List[NamedImage], ResponseMetadata]:
md = kwargs.get("metadata", self.Metadata()).proto
request = GetImagesRequest(name=self.name, extra=dict_to_struct(extra), filter_source_names=filter_source_names)
request = GetImagesRequest(name=self.name)
response: GetImagesResponse = await self.client.GetImages(request, timeout=timeout, metadata=md)
imgs = []
for img_data in response.images:
if img_data.mime_type:
mime_type = img_data.mime_type
else:
# TODO(RSDK-11728): remove this once we deleted the format field
mime_type = str(CameraMimeType.from_proto(img_data.format))
mime_type = CameraMimeType.from_proto(img_data.format)
img = NamedImage(img_data.source_name, img_data.image, mime_type)
imgs.append(img)
resp_metadata: ResponseMetadata = response.response_metadata
Expand Down
19 changes: 3 additions & 16 deletions src/viam/components/camera/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
from google.api.httpbody_pb2 import HttpBody # type: ignore
from grpclib.server import Stream

from viam.media.video import CameraMimeType
from viam.proto.common import DoCommandRequest, DoCommandResponse, GetGeometriesRequest, GetGeometriesResponse
from viam.proto.component.camera import (
CameraServiceBase,
Format,
GetImageRequest,
GetImageResponse,
GetImagesRequest,
Expand Down Expand Up @@ -50,23 +48,12 @@ async def GetImages(self, stream: Stream[GetImagesRequest, GetImagesResponse]) -
camera = self.get_resource(name)

timeout = stream.deadline.time_remaining() if stream.deadline else None
images, metadata = await camera.get_images(
timeout=timeout,
metadata=stream.metadata,
extra=struct_to_dict(request.extra),
filter_source_names=list(request.filter_source_names),
)
images, metadata = await camera.get_images(timeout=timeout, metadata=stream.metadata)
img_bytes_lst = []
for img in images:
try:
mime_type = CameraMimeType.from_string(img.mime_type) # this can ValueError if the mime_type is not a CameraMimeType
fmt = mime_type.to_proto()
except ValueError:
# TODO(RSDK-11728): remove this once we deleted the format field
fmt = Format.FORMAT_UNSPECIFIED

fmt = img.mime_type.to_proto()
img_bytes = img.data
img_bytes_lst.append(Image(source_name=name, mime_type=img.mime_type, format=fmt, image=img_bytes))
img_bytes_lst.append(Image(source_name=name, format=fmt, image=img_bytes))
response = GetImagesResponse(images=img_bytes_lst, response_metadata=metadata)
await stream.send_message(response)

Expand Down
15 changes: 6 additions & 9 deletions src/viam/media/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ def from_string(cls, value: str) -> Self:
Self: The mimetype
"""
value_mime = value[:-5] if value.endswith("+lazy") else value # ViamImage lazy encodes by default
try:
return cls(value_mime)
except ValueError:
raise ValueError(f"Invalid mimetype: {value}")
return cls(value_mime)

@classmethod
def from_proto(cls, format: Format.ValueType) -> "CameraMimeType":
Expand Down Expand Up @@ -73,11 +70,11 @@ class ViamImage:
"""

_data: bytes
_mime_type: str
_mime_type: CameraMimeType
_height: Optional[int] = None
_width: Optional[int] = None

def __init__(self, data: bytes, mime_type: str) -> None:
def __init__(self, data: bytes, mime_type: CameraMimeType) -> None:
self._data = data
self._mime_type = mime_type
self._width, self._height = _getDimensions(data, mime_type)
Expand All @@ -88,7 +85,7 @@ def data(self) -> bytes:
return self._data

@property
def mime_type(self) -> str:
def mime_type(self) -> CameraMimeType:
"""The mime type of the image"""
return self._mime_type

Expand Down Expand Up @@ -131,12 +128,12 @@ class NamedImage(ViamImage):
"""The name of the image
"""

def __init__(self, name: str, data: bytes, mime_type: str) -> None:
def __init__(self, name: str, data: bytes, mime_type: CameraMimeType) -> None:
self.name = name
super().__init__(data, mime_type)


def _getDimensions(image: bytes, mime_type: str) -> Tuple[Optional[int], Optional[int]]:
def _getDimensions(image: bytes, mime_type: CameraMimeType) -> Tuple[Optional[int], Optional[int]]:
try:
if mime_type == CameraMimeType.JPEG:
return _getDimensionsFromJPEG(image)
Expand Down
6 changes: 4 additions & 2 deletions src/viam/services/vision/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ async def GetDetections(self, stream: Stream[GetDetectionsRequest, GetDetections
extra = struct_to_dict(request.extra)
timeout = stream.deadline.time_remaining() if stream.deadline else None

image = ViamImage(request.image, request.mime_type)
mime_type = CameraMimeType.from_string(request.mime_type)
image = ViamImage(request.image, mime_type)

result = await vision.get_detections(image, extra=extra, timeout=timeout)
response = GetDetectionsResponse(detections=result)
Expand All @@ -104,7 +105,8 @@ async def GetClassifications(self, stream: Stream[GetClassificationsRequest, Get
extra = struct_to_dict(request.extra)
timeout = stream.deadline.time_remaining() if stream.deadline else None

image = ViamImage(request.image, request.mime_type)
mime_type = CameraMimeType.from_string(request.mime_type)
image = ViamImage(request.image, mime_type)

result = await vision.get_classifications(image, request.n, extra=extra, timeout=timeout)
response = GetClassificationsResponse(classifications=result)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from viam.proto.component.camera import (
CameraServiceStub,
DistortionParameters,
Format,
GetImageRequest,
GetImageResponse,
GetImagesRequest,
Expand Down Expand Up @@ -141,7 +142,6 @@ async def test_get_image(self, camera: MockCamera, service: CameraRPCService, im
request = GetImageRequest(name="camera", mime_type=CameraMimeType.PNG)
response: GetImageResponse = await client.GetImage(request, timeout=18.1)
assert response.image == image.data
assert response.mime_type == CameraMimeType.PNG
assert camera.timeout == loose_approx(18.1)

# Test empty mime type. Empty mime type should default to response mime type
Expand All @@ -158,7 +158,7 @@ async def test_get_images(self, camera: MockCamera, service: CameraRPCService, m
request = GetImagesRequest(name="camera")
response: GetImagesResponse = await client.GetImages(request, timeout=18.1)
raw_img = response.images[0]
assert raw_img.mime_type == CameraMimeType.PNG
assert raw_img.format == Format.FORMAT_PNG
assert raw_img.source_name == camera.name
assert response.response_metadata == metadata
assert camera.timeout == loose_approx(18.1)
Expand Down
Loading