Xaval v0.6
Pre-releaseXaval v0.6 Release
This release contains a number of new features, improvements and breaking changes.
Here's a brief overview of what has changed:
- This release introduces camera support. You can now work with video streams from connected cameras via a simple API (
xaval.io.cameras
) and (camera.getStream()
) - You can now import multiple files in your workspace and access them in code via the new
xaval.io.files
API - Widgets now support 3 new additional parameter controls (checkbox, select list and text field)
- Widget ids are displayed on the widgets' headers
- You can now explore different example code from the samples menu
- Minor UI improvements including a new font family and slightly rounder buttons
Breaking changes
xaval.io.imageSource
has been removed. You should now usexaval.io.files.readImage(name)
instead ofxaval.io.imageSource.read()
xaval.widgets.create(tplName)
now returns the created widget instead of the widget id
Introduction camera support
One of the major highlights of this release is that Xaval finally allows you to work with cameras. It exposes xaval.io.cameras
which is an instance of CameraManager
. This allows you request connected cameras from the browser user: cameras.getDefault()
returns the default camera with a muted video stream, and cameras.getWithConstraints(constraints)
allows you to specify options.
The returned objects are instances of Camera
. This is a wrapper that allows you to request permission to use the camera via camera.start()
, which returns a promise. You can read the current frame from the camera using camera.read()
. But most often you will want to get video a stream from the camera. For that you can use the camera.getStream({ fps })
method which returns a data source that you can pipe to a widget's input or other data sink.
Example:
const camera = xaval.io.cameras.getDefault();
const stream = camera.getStream({ fps: 30 });
stream.pipe(xaval.io.imageViewer);
camera.start();
Here are more detailed descriptions of the new APIs.
CameraManager
API (xaval.io.cameras
)
Member | Description |
---|---|
cameras.getDefault(): Camera |
returns a camera instance representing the default camera from the browser, without audio capture |
cameras.getWithConstraints(contraints: MediaStreamContraints): Camera |
allows you to specify more fine-grained contraints. Refer to the MediaStreamContraints web API for available options. |
Note, access to the camera is not requested until you call camera.start()
, so there's not guarantee that the instance returned by the camera manager represents an available or accessible camera.
Camera
API
Member | Description |
---|---|
camera.start(): Promise |
tries to get the camera with the specified constraints. This also prompts the user for permission. If access is granted, the camera will start the video feed and the returned promise will resolve. From this point on you can call camera.read() to get the current frame. |
camera.read(dest?: cv.Mat): cv.Mat |
returns the current frame of the camera feed. If dest is provided, the image will be stored in that memory, otherwise the camera will store it elsewhere (in a recycled memory area, so a new one is only created when the current one is deleted) |
camera.width: number |
width of the video |
camera.height: number |
height of the video |
camera.getStream(opts: {fps: number, autoStart?: boolean}): VideoStream |
returns a video stream from the camera feed at a rate specified by the opts.fps option. If opts.autoStart is true (which is the default), the camera will start the stream automatically when the camera feed starts. However, if it's false, you will have to manually call stream.start() after camera.start() has resolved successfully. Furthermore, this method does not create a new stream if one is already connected to the camera, even if you pass different options. If you want a different stream (for example, with a different frame rate), you need to stop the camera (camera.stop() ) and then call camera.getStream() , and don't forget to start the camera again. |
camera.stop() |
This stops the camera feed and disposes of the resources used by the camera. This also stops the stream obtained from getStream() if any, and disconnects it. You can start the camera again using camera.start() but you will need to get a new stream from camera.getStream(opts) . |
Camera
implements the new VideoSource
API, which exposes the read(dest?)
and getStream(opts)
methods, as well as the width
and height
properties.
VideoStream
API
Member | Description |
---|---|
stream.streaming: boolean |
gets whether or not its currently streaming data |
stream.params: { fps: number, autoStart: boolean } |
returns the options used to create the stream |
stream.start() |
starts streaming data, before this is called, not data is transmitted to observers |
stream.stop() |
stops streaming data. To start streaming data again call stream.start() |
VideoStream
implements the DataSource
interface and therefore exposes the following members:
stream.observable
stream.subscribe(observer: Observer): Subscription
stream.pipe(dest: DataSink): DataSink
New file library
With the new file library, you can now import multiple images (more file types coming soon). The new file library is located at the same position as the old image source. Now you will see an Import button that allows you to select images to import. You can select and import multiple files at once. Once imported, the thumbnails are displayed on a horizontal list along with their file names. You can edit a file's name by simple clicking it and editing it.
You can also manage and access the files programmatically via the new FileLibrary
API, that xaval.io.files
exposes.
FileLibrary
API (xaval.io.files
)
Member | Description |
---|---|
files.addImage(url: string, name?: string) |
adds a new image to the library, where url is the image's source. If name is not provided, a new one is generated (file1 , then file2 , etc.). Warning: if the image is from the web, it will still be added, but you may get errors when working with the image in Xaval due to cross-origin restrictions in the browser. This is a known issue that be addressed in the future. |
files.readImage(name: string): cv.Mat |
returns the image with the specified name, undefined is returned if the name is not in the library. You will get unexpected results if the file exists but is not an image. |
rename(oldName: string, newName: string) |
renames a file. You will get an error alert if a file with the target name already exists |
Widgets improvements
Widget id displayed in the header
The widget id is now displayed on the right end the widget header, prepended with a #
character. For example if #widget1
is displayed, the real id is actually widget1
.
WidgetManager#create(name: string)
returns the widget
It was counter-intuitive for widgets.create()
to return the widget id. This was done because there was no easy way to tell what the id was, but is now no longer necessary.
So instead of:
const id = widgets.create('MyWidget');
const widget = widgets.get(id);
You should now do:
const widget = widgets.create('MyWidget');
New param data types and controls
Up to now only the slider
control was available. Now Xaval adds checkboxes, select lists and text fields, as well as support for boolean
param data types.
checkbox
control
This is the default control for boolean
widget params.
text
control
This renders a text field. It's the default control for string
widget params.
select
control
This is a single-select list. It supports multiple data types, namely numbers and strings. It requires an options
option in the param config, which is an object mapping possible values to their labels. The labels are what are displayed on the list, but its the values that are used internally. If the param type is 'number'
, then the values will be automatically converted to numbers. Furthermore, if the an initial
option is provided, it should be of the correct type.
Minor changes
- A Samples menu has been added to the main header, allowing the user to check out different examples of what you can do in Xaval
- The app now starts with an empty editor that only contains a few comments and link to OpenCV.js tutorials
- The editor indentation size has been reduced to spaces to allow for more writing width
- The font family has been changed to the system's default ui font
- Buttons were given slightly rounder edges