fromCamera working; experimenting with zoom

feature/image-source
Christoph Oberhofer 8 years ago
parent 242c275571
commit eb858d0c63

@ -77,7 +77,7 @@
</label> </label>
<label> <label>
<span>Half-Sample</span> <span>Half-Sample</span>
<input type="checkbox" name="locator_half-sample" /> <input checked="checked" type="checkbox" name="locator_half-sample" />
</label> </label>
<label> <label>
<span>Single Channel</span> <span>Single Channel</span>

@ -3,24 +3,29 @@ $(function() {
init : function() { init : function() {
this.overlay = document.querySelector('#interactive canvas.drawing'); this.overlay = document.querySelector('#interactive canvas.drawing');
this.scanner = Quagga this.state.inputStream.constraints.zoom = {exact: 2};
.fromConfig(this.state); Quagga.fromCamera({
constraints: this.state.inputStream.constraints,
this.scanner locator: this.state.locator,
.addEventListener("processed", drawResult.bind(this, this.scanner)) decoder: this.state.decoder,
.addEventListener("detected", addToResults.bind(this, this.scanner)); }).then(function(scanner) {
this.scanner = scanner;
this.scanner.start() this.scanner
.then(function (){ .addEventListener("processed", drawResult.bind(this, this.scanner))
console.log("started"); .addEventListener("detected", addToResults.bind(this, this.scanner));
this.attachListeners();
}.bind(this)) this.scanner.start()
.catch(function(err) { .then(function (){
console.log("Error: " + err); console.log("started");
}); this.attachListeners();
}.bind(this))
.catch(function(err) {
console.error(err);
});
}.bind(this));
}, },
initCameraSelection: function(){ initCameraSelection: function() {
var streamLabel = Quagga.CameraAccess.getActiveStreamLabel(); var streamLabel = this.scanner.getSource().getLabel();
return Quagga.CameraAccess.enumerateVideoDevices() return Quagga.CameraAccess.enumerateVideoDevices()
.then(function(devices) { .then(function(devices) {
@ -106,8 +111,8 @@ $(function() {
if (/^(\d+)x(\d+)$/.test(value)) { if (/^(\d+)x(\d+)$/.test(value)) {
var values = value.split('x'); var values = value.split('x');
return { return {
width: {min: parseInt(values[0])}, width: {ideal: parseInt(values[0])},
height: {min: parseInt(values[1])} height: {ideal: parseInt(values[1])}
}; };
} }
return { return {
@ -141,8 +146,8 @@ $(function() {
inputStream: { inputStream: {
type : "LiveStream", type : "LiveStream",
constraints: { constraints: {
width: {min: 640}, width: {ideal: 640},
height: {min: 480}, height: {ideal: 480},
facingMode: "environment", facingMode: "environment",
aspectRatio: {min: 1, max: 2} aspectRatio: {min: 1, max: 2}
} }

@ -4,3 +4,13 @@ export function sleep(millis) {
window.setTimeout(resolve, millis); window.setTimeout(resolve, millis);
}); });
} }
export function getViewport(target) {
if (target && target.nodeName && target.nodeType === 1) {
return target;
} else {
// Use '#interactive.viewport' as a fallback selector (backwards compatibility)
var selector = typeof target === 'string' ? target : '#interactive.viewport';
return document.querySelector(selector);
}
}

@ -30,7 +30,7 @@ module.exports = {
} }
}, },
locator: { locator: {
halfSample: false, halfSample: true,
patchSize: "medium", // x-small, small, medium, large, x-large patchSize: "medium", // x-small, small, medium, large, x-large
debug: { debug: {
showCanvas: false, showCanvas: false,

@ -2,6 +2,7 @@ import {
computeGray computeGray
} from '../common/cv_utils'; } from '../common/cv_utils';
import {sleep} from '../common/utils'; import {sleep} from '../common/utils';
import {getViewport} from '../common/utils';
function adjustCanvasSize(input, canvas) { function adjustCanvasSize(input, canvas) {
if (input instanceof HTMLVideoElement) { if (input instanceof HTMLVideoElement) {
@ -25,18 +26,8 @@ function adjustCanvasSize(input, canvas) {
} }
} }
function getViewPort(target) {
if (target && target.nodeName && target.nodeType === 1) {
return target;
} else {
// Use '#interactive.viewport' as a fallback selector (backwards compatibility)
var selector = typeof target === 'string' ? target : '#interactive.viewport';
return document.querySelector(selector);
}
}
function getOrCreateCanvas(source, target) { function getOrCreateCanvas(source, target) {
const $viewport = getViewPort(target); const $viewport = getViewport(target);
let $canvas = $viewport.querySelector("canvas.imgBuffer"); let $canvas = $viewport.querySelector("canvas.imgBuffer");
if (!$canvas) { if (!$canvas) {
$canvas = document.createElement("canvas"); $canvas = document.createElement("canvas");

@ -1,21 +1,40 @@
import {clone} from 'lodash';
import {determineOrientation, PORTRAIT} from '../common/device'; import {determineOrientation, PORTRAIT} from '../common/device';
import CameraAccess from './camera_access'; import CameraAccess from './camera_access';
import {getViewport} from '../common/utils';
export function fromCamera(constraints) { function getOrCreateVideo(source, target) {
if (!constraints) { const $viewport = getViewport(target);
constraints = {width: {ideal: 540}, height: {ideal: 540}, aspectRatio: {ideal: 1}, facingMode: 'environment'}; if ($viewport) {
let $video = $viewport.querySelector("video");
if (!$video) {
$video = document.createElement("video");
$viewport.appendChild($video);
}
return $video;
} }
return document.createElement("video");
}
export function fromCamera(constraints) {
var orientation = determineOrientation(); var orientation = determineOrientation();
var videoConstraints = constraints; var videoConstraints = clone(constraints);
if (orientation === PORTRAIT) { if (orientation === PORTRAIT) {
constraints = Object.assign({}, constraints, { videoConstraints = Object.assign({}, videoConstraints, {
width: constraints.height, width: videoConstraints.height,
height: constraints.width, height: videoConstraints.width,
}); });
} }
const video = document.querySelector('video'); if (videoConstraints.zoom && videoConstraints.zoom.exact > 1) {
CameraAccess.request(videoConstraints, video) videoConstraints.width.ideal = Math.floor(videoConstraints.width.ideal * videoConstraints.zoom.exact);
videoConstraints.height.ideal = Math.floor(videoConstraints.height.ideal * videoConstraints.zoom.exact);
delete videoConstraints.zoom;
}
console.log(videoConstraints);
const video = getOrCreateVideo();
return CameraAccess.request(video, videoConstraints)
.then(function(mediastream) { .then(function(mediastream) {
const track = mediastream.getVideoTracks()[0]; const track = mediastream.getVideoTracks()[0];
return { return {
@ -39,8 +58,8 @@ export function fromCamera(constraints) {
return { return {
viewport, viewport,
canvas: { canvas: {
width: constraints.width, // AR width: viewport.width, // AR
height: constraints.height, // AR height: viewport.height, // AR
}, },
}; };
}, },
@ -65,7 +84,7 @@ export function fromCamera(constraints) {
constraints.height.ideal = Math.floor(constraints.height.ideal * constraints.zoom.exact); constraints.height.ideal = Math.floor(constraints.height.ideal * constraints.zoom.exact);
delete constraints.zoom; delete constraints.zoom;
} }
return CameraAccess.request(videoConstraints, video); return CameraAccess.request(video, videoConstraints);
}, },
getLabel: function() { getLabel: function() {
return track.label; return track.label;

@ -10,7 +10,7 @@ var streamRef;
function waitForVideo(video, stream) { function waitForVideo(video, stream) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let attempts = 10; let attempts = 20;
function checkVideo() { function checkVideo() {
if (attempts > 0) { if (attempts > 0) {
@ -20,7 +20,7 @@ function waitForVideo(video, stream) {
} }
resolve(stream); resolve(stream);
} else { } else {
window.setTimeout(checkVideo, 500); window.setTimeout(checkVideo, 200);
} }
} else { } else {
reject('Unable to play video stream. Is webcam working?'); reject('Unable to play video stream. Is webcam working?');

@ -5,13 +5,14 @@ import ImageDebug from './common/image_debug';
import ResultCollector from './analytics/result_collector'; import ResultCollector from './analytics/result_collector';
import Config from './config/config'; import Config from './config/config';
import {merge} from 'lodash'; import {merge} from 'lodash';
import {createConfigForImage} from './input/config_factory'; import CameraAccess from './input/camera_access';
import * as PixelCapture from './input/PixelCapture'; import * as PixelCapture from './input/PixelCapture';
import * as Source from './input/Source'; import * as Source from './input/Source';
function fromConfig(pixelCapturer, config) { function fromConfig(pixelCapturer, config) {
const scanner = createScanner(pixelCapturer); const scanner = createScanner(pixelCapturer);
const source = pixelCapturer.getSource(); const source = pixelCapturer.getSource();
let currentConfig = config;
let pendingStart = null; let pendingStart = null;
let initialized = false; let initialized = false;
return { return {
@ -35,7 +36,7 @@ function fromConfig(pixelCapturer, config) {
return Promise.resolve(true); return Promise.resolve(true);
} }
pendingStart = new Promise((resolve, reject) => { pendingStart = new Promise((resolve, reject) => {
scanner.init(config, (error) => { scanner.init(currentConfig, (error) => {
if (error) { if (error) {
console.log(error); console.log(error);
reject(error); reject(error);
@ -80,7 +81,7 @@ function fromConfig(pixelCapturer, config) {
}; };
} else { } else {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
scanner.decodeSingle(config, (result) => { scanner.decodeSingle(currentConfig, (result) => {
if (result && result.codeResult && result.codeResult.code) { if (result && result.codeResult && result.codeResult.code) {
return resolve(result); return resolve(result);
} }
@ -95,6 +96,21 @@ function fromConfig(pixelCapturer, config) {
getCanvas() { getCanvas() {
return pixelCapturer.getCanvas(); return pixelCapturer.getCanvas();
}, },
applyConfig(newConfig) {
// during runtime?
// running scanners must know that!
// apply constraints to source, only if changed
const normalizedConfig = merge({}, Config, newConfig);
this.stop();
currentConfig = normalizedConfig;
return source.applyConstraints(currentConfig.constraints)
.then(() => this.start());
},
getSource() {
return pixelCapturer.getSource();
}
}; };
} }
@ -116,6 +132,12 @@ function createApi() {
.fromImage(image, config.constraints) .fromImage(image, config.constraints)
.then(fromSource.bind(null, config)); .then(fromSource.bind(null, config));
}, },
fromCamera(options) {
const config = merge({}, Config, options);
return Source
.fromCamera(config.constraints)
.then(fromSource.bind(null, config));
},
fromSource(src, inputConfig) { fromSource(src, inputConfig) {
return fromSource(configuration, src, inputConfig); return fromSource(configuration, src, inputConfig);
}, },
@ -134,6 +156,7 @@ function createApi() {
config(conf) { config(conf) {
return createApi(merge({}, configuration, conf)); return createApi(merge({}, configuration, conf));
}, },
CameraAccess,
ImageWrapper, ImageWrapper,
ImageDebug, ImageDebug,
ResultCollector, ResultCollector,

@ -209,10 +209,11 @@ function createScanner(pixelCapturer) {
} else { } else {
//_framegrabber.attachData(_inputImageWrapper.data); //_framegrabber.attachData(_inputImageWrapper.data);
} }
pixelCapturer.grabFrameData()
return pixelCapturer.grabFrameData()
.then((bitmap) => { .then((bitmap) => {
_inputImageWrapper.data = bitmap.data;
if (bitmap) { if (bitmap) {
_inputImageWrapper.data = bitmap.data;
if (availableWorker) { if (availableWorker) {
availableWorker.busy = true; availableWorker.busy = true;
availableWorker.worker.postMessage({ availableWorker.worker.postMessage({
@ -226,15 +227,15 @@ function createScanner(pixelCapturer) {
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
}) });
} else {
locateAndDecode();
} }
return locateAndDecode();
} }
function startContinuousUpdate() { function startContinuousUpdate() {
var next = null, var next = null,
delay = 1000 / (_config.frequency === 0 ? 60 : (_config.frequency || 60)); delay = 1000 / (_config.frequency === 0 ? 10 : (_config.frequency || 10));
_stopped = false; _stopped = false;
(function frame(timestamp) { (function frame(timestamp) {
@ -242,9 +243,12 @@ function createScanner(pixelCapturer) {
if (!_stopped) { if (!_stopped) {
if (timestamp >= next) { if (timestamp >= next) {
next += delay; next += delay;
update(); update().then(() => {
window.requestAnimFrame(frame);
});
} else {
window.requestAnimFrame(frame);
} }
window.requestAnimFrame(frame);
} }
}(performance.now())); }(performance.now()));
} }

Loading…
Cancel
Save