IndexSizeError: DOM Exception 1 (Processing.js, Aruco.js, getUserMedia)
in
Processing with Other Languages
•
6 months ago
I am attempting to use the
Aruco.js augmented reality library with Processing.js. I already have it's most simple implementation working, where I am using getUserMedia to use the webcam through the browser and applying it to the canvas using context.drawImage(). I then use context.getImageData() to grab the color information and feed it to Aruco via detector.detect(). This gives me Marker objects, which provide polygon information which I then read in my processing.js sketch to draw. The result looks like this (the red polygon borders, green marker, and blue number are all rendered using processing methods):
Of course, the next step is to get the rotation information for each AR marker in order to do some cool 3D stuff. This is where I ran into my problem. In order to use rotateX() and rotateY() I need to setup my processing sketch using the OPENGL context. When I switch to OPENGL, I can no longer use the context.drawImage() method that was applying the video frame to the canvas. So I ended up making one canvas (set to display: none) which acts as a container for my frames in order to get the color data, and another canvas for my Processing.js WebGL content.
When I launch the page, I can see my processing sketch with a little spinning cube (in order to insure the draw loop is still working) and the prompt at the top of the browser asking to allow the camera. As soon as I hit allow, my animation stops and I get this error in the browser console:
So, I start commenting out code and I get to the point where I discover the line that is actually causing the issue is this one:
- imageData = context.getImageData(0, 0, canvas.width, canvas.height);
However, I can't find any information regarding this DOM exception or issues with using multiple canvas objects with Processing.js. I am testing this in Chrome 26.0.1410.64m on Windows 7 and Chrome 26.0.1410.65 on OSX 10.7.5 using Processing.js 1.4.1. The error is consistent across platforms. Here is the complete code:
processing_3dar.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>processingjs augmented reality test</title>
- <meta charset="utf-8">
- <link rel="stylesheet" type="text/css" href="_css/basic.css" />
- </head>
- <body>
- <script src="_js/cv.js"></script>
- <script src="_js/aruco.js"></script>
- <script src="_js/posit1.js"></script>
- <script src="_js/svd.js"></script>
- <script src="_js/processing.js"></script>
- <script src="_js/aruco3dp5.js"></script>
- <video id="video" autoplay="true" style="display:none;"></video>
- <canvas id="canvas" data-processing-sources="_pde/processing_aruco3d.pde" width="960" height="720"></canvas>
- <canvas id="imagecanvas" width="960" height="720" style="display:none;"></canvas>
- </body>
- </html>
aruco3dp5.js:
- var video; // video DOM element
- var canvas; // canvas DOM element
- var context; // canvas javascript context
- var imageData; // webcam image data
- var detector; // AR detector
- var markers; // array of marker objects for any given frame
- var posit; // posit object to analyze corners for rotation vector
- var markerSize = 18;
- /*
- * Init function.
- */
- function onLoad(){
- // establish DOM elements and canvas context
- video = document.getElementById("video");
- canvas = document.getElementById("imagecanvas");
- context = canvas.getContext("2d");
- // get canvas dimensions
- canvas.width = parseInt(canvas.style.width);
- canvas.height = parseInt(canvas.style.height);
- // get access to camera
- navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
- if (navigator.getUserMedia){
- navigator.getUserMedia({video: true}, successCallback, errorCallback);
- function successCallback(stream){
- if (window.webkitURL) {
- video.src = window.webkitURL.createObjectURL(stream);
- } else {
- video.src = stream;
- }
- }
- function errorCallback(error){
- // do nothing, I guess.
- }
- // create the AR detector
- detector = new AR.Detector();
- // create the Posit object
- posit = new POS.Posit(markerSize, canvas.width);
- }
- }
- /*
- * Grab the current frame from the video.
- */
- function snapshot(){
- context.drawImage(video, 0, 0, canvas.width, canvas.height);
- // FIXME: line below: "Uncaught Error: IndexSizeError: DOM Exception 1"
- imageData = context.getImageData(0, 0, canvas.width, canvas.height);
- //markers = detector.detect(imageData);
- }
- window.onload = onLoad;
processing_aruco3d.pde (note that drawOutline and drawPose are never called for purposes of testing):
- void setup(){
- size(960, 720, OPENGL);
- frameRate(30);
- rectMode(CENTER);
- strokeWeight(3);
- }
- void draw(){
- if (video.readyState === video.HAVE_ENOUGH_DATA){
- snapshot();
- //drawOutline();
- }
- background(255);
- translate(width/2, height/2);
- rotateY(0.5);
- rotateX(frameCount * 0.01);
- box(100);
- }
- void drawOutline(){
- for(Object m : markers){
- // draw outline
- noFill();
- stroke(255,0,0);
- beginShape();
- for(int i=0; i<m.corners.length; i++){
- vertex(m.corners[i].x, m.corners[i].y);
- }
- endShape(CLOSE);
- // draw primary corner
- stroke(0,255,0);
- rect(m.corners[0].x, m.corners[0].y, 4, 4);
- // draw ID number
- fill(0,150,255);
- text(m.id, m.corners[0].x, m.corners[0].y);
- // draw pose
- //drawPose(m.corners);
- }
- }
- void drawPose(Object[] corners){
- // translate corners to center justify marker face
- for(Object corner : corners){
- corner.x = corner.x - (width / 2);
- corner.y = (height / 2) - corner.y;
- }
- Object pose = posit.pose(corners);
- // get rotation and translation values
- Object rot = pose.bestRotation;
- Object trans = pose.bestTranslation;
- // convert rotation values to radians (I think)
- float yaw = -Math.atan2(rot[0][2], rot[2][2]);
- float pitch = -Math.asin(-rot[1][2]);
- float roll = Math.atan2(rot[1][0], rot[1][1]);
- // draw a cube
- pushMatrix();
- translate(trans.x, trans.y, trans.z);
- rotateX(pitch);
- rotateY(yaw);
- rotateZ(roll);
- box(markerSize);
- popMatrix();
- }
1