3
3
package fake
4
4
5
5
import (
6
+ "bytes"
6
7
"context"
8
+ "encoding/base64"
7
9
"errors"
8
10
"fmt"
9
11
"image"
12
+ "image/jpeg"
10
13
"time"
11
14
12
15
"go.viam.com/rdk/components/camera"
@@ -36,9 +39,16 @@ func init() {
36
39
}
37
40
38
41
func newCamera (ctx context.Context , name resource.Name , newConf * fileSourceConfig , logger logging.Logger ) (camera.Camera , error ) {
39
- videoSrc := & fileSource {newConf .Color , newConf .Depth , newConf .PointCloud , newConf .CameraParameters }
42
+ videoSrc := & fileSource {
43
+ ColorFN : newConf .Color ,
44
+ DepthFN : newConf .Depth ,
45
+ PointCloudFN : newConf .PointCloud ,
46
+ Intrinsics : newConf .CameraParameters ,
47
+ PreloadedImage : newConf .PreloadedImage ,
48
+ }
49
+
40
50
imgType := camera .ColorStream
41
- if newConf .Color == "" {
51
+ if newConf .Color == "" && newConf . PreloadedImage == "" {
42
52
imgType = camera .DepthStream
43
53
}
44
54
cameraModel := camera .NewPinholeModelWithBrownConradyDistortion (newConf .CameraParameters , newConf .DistortionParameters )
@@ -56,10 +66,11 @@ func newCamera(ctx context.Context, name resource.Name, newConf *fileSourceConfi
56
66
57
67
// fileSource stores the paths to a color and depth image and a pointcloud.
58
68
type fileSource struct {
59
- ColorFN string
60
- DepthFN string
61
- PointCloudFN string
62
- Intrinsics * transform.PinholeCameraIntrinsics
69
+ ColorFN string
70
+ DepthFN string
71
+ PointCloudFN string
72
+ Intrinsics * transform.PinholeCameraIntrinsics
73
+ PreloadedImage string
63
74
}
64
75
65
76
// fileSourceConfig is the attribute struct for fileSource.
@@ -69,6 +80,7 @@ type fileSourceConfig struct {
69
80
Color string `json:"color_image_file_path,omitempty"`
70
81
Depth string `json:"depth_image_file_path,omitempty"`
71
82
PointCloud string `json:"pointcloud_file_path,omitempty"`
83
+ PreloadedImage string `json:"preloaded_image,omitempty"` // can be "pizza", "dog", or "crowd"
72
84
}
73
85
74
86
// Validate ensures all parts of the config are valid.
@@ -81,23 +93,41 @@ func (c fileSourceConfig) Validate(path string) ([]string, error) {
81
93
}
82
94
}
83
95
96
+ if c .PreloadedImage != "" {
97
+ switch c .PreloadedImage {
98
+ case "pizza" , "dog" , "crowd" :
99
+ // valid options
100
+ default :
101
+ return nil , fmt .Errorf ("preloaded_image must be one of: pizza, dog, crowd. Got: %s" , c .PreloadedImage )
102
+ }
103
+ }
104
+
84
105
return []string {}, nil
85
106
}
86
107
87
108
// Read returns just the RGB image if it is present, or the depth map if the RGB image is not present.
88
109
func (fs * fileSource ) Read (ctx context.Context ) (image.Image , func (), error ) {
89
- if fs .ColorFN == "" && fs .DepthFN == "" {
110
+ if fs .ColorFN == "" && fs .DepthFN == "" && fs . PreloadedImage == "" {
90
111
return nil , nil , errors .New ("no image file to read, so not implemented" )
91
112
}
92
- if fs .ColorFN == "" { // only depth info
113
+ if fs .ColorFN == "" && fs . PreloadedImage == "" { // only depth info
93
114
img , err := rimage .NewDepthMapFromFile (context .Background (), fs .DepthFN )
94
115
if err != nil {
95
116
return nil , nil , err
96
117
}
97
118
return img , func () {}, err
98
119
}
99
120
100
- img , err := rimage .NewImageFromFile (fs .ColorFN )
121
+ var img * rimage.Image
122
+ var err error
123
+
124
+ // Get image from preloaded image or file
125
+ if fs .PreloadedImage != "" {
126
+ img , err = getPreloadedImage (fs .PreloadedImage )
127
+ } else {
128
+ img , err = rimage .NewImageFromFile (fs .ColorFN )
129
+ }
130
+
101
131
if err != nil {
102
132
return nil , nil , err
103
133
}
@@ -123,24 +153,35 @@ func (fs *fileSource) Read(ctx context.Context) (image.Image, func(), error) {
123
153
124
154
// Images returns the saved color and depth image if they are present.
125
155
func (fs * fileSource ) Images (ctx context.Context ) ([]camera.NamedImage , resource.ResponseMetadata , error ) {
126
- if fs .ColorFN == "" && fs .DepthFN == "" {
127
- return nil , resource.ResponseMetadata {}, errors .New ("no image file to read, so not implemented" )
156
+ if fs .ColorFN == "" && fs .DepthFN == "" && fs . PreloadedImage == "" {
157
+ return nil , resource.ResponseMetadata {}, errors .New ("no image files to read, so not implemented" )
128
158
}
129
159
imgs := []camera.NamedImage {}
160
+
161
+ if fs .PreloadedImage != "" {
162
+ img , err := getPreloadedImage (fs .PreloadedImage )
163
+ if err != nil {
164
+ return nil , resource.ResponseMetadata {}, err
165
+ }
166
+ imgs = append (imgs , camera.NamedImage {img , "preloaded" })
167
+ }
168
+
130
169
if fs .ColorFN != "" {
131
170
img , err := rimage .NewImageFromFile (fs .ColorFN )
132
171
if err != nil {
133
172
return nil , resource.ResponseMetadata {}, err
134
173
}
135
174
imgs = append (imgs , camera.NamedImage {img , "color" })
136
175
}
176
+
137
177
if fs .DepthFN != "" {
138
178
dm , err := rimage .NewDepthMapFromFile (context .Background (), fs .DepthFN )
139
179
if err != nil {
140
180
return nil , resource.ResponseMetadata {}, err
141
181
}
142
182
imgs = append (imgs , camera.NamedImage {dm , "depth" })
143
183
}
184
+
144
185
ts := time .Now ()
145
186
return imgs , resource.ResponseMetadata {CapturedAt : ts }, nil
146
187
}
@@ -227,3 +268,25 @@ func (ss *StaticSource) NextPointCloud(ctx context.Context) (pointcloud.PointClo
227
268
func (ss * StaticSource ) Close (ctx context.Context ) error {
228
269
return nil
229
270
}
271
+
272
+ // getPreloadedImage returns one of the preloaded images based on the name.
273
+ func getPreloadedImage (name string ) (* rimage.Image , error ) {
274
+ var imageBase64 []byte
275
+ switch name {
276
+ case "pizza" :
277
+ imageBase64 = pizzaBase64
278
+ case "dog" :
279
+ imageBase64 = dogBase64
280
+ case "crowd" :
281
+ imageBase64 = crowdBase64
282
+ default :
283
+ return nil , fmt .Errorf ("unknown preloaded image: %s" , name )
284
+ }
285
+
286
+ d := base64 .NewDecoder (base64 .StdEncoding , bytes .NewReader (imageBase64 ))
287
+ img , err := jpeg .Decode (d )
288
+ if err != nil {
289
+ return nil , fmt .Errorf ("failed to decode image: %w" , err )
290
+ }
291
+ return rimage .ConvertImage (img ), nil
292
+ }
0 commit comments