Source: ptolemy/actor/lib/jjs/modules/aprilTags/aprilTags.js

// Below is the copyright agreement for the Ptolemy II system.
//
// Copyright (c) 2015-2016 The Regents of the University of California.
// All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the above
// copyright notice and the following two paragraphs appear in all copies
// of this software.
//
// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
// ENHANCEMENTS, OR MODIFICATIONS.
//
//
// Ptolemy II includes the work of others, to see those copyrights, follow
// the copyright link on the splash page or see copyright.htm.
/**
Module to identify AprilTags in an image.

This code uses AprilTags Java code found in $PTII/edu/umich/eecs/april.

The AprilTags code developed by the APRIL robotics lab under the
direction of Edwin Olson (ebolson@umich.edu).

The Java implementation of the AprilTags detector is provided for
convenience as a demonstration.  It is an older version implemented in
Java that has been supplanted by a much better performing C version.
If your application demands better performance, you will need to
replace this implementation with the newer C version and using JNI or
JNA to interface the C version to Java.

For details about the C version, see
https://april.eecs.umich.edu/wiki/index.php/AprilTags-C

https://april.eecs.umich.edu/software/apriltag.html contains a set of
pregenerated tags as png and PostScript files.  However, these are of
low resolution.  To scale them, use linear interpolation to avoid blurring.

For example, with ImageMagik, use:

mogrify -scale 1000x1000 *.png; convert *.png tag36h11.pdf

Or, search the web for "tag 36H11".

In the Ptolemy tree, a sample file may be found at
$PTII/ptolemy/actor/lib/jjs/modules/aprilTags//demo/AprilTags/tag36_11_00586.pdf

@module aprilTags
@author Edward A. Lee
 */

// Stop extra messages from jslint.  Note that there should be no
// space between the / and the * and global.
/*globals exports, Java */
/*jshint globalstrict: true*/
"use strict";

////////////////////////////////////////////////////////////
//// Private variables.

var Filter = Java.type('edu.umich.eecs.april.image.AprilTagFilter');
var filter = new Filter();

////////////////////////////////////////////////////////////
//// Functions provided in this module.

/** Invoke the AprilTag detector on the specified image with the specified
 *  options and return the result.  Any unrecognized options are ignored.
 *  Note that previously applied options for a given filter will still be
 *  used, even if they are not set in this call.
 *  @param image The image to filter.
 *  @param options An object whose fields specify filter options.
 *  @return The filtered image.
 */
exports.filter = function (image, options) {
    var optionName, setter;
    image = image.asAWTImage();
    if (options) {
        for (optionName in options) {
            // jslint: avoid "The body of a for in should be wrapped
            // in an if statement to filter unwanted properties from
            // the prototype."
            if (options.hasOwnProperty(optionName)) {
                // Look for a setter function for the option.
                setter = 'set' + optionName;
                if (typeof filter[setter] === 'function') {
                    // Invoke the setter function.
                    filter[setter](options[optionName]);
                }
            }
        }
    }
    // The second (null) argument declines to give a destination image.
    return filter.filter(image, null);
};

/** Return an array of tags detected by the most recent call to filter().
 *  The returned value is null if there has been no call to filter().
 *  Otherwise, it is an array of objects with the following fields:
 *  <ul>
 *  <li> id: The ID of the detected tag.
 *  <li> center: An array with two doubles giving the center of the tag in pixel coordinates.
 *  <li> perimeter: An array with four arrays, each of which gives the x and y coordinates of
 *       a corner of the AprilTag, listed in a counter-clockwise direction.
 *  </ul>
 *  @return The detected tags.
 */
exports.tags = function () {
    return filter.tags();
};