Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSDK-7469: Add CaptureAllFromCamera() #3906

Merged
merged 13 commits into from
May 16, 2024
Merged

Conversation

Rob1in
Copy link
Member

@Rob1in Rob1in commented May 6, 2024

that way it seems that it just works for all built-in vision service in RDK.

EDIT: Open question on the MimeType for the "resp.Image.Image" ok now

@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label May 6, 2024
Copy link
Contributor

github-actions bot commented May 6, 2024

Warning your change may break code samples. If your change modifies any of the following functions please contact @viamrobotics/fleet-management. Thanks!

component function
base IsMoving
board GPIOPinByName
camera Properties
encoder Properties
motor IsMoving
sensor Readings
servo Position
arm EndPosition
audio MediaProperties
gantry Lengths
gripper IsMoving
input_controller Controls
movement_sensor LinearAcceleration
power_sensor Power
pose_tracker Poses
motion GetPose
vision ClassificationsFromCamera

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels May 9, 2024
Copy link
Member

@bhaney bhaney left a comment

Choose a reason for hiding this comment

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

Nice that CaptureAllFromCamera is going to be finally be able to return all the things we need it too!

In addition to the changes requested below, please add tests for client, server, and vision service

Comment on lines 262 to 265
return nil, err
if mimeType == "" {
img, _, err = image.Decode(bytes.NewReader(imgBytes))
if err != nil {
return nil, err
}
} else {
return nil, err
}
Copy link
Member

Choose a reason for hiding this comment

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

I know we wrote this together, but actually I think what you can do is just put this in its own case statement, so that you don't have to check again if the mimeType is ""

so it would be

case "":
    img, err := DecodeJPEG(bytes.NewReader(imgBytes))
    if err != nil {
        img, _, err = image.Decode(bytes.NewReader(imgBytes))
        if err != nil {
            return nil, err
       }
    }
    return img, nil   

Comment on lines 243 to 246
returnImage bool,
returnDetections bool,
returnClassifications bool,
returnObject bool,
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer that you create a struct that contains all of these bools together, rather than having to feed them in individually. It would also help with backwards compatability in case anything is ever added to the list

Comment on lines 54 to 57
returnImage bool,
returnClass bool,
returnDet bool,
returnObjPCD bool,
Copy link
Member

Choose a reason for hiding this comment

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

gather all of these bools into a struct, and pass the struct in as the argument. You can define this input within the viscapture package too

Comment on lines 222 to 225
returnImage bool,
returnClass bool,
returnDet bool,
returnObjPCD bool,
Copy link
Member

Choose a reason for hiding this comment

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

use a new struct for these bool inputs

Comment on lines 13 to 24
type VisCapture interface {
Image() image.Image
Detections() []objectdetection.Detection
Classifications() classification.Classifications
PointCloudObject() []*vision.Object
}

// NewVisCapture returns a VisCapture.
func NewVisCapture(img image.Image,
dets []objectdetection.Detection,
class classification.Classifications,
obj []*vision.Object,
) VisCapture {
return &capture{
image: img,
detections: dets,
classifications: class,
pcd: obj,
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious why you chose to make an interface for VisCapture, rather than just making the struct Public. Was it in order so that the output could not be modified by a user? In that case, what you can do is make the struct public, but the member variables private, and then have the methods on it to retrieve the values from the member variables (as you have already done)

services/vision/server.go Outdated Show resolved Hide resolved
Comment on lines 243 to 302
func imageToProto(ctx context.Context, img image.Image, mimeType string) (*v11.Image, error) {
imgBytes, err := rimage.EncodeImage(ctx, img, mimeType)
if err != nil {
return nil, err
}
return &v11.Image{Image: imgBytes}, nil
}
Copy link
Member

Choose a reason for hiding this comment

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

Add checks for if a "" mimeType is passed in.

  1. Check if its DepthMap or Gray16 (then encode as a ViamRawDepth Image)
  2. Check if it is a LazyEncodedImage (then use the mimeType from the lazy encoded Image)
  3. If it's none of those, you can default to a JPEG encoding

if err != nil {
return nil, err
}
return &v11.Image{Image: imgBytes}, nil
Copy link
Member

Choose a reason for hiding this comment

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

Also, Image has more fields than "Image", you should also store the"Format" that you ended up encoding it as. You also have the original camera name -- put that in the "SourceName" field

return nil, err
}

img, err := rimage.DecodeImage(ctx, resp.Image.Image, "")
Copy link
Member

Choose a reason for hiding this comment

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

The response Image gives you the "Format" as well. So you don't actually have to leave this blank -- you can know what the image is encoded as and decode it appropriately

return nil, err
}

capt := viscapture.NewVisCapture(img, dets, protoToClas(resp.Classifications), objPCD)
Copy link
Member

Choose a reason for hiding this comment

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

While protoToClas doesn't return an error, it was confusing at first because it seemed like you didn't return classifications. Go ahead and put this conversion on a line after protosToDets rather than doing the conversion in the New function.

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels May 13, 2024
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels May 15, 2024
@viambot viambot removed the safe to test This pull request is marked safe to test from a trusted zone label May 15, 2024
@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label May 15, 2024
@Rob1in Rob1in requested a review from bhaney May 15, 2024 17:43
@Rob1in Rob1in marked this pull request as ready for review May 15, 2024 17:43
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels May 15, 2024
defer release()
var detections []objectdetection.Detection
if opt.ReturnDetections {
if !vm.properties.DetectionSupported {
Copy link
Member Author

Choose a reason for hiding this comment

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

@bhaney I changed those tests to use the new vm.properites. Is that ok?

Copy link
Member

Choose a reason for hiding this comment

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

Yes 👍

sort.Slice(cc, func(i, j int) bool { return cc[i].Score() > cc[j].Score() })
return cc[0:n], nil
Copy link
Member Author

Choose a reason for hiding this comment

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

the change to return all classifications when n=0

return &camerapb.Image{
Image: imgBytes,
Format: format,
SourceName: cameraName,
Copy link
Member Author

Choose a reason for hiding this comment

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

it seems that SourceName gets lost when the proto is decoded in the image.Image....

Copy link
Member

Choose a reason for hiding this comment

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

luckily, SourceName is only really important for GetImages -- so I think this is fine

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels May 15, 2024
}, nil
}

func encodeUnknownType(ctx context.Context, img image.Image, defaultMime string) ([]byte, string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

nice function!

Copy link
Member

@bhaney bhaney left a comment

Choose a reason for hiding this comment

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

Nice work! LGTM!

@Rob1in Rob1in merged commit 18d6caf into viamrobotics:main May 16, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
safe to test This pull request is marked safe to test from a trusted zone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants