SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
WebCamera Class Reference

Interface to access the camera in the browser. More...

#include <WebCamera.h>

Public Member Functions

void open (WebCameraFacing facing)
 Acquires a video stream. More...
 
bool isReady ()
 Returns whether the video stream has been acquired. More...
 
CVMat read ()
 Reads the current frame. More...
 
CVSize2i getSize ()
 Gets the size of the video input. More...
 
void setSize (CVSize2i size)
 Requests a video size from the browser. More...
 
void close ()
 Closes the video stream. More...
 
bool isOpened ()
 

Private Attributes

bool _isOpened = false
 
CVMat _image
 
CVMat _imageBGR
 
bool _waitingForResize = false
 

Detailed Description

Interface to access the camera in the browser.

Definition at line 25 of file WebCamera.h.

Member Function Documentation

◆ close()

void WebCamera::close ( )

Closes the video stream.

After calling this function, the camera must be reopened before accessing any of the other member functions.

Definition at line 192 of file WebCamera.cpp.

193 {
194  // clang-format off
195  EM_ASM({
196  let video = document.querySelector("#capture-video");
197  let stream = video.srcObject;
198 
199  if (stream === null) {
200  console.log("[WebCamera] Stream is already closed");
201  }
202 
203  stream.getVideoTracks().forEach(track => {
204  if (track.readyState == "live") {
205  track.stop();
206  stream.removeTrack(track);
207  }
208  });
209 
210  console.log("[WebCamera] Stream closed");
211  });
212  // clang-format on
213 }

◆ getSize()

CVSize2i WebCamera::getSize ( )

Gets the size of the video input.

The size is determined by getting the width and height of the HTML video element.

Returns
The size of the video input

Definition at line 123 of file WebCamera.cpp.

124 {
125  int32_t width;
126  int32_t height;
127 
128  // clang-format off
129  EM_ASM({
130  let video = document.querySelector("#capture-video");
131  let width = video.videoWidth;
132  let height = video.videoHeight;
133 
134  setValue($0, video.videoWidth, "i32");
135  setValue($1, video.videoHeight, "i32");
136  }, &width, &height);
137  // clang-format on
138 
139  return CVSize2i(width, height);
140 }
cv::Size2i CVSize2i
Definition: CVTypedefs.h:56

◆ isOpened()

bool WebCamera::isOpened ( )
inline

Definition at line 36 of file WebCamera.h.

36 { return _isOpened; }
bool _isOpened
Definition: WebCamera.h:39

◆ isReady()

bool WebCamera::isReady ( )

Returns whether the video stream has been acquired.

The video stream is not immediately available when calling WebCamera::open. This function can be used to determine if the user has allowed camera access and if it is ready for reading.

Returns
True if the stream has been acquired

Definition at line 57 of file WebCamera.cpp.

58 {
59  return _image.cols != 0 && _image.rows != 0;
60 }
CVMat _image
Definition: WebCamera.h:40

◆ open()

void WebCamera::open ( WebCameraFacing  facing)

Acquires a video stream.

Requests a video stream from the browser and assigns it to the HTML video object as soon as it is ready. It must be called before accessing any of the other member functions. The function does not block, so the stream may not be ready yet after it returns.

Parameters
facingPreferred facing mode on mobile

Definition at line 23 of file WebCamera.cpp.

24 {
25  // clang-format off
26  EM_ASM({
27  console.log("[WebCamera] Requesting stream...");
28 
29  let facingMode;
30  if ($0 == 0) facingMode = "user";
31  else if ($0 == 1) facingMode = "environment";
32 
33  navigator.mediaDevices.getUserMedia({ "video": { "facingMode": facingMode } })
34  .then(stream => {
35  console.log("[WebCamera] Stream acquired");
36 
37  let video = document.querySelector("#capture-video");
38  video.srcObject = stream;
39  })
40  .catch(error => {
41  console.log("[WebCamera] Failed to acquire stream");
42  console.log(error);
43  });
44  }, facing);
45  // clang-format on
46 
47  _isOpened = true;
48 }

◆ read()

CVMat WebCamera::read ( )

Reads the current frame.

If the video stream is ready, copies the current frame from the video HTML element into a CVMat in BGR format. Returns an empty image otherwise.

Returns
The CVMat containing the image data in BGR format

Definition at line 68 of file WebCamera.cpp.

69 {
70  CVSize2i size = getSize();
71 
72  // If the width or the height is zero, the video is not ready
73  if (size.width == 0 || size.height == 0)
74  return CVMat(0, 0, CV_8UC3);
75 
76  // Recreate the image if the size has changed
77  if (size.width != _image.cols || size.height != _image.rows)
78  {
79  _image = CVMat(size.height,
80  size.width,
81  CV_8UC4);
82  _waitingForResize = false;
83  }
84 
85  // clang-format off
86  EM_ASM({
87  let video = document.querySelector("#capture-video");
88  let canvas = document.querySelector("#capture-canvas");
89 
90  // the last parameter canvas_will_read_frequently is set to true
91  // https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently
92  let ctx = canvas.getContext("2d", true, false, "srgb", true);
93 
94  let width = video.videoWidth;
95  let height = video.videoHeight;
96 
97  if (width == 0 || height == 0)
98  return;
99 
100  canvas.width = width;
101  canvas.height = height;
102  ctx.drawImage(video, 0, 0, width, height);
103  let imageData = ctx.getImageData(0, 0, width, height);
104 
105  writeArrayToMemory(imageData.data, $0);
106  }, _image.data);
107  // clang-format on
108 
109  if (_imageBGR.size != _image.size)
110  _imageBGR = CVMat(_image.rows, _image.cols, CV_8UC3);
111 
112  cv::cvtColor(_image, _imageBGR, cv::COLOR_RGBA2BGR);
113 
114  return _imageBGR;
115 }
cv::Mat CVMat
Definition: CVTypedefs.h:38
CVMat _imageBGR
Definition: WebCamera.h:41
bool _waitingForResize
Definition: WebCamera.h:42
CVSize2i getSize()
Gets the size of the video input.
Definition: WebCamera.cpp:123

◆ setSize()

void WebCamera::setSize ( CVSize2i  size)

Requests a video size from the browser.

The function tries to resize the video size. It is not guaranteed that this will have any effect or that the size after resizing will be equal to the size provided because the browser may not support it.

Parameters
sizePreferred size of the video

Definition at line 149 of file WebCamera.cpp.

150 {
151  // Return if the stream is still loading
152  if (!isReady())
153  return;
154 
155  // Return if we are already waiting for the resize
156  if (_waitingForResize)
157  return;
158 
159  // Return if the new size is equal to the old size
160  if (size.width == _image.cols && size.height == _image.rows)
161  return;
162 
163  _waitingForResize = true;
164 
165  // clang-format off
166  EM_ASM({
167  let video = document.querySelector("#capture-video");
168  let stream = video.srcObject;
169 
170  if (stream === null)
171  return;
172 
173  // We can't use object literals because that breaks EM_ASM for some reason
174  let constraints = {};
175  constraints["width"] = $0;
176  constraints["height"] = $1;
177 
178  stream.getVideoTracks().forEach(track => {
179  track.applyConstraints(constraints);
180  });
181 
182  console.log("[WebCamera] Applied resolution " + $0 + "x" + $1);
183  }, size.width, size.height);
184  // clang-format on
185 }
bool isReady()
Returns whether the video stream has been acquired.
Definition: WebCamera.cpp:57

Member Data Documentation

◆ _image

CVMat WebCamera::_image
private

Definition at line 40 of file WebCamera.h.

◆ _imageBGR

CVMat WebCamera::_imageBGR
private

Definition at line 41 of file WebCamera.h.

◆ _isOpened

bool WebCamera::_isOpened = false
private

Definition at line 39 of file WebCamera.h.

◆ _waitingForResize

bool WebCamera::_waitingForResize = false
private

Definition at line 42 of file WebCamera.h.


The documentation for this class was generated from the following files: