Skip to content

Xaval v0.6

Pre-release
Pre-release
Compare
Choose a tag to compare
@habbes habbes released this 12 Jun 23:30
· 79 commits to master since this release

Xaval v0.6 Release

Xaval v0.6 edge detection

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 use xaval.io.files.readImage(name) instead of xaval.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

Xaval v0.6 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

Xaval 0.6 new widget controls

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