├── .gitignore ├── .travis.yml ├── test ├── files │ ├── eye-tjs.json │ ├── leye-old-tjs.json │ ├── leye-old.json │ ├── eye.json │ ├── leye-old.xml │ ├── eye2.xml │ ├── eye.xml │ └── eye-malformed.xml ├── test-converter-tjs-transform.js └── test-converter-tjs.js ├── .editorconfig ├── package.json ├── LICENSE ├── src ├── converter-tjs-transform.js └── converter-tjs.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | modified_files/ 3 | *.log 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.11" 5 | -------------------------------------------------------------------------------- /test/files/eye-tjs.json: -------------------------------------------------------------------------------- 1 | [20,20,-1.4562760591506958,1,1,2,0,8,20,12,-1,0,14,20,6,2,0.12963959574699402,-0.7730420827865601,0.6835014820098877] 2 | -------------------------------------------------------------------------------- /test/files/leye-old-tjs.json: -------------------------------------------------------------------------------- 1 | [ 2 | 18, 3 | 12, 4 | -1.9446439743041992, 5 | 1, 6 | 0, 7 | 2, 8 | 3, 9 | 0, 10 | 12, 11 | 12, 12 | -1, 13 | 7, 14 | 4, 15 | 4, 16 | 4, 17 | 9, 18 | -0.5461140871047974, 19 | 0.8206881880760193, 20 | -0.7562180161476135 21 | ] 22 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = tab 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.js] 13 | indent_style = space 14 | 15 | [*.yml] 16 | indent_style = space 17 | 18 | 19 | [*.xml] 20 | insert_final_newline = false 21 | -------------------------------------------------------------------------------- /test/files/leye-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "nstages": 1, 3 | "stages": [ 4 | { 5 | "stageThreshold": -1.9446439743041992, 6 | "nodes": [ 7 | { 8 | "left_val": 0.8206881880760193, 9 | "right_val": -0.7562180161476135, 10 | "threshold": -0.5461140871047974, 11 | "f": 0 12 | } 13 | ], 14 | "nnodes": 1 15 | } 16 | ], 17 | "rects": [ 18 | { 19 | "data": [ 20 | "3 0 12 12 -1.", 21 | "7 4 4 4 9." 22 | ], 23 | "tilted": 0 24 | } 25 | ], 26 | "maxWeakCount": 0, 27 | "cascadeSize": { 28 | "width": 18, 29 | "height": 12 30 | }, 31 | "maxCatCount": 0 32 | } -------------------------------------------------------------------------------- /test/files/eye.json: -------------------------------------------------------------------------------- 1 | { 2 | "nstages": 1, 3 | "stages": [ 4 | { 5 | "stageThreshold": -1.4562760591506958, 6 | "nodes": [ 7 | { 8 | "left_val": -0.7730420827865601, 9 | "right_val": 0.6835014820098877, 10 | "threshold": 0.12963959574699402, 11 | "f": 0 12 | } 13 | ], 14 | "nnodes": 1 15 | } 16 | ], 17 | "rects": [ 18 | { 19 | "data": [ 20 | "0 8 20 12 -1.", 21 | "0 14 20 6 2." 22 | ], 23 | "tilted": 1 24 | } 25 | ], 26 | "maxWeakCount": 0, 27 | "cascadeSize": { 28 | "width": 20, 29 | "height": 20 30 | }, 31 | "maxCatCount": 0 32 | } 33 | -------------------------------------------------------------------------------- /test/files/leye-old.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 12 4 | 5 | <_> 6 | 7 | 8 | <_> 9 | 10 | <_> 11 | 12 | 13 | 14 | <_>3 0 12 12 -1. 15 | <_>7 4 4 4 9. 16 | 17 | 0 18 | 19 | -5.4611408710479736e-001 20 | 8.2068818807601929e-001 21 | -7.5621801614761353e-001 22 | 23 | 24 | 25 | -1.9446439743041992e+000 26 | -1 27 | -1 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-converter-tjs", 3 | "description": "Converts new type of OpenCV HaarCascade xml data to tracking.js internal rep", 4 | "version": "0.0.3", 5 | "main": "src/converter-tjs-transform.js", 6 | "scripts": { 7 | "test": "mocha test" 8 | }, 9 | "author": "Ciro S. Costa (http://www.cirocosta.com.br/)", 10 | "license": "MIT", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/cirocosta/gulp-converter-tjs.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/cirocosta/gulp-converter-tjs/issues" 17 | }, 18 | "homepage": "https://github.com/cirocosta/gulp-converter-tjs", 19 | "dependencies": { 20 | "gulp-util": "^3.0.0", 21 | "through2": "^0.5.1", 22 | "xml-stream": "^0.4.5" 23 | }, 24 | "devDependencies": { 25 | "gulp": "^3.8.7", 26 | "mocha": "^1.21.4", 27 | "vinyl": "^0.3.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/files/eye2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BOOST 5 | HAAR 6 | 50 7 | 50 8 | 9 | 1 10 | 11 | 12 | 0 13 | 14 | 1 15 | 16 | <_> 17 | 1 18 | -1.4515760591501958e+00 19 | 20 | <_> 21 | 0 -1 0 1.5913959574199405e-01 22 | -7.7304208278151001e-01 1.8350148200988770e-01 23 | 24 | 25 | 26 | 27 | 28 | <_> 29 | 30 | <_>0 8 20 12 -1. 31 | <_>0 14 20 1 2. 32 | 33 | 1 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/files/eye.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BOOST 5 | HAAR 6 | 20 7 | 20 8 | 9 | 1 10 | 11 | 12 | 0 13 | 14 | 1 15 | 16 | <_> 17 | 1 18 | -1.4562760591506958e+00 19 | 20 | <_> 21 | 0 -1 0 1.2963959574699402e-01 22 | -7.7304208278656006e-01 6.8350148200988770e-01 23 | 24 | 25 | 26 | 27 | 28 | <_> 29 | 30 | <_>0 8 20 12 -1. 31 | <_>0 14 20 6 2. 32 | 33 | 1 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ciro S. Costa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/files/eye-malformed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BOOST 5 | HAAR 6 | 20 7 | 20 8 | 9 | 1 10 | 11 | 12 | 0 13 | 14 | 1 15 | 16 | <_> 17 | 1 18 | -1.4562760591506958e+00 19 | 20 | <_> 21 | 0 -1 0 1.2963959574699402e-01 22 | -7.7304208278656006e-01 6.8350148200988770e-01 23 | 24 | 25 | 26 | 27 | 28 | <_> 29 | 30 | <_>0 8 20 12 -1. 31 | <_>0 14 20 6 2. 32 | 33 | 34 | <_> 35 | 36 | <_>0 55 22 3 -3. 37 | <_>1 1 20 3 1. 38 | 39 | 1 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/converter-tjs-transform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var through = require('through2') 4 | , converter = require('./converter-tjs')() 5 | , Readable = require('stream').Readable || require('readable-stream') 6 | , PluginError = require('gulp-util').PluginError 7 | , NAME = 'gulp-converter-tjs'; 8 | 9 | /** 10 | * Creates a stream w/ data. 11 | */ 12 | function createStream (data) { 13 | var rs = new Readable({ objectMode: true }); 14 | rs.push(data); 15 | rs.push(null); 16 | 17 | return rs; 18 | } 19 | 20 | /** 21 | * The transform itself 22 | */ 23 | function ConverterTJS () { 24 | if (!(this instanceof ConverterTJS)) 25 | return new ConverterTJS(); 26 | 27 | function _transform (file, enc, callback) { 28 | if (file.isStream()) 29 | return (this.emit('error', new PluginError(NAME, 'Streams are not supported!')), 30 | callback()); 31 | 32 | if (file.isBuffer()) { 33 | var stream = createStream(file.contents.toString()); 34 | var scope = this; 35 | 36 | stream.on('error', this.emit.bind(this, 'error')); 37 | converter.convert(stream, function (err, data) { 38 | if (err) 39 | return (scope.emit('error', new PluginError(NAME, err)), 40 | callback()); 41 | 42 | file.contents = new Buffer(JSON.stringify(converter.toTJS(data))); 43 | scope.push(file); 44 | callback(); 45 | }); 46 | } 47 | } 48 | 49 | return through.obj(_transform); 50 | } 51 | 52 | module.exports = ConverterTJS; 53 | -------------------------------------------------------------------------------- /test/test-converter-tjs-transform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('assert') 4 | , fs = require('fs') 5 | , gutil = require('gulp-util') 6 | , File = require('vinyl') 7 | , converterTjs = require('../src/converter-tjs-transform') 8 | , path = require('path').resolve(__dirname, './files'); 9 | 10 | describe('converterTransform', function() { 11 | it('should be sane', function() { 12 | assert(!!converterTjs); 13 | }); 14 | 15 | var converter; 16 | 17 | it('should not deal with gulp streams', function(done) { 18 | converter = converterTjs(); 19 | var stream = fs.createReadStream(path + '/eye.xml'); 20 | var file = new File({contents: stream}); 21 | 22 | assert.throws(function () { 23 | converter.write(file); 24 | }, 'Streams are not allowed'); 25 | 26 | done(); 27 | }); 28 | 29 | describe('Regarding the new format', function() { 30 | 31 | beforeEach(function () { 32 | converter = converterTjs(); 33 | }); 34 | 35 | it('should deal with gulp buffers', function(done) { 36 | var xml = fs.readFileSync(path + '/eye.xml'); 37 | var file = new File({contents: new Buffer(xml)}); 38 | 39 | converter.write(file); 40 | converter.end(); 41 | 42 | converter.once('data', function (f) { 43 | var actual = JSON.parse(f.contents.toString()); 44 | var expected = JSON.parse( 45 | fs.readFileSync(path + '/eye-tjs.json')); 46 | 47 | assert.deepEqual(actual, expected); 48 | done(); 49 | }); 50 | }); 51 | }); 52 | 53 | 54 | describe('Regarding the Old format', function() { 55 | 56 | beforeEach(function () { 57 | converter = converterTjs('old'); 58 | }); 59 | 60 | it('should deal with gulp buffers regarding old format', function(done) { 61 | var xml = fs.readFileSync(path + '/leye-old.xml'); 62 | var file = new File({contents: new Buffer(xml)}); 63 | 64 | converter.write(file); 65 | converter.end(); 66 | 67 | converter.once('data', function (f) { 68 | var actual = JSON.parse(f.contents.toString()); 69 | var expected = JSON.parse( 70 | fs.readFileSync(path + '/leye-old-tjs.json')); 71 | 72 | assert.deepEqual(actual, expected); 73 | done(); 74 | }); 75 | }); 76 | }); 77 | 78 | }); 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-converter-tjs [![Build Status](https://travis-ci.org/cirocosta/gulp-converter-tjs.svg?branch=master)](https://travis-ci.org/cirocosta/gulp-converter-tjs) 2 | 3 | > Converts new and old type of [OpenCV](https://github.com/Itseez/opencv) HaarCascade XML data to [tracking.js](https://github.com/eduardolundgren/tracking.js)' internal format. 4 | 5 | ## Process 6 | 7 | *converter-tjs* takes a XML of OpenCV training data (new or old type), parses it to an internal representation (JavaScript object) and then pushes to stdout the *tracking.js* representation of it. 8 | 9 | ### Example 10 | 11 | ```javascript 12 | var gulp = require('gulp'); 13 | var converterTjs = require('gulp-converter-tjs'); 14 | 15 | gulp.task('default', function () { 16 | gulp.src('./test/files/haarcascade_frontalface_alt.xml') 17 | .pipe(converterTjs()) 18 | .pipe(gulp.dest('./modified-files')); 19 | }); 20 | ``` 21 | 22 | ```xml 23 | 24 | 25 | 26 | BOOST 27 | HAAR 28 | 20 29 | 20 30 | 31 | 1 32 | 33 | 34 | 0 35 | 36 | 1 37 | 38 | <_> 39 | 1 40 | -1.4562760591506958e+00 41 | 42 | <_> 43 | 0 -1 0 1.2963959574699402e-01 44 | -7.7304208278656006e-01 6.8350148200988770e-01 45 | 46 | 47 | 48 | 49 | 50 | <_> 51 | 52 | <_>0 8 20 12 -1. 53 | <_>0 14 20 6 2. 54 | 55 | 1 56 | 57 | 58 | 59 | 60 | ``` 61 | 62 | turns into 63 | 64 | ```json 65 | { 66 | "nstages": 1, 67 | "stages": [ 68 | { 69 | "stageThreshold": -1.4562760591506958, 70 | "nodes": [ 71 | { 72 | "left_val": -0.77304208278656006, 73 | "right_val": -0.68350148200988770, 74 | "threshold": 0.12963959574699402, 75 | "f": 0 76 | } 77 | ], 78 | "nnodes": 1 79 | } 80 | ], 81 | "rects": [ 82 | { 83 | "data": [ 84 | "0 8 20 12 -1.", 85 | "0 14 20 6 2." 86 | ], 87 | "tilted": 1 88 | } 89 | ], 90 | "maxWeakCount": 0, 91 | "cascadeSize": { 92 | "width": 20, 93 | "height": 20 94 | }, 95 | "maxCatCount": 0 96 | } 97 | ``` 98 | 99 | which turns into 100 | 101 | ```javascript 102 | [20,20,-1.4562760591506958,1,1,2,0,8,20,12,-1,0,14,20,6,2,0.12963959574699402, -0.77304208278656006,-0.68350148200988770] 103 | 104 | // which is similar to a flattened nested array w/ loops ('[]') like the following: 105 | 106 | [width, height, 107 | [stageThreshold, nodeLength, 108 | [tilted, rectsLength, 109 | [rL, rT, rW, rH, rWeigth] 110 | nThreshold, nL, nR]]] 111 | ``` 112 | -------------------------------------------------------------------------------- /test/test-converter-tjs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs') 4 | , path = require('path') 5 | , assert = require('assert') 6 | , ConverterTJS = require('../src/converter-tjs') 7 | , Readable = require('stream').Readable || require('readable-stream'); 8 | 9 | 10 | function createStream (data) { 11 | var rs = new Readable({ objectMode: true }); 12 | rs.push(data); 13 | rs.push(null); 14 | 15 | return rs; 16 | } 17 | 18 | describe('converter\'s', function() { 19 | it('should be sane', function() { 20 | assert(!!ConverterTJS); 21 | }); 22 | 23 | var converter = new ConverterTJS(); 24 | var filesPath = path.resolve(__dirname, './files'); 25 | 26 | describe('convert method', function() { 27 | it('should convert new type directly from a stream', function(done) { 28 | var stream = fs.createReadStream(filesPath + '/eye.xml', 29 | {encoding: 'utf8'}); 30 | 31 | converter.convert(stream, function (err, result) { 32 | if (err) done(err); 33 | 34 | var expected = fs.readFileSync(filesPath + '/eye.json'); 35 | 36 | assert.deepEqual(result, JSON.parse(expected)); 37 | done(); 38 | }); 39 | }); 40 | 41 | it('should convert new type from a fake stream', function (done) { 42 | var fileContent = fs.readFileSync(filesPath + '/eye.xml', 43 | {enconding: 'utf8'}); 44 | var stream = createStream(fileContent); 45 | 46 | converter.convert(stream, function (err, result) { 47 | if (err) done(err); 48 | 49 | var expected = fs.readFileSync(filesPath + '/eye.json'); 50 | 51 | assert.deepEqual(result, JSON.parse(expected)); 52 | done(); 53 | }); 54 | }); 55 | 56 | it('should throw if malformed new type of haar cascade', function(done) { 57 | var stream = fs.createReadStream(filesPath + '/eye-malformed.xml', 58 | {encoding: 'utf8'}); 59 | 60 | converter.convert(stream, function (err, result) { 61 | if (err) 62 | (assert(err), done()); 63 | else 64 | done(new Error('Should throw an exception')); 65 | }); 66 | }); 67 | 68 | it('should convert an old type directly from a stream', function(done) { 69 | var stream = fs.createReadStream(filesPath + '/leye-old.xml', 70 | {encoding: 'utf8'}); 71 | 72 | converter.convert(stream, function (err, result) { 73 | if (err) done (err); 74 | 75 | var expected = fs.readFileSync(filesPath + '/leye-old.json'); 76 | 77 | assert.deepEqual(result, JSON.parse(expected)); 78 | done(); 79 | }); 80 | }); 81 | }); 82 | 83 | describe('toTJS method', function() { 84 | it('should convert a haarStruct from the new type of xml', function() { 85 | var fileRes = fs.readFileSync(filesPath + '/eye-tjs.json'); 86 | var orig = fs.readFileSync(filesPath + '/eye.json'); 87 | 88 | var expected = JSON.parse(fileRes); 89 | var actual = converter.toTJS(JSON.parse(orig)); 90 | 91 | assert.deepEqual(actual, expected) 92 | }); 93 | 94 | it('should convert a haarStruct from the old type of xml', function() { 95 | var fileRes = fs.readFileSync(filesPath + '/leye-old-tjs.json'); 96 | var orig = fs.readFileSync(filesPath + '/leye-old.json'); 97 | var expected = JSON.parse(fileRes); 98 | var actual = converter.toTJS(JSON.parse(orig)); 99 | 100 | assert.deepEqual(actual, expected); 101 | }); 102 | }); 103 | }); 104 | -------------------------------------------------------------------------------- /src/converter-tjs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs') 4 | , path = require('path') 5 | , XmlStream = require('xml-stream'); 6 | 7 | /** 8 | * Constructor 9 | */ 10 | function ConverterTJS () { 11 | if (!(this instanceof ConverterTJS)) 12 | return new ConverterTJS(); 13 | } 14 | 15 | 16 | /** 17 | * Converts the new type of opencv haarcascade 18 | * classifiers to an internal representation. 19 | * @param {stream} stream stream of xml 20 | * @param {Function} cb callback function 21 | * to be resolved with 22 | * (err|data), w/ data 23 | * being the result 24 | * structure 25 | */ 26 | ConverterTJS.prototype.convert = function (stream, cb) { 27 | if (!stream) 28 | throw new Error('A stream must be passed'); 29 | 30 | var f = 0; 31 | var g = 0; 32 | 33 | var xml = new XmlStream(stream); 34 | var haarStruct = { 35 | nstages: 0, 36 | stages: [], 37 | rects: [], 38 | maxWeakCount: 0, 39 | cascadeSize: { 40 | width: 0, 41 | height: 0 42 | }, 43 | maxCatCount: 0 44 | }; 45 | 46 | xml.collect('_'); 47 | 48 | xml.on('endElement: size', function (item) { 49 | var sizes = item['$text'].split(' '); 50 | 51 | haarStruct.cascadeSize.width = +sizes[0]; 52 | haarStruct.cascadeSize.height = +sizes[1]; 53 | }); 54 | 55 | xml.on('endElement: cascade > height', function (item) { 56 | haarStruct.cascadeSize.height = +item['$text']; 57 | }); 58 | 59 | xml.on('endElement: cascade > width', function (item) { 60 | haarStruct.cascadeSize.width = +item['$text']; 61 | }); 62 | 63 | xml.on('endElement: stages > _', function (item) { 64 | if (!item.trees) { 65 | // dealing with the new type 66 | var stage = { 67 | stageThreshold: parseFloat(item.stageThreshold), 68 | nodes: [] 69 | }; 70 | 71 | stage.nnodes = item.weakClassifiers['_'].length; 72 | 73 | for (var i = 0 ; i < stage.nnodes; i++) { 74 | var internalNodes = item 75 | .weakClassifiers['_'][i] 76 | .internalNodes.split(' '); 77 | var leafValues = item 78 | .weakClassifiers['_'][i] 79 | .leafValues.split(' '); 80 | var node = { 81 | left_val: '', 82 | right_val: '', 83 | threshold: '' 84 | }; 85 | 86 | g++; 87 | 88 | node.left_val = parseFloat(leafValues[0]); 89 | node.right_val = parseFloat(leafValues[1]); 90 | node.f = +internalNodes[2]; 91 | node.threshold = parseFloat(internalNodes[3]); 92 | 93 | stage.nodes.push(node); 94 | } 95 | 96 | haarStruct.nstages++; 97 | haarStruct.stages.push(stage); 98 | } else { 99 | // dealing with the old type 100 | var trees = item.trees._; 101 | var stage = { 102 | stageThreshold: parseFloat(item.stage_threshold), 103 | nodes: [] 104 | }; 105 | 106 | stage.nnodes = trees.length; 107 | 108 | for (var i in trees) { 109 | var tree = trees[i]._; 110 | var node = { 111 | "left_val": parseFloat(tree[0].left_val), 112 | "right_val": parseFloat(tree[0].right_val), 113 | "threshold": parseFloat(tree[0].threshold), 114 | "f": f++ 115 | }; 116 | 117 | g++; 118 | stage.nodes.push(node); 119 | 120 | haarStruct.rects.push({ 121 | data: tree[0].feature.rects._, 122 | tilted: +tree[0].feature.tilted 123 | }); 124 | } 125 | 126 | haarStruct.nstages++; 127 | haarStruct.stages.push(stage); 128 | } 129 | }); 130 | 131 | xml.on('endElement: features > _', function(item) { 132 | haarStruct.rects.push({ 133 | data: item.rects['_'], 134 | tilted: item.tilted ? 1 : 0 135 | }); 136 | 137 | f++; 138 | }); 139 | 140 | xml.on('error', function (err) { 141 | cb(err); 142 | }); 143 | 144 | xml.on('end', function () { 145 | if (g !== f) 146 | return cb(new Error('Number of rects does not mach number of Nodes')); 147 | cb(null, haarStruct); 148 | }); 149 | }; 150 | 151 | /** 152 | * Converts from the internal structure to 153 | * tracking.js-ready opencv representation of 154 | * haarcascade classifiers 155 | * @param {Object} orig the internal rep of the 156 | * xml passed to convert 157 | * @return {[type]} the tracking.js-ready 158 | * rep 159 | */ 160 | ConverterTJS.prototype.toTJS = function (orig) { 161 | var results = []; 162 | var f = 0; 163 | 164 | // width and height 165 | results.push(orig.cascadeSize.width); 166 | results.push(orig.cascadeSize.height); 167 | 168 | // iterate through stages 169 | for (var i = 0; i < orig.nstages;) { 170 | // stageThreshold, nodeLength 171 | var stage = orig.stages[i++]; 172 | 173 | results.push(stage.stageThreshold); 174 | results.push(stage.nodes.length); 175 | 176 | // iterate through nodes 177 | for (var j = 0; j < stage.nnodes;) { 178 | // tilted, rectsLength 179 | var node = stage.nodes[j++]; 180 | var rect = orig.rects[f++]; 181 | 182 | results.push(rect.tilted); 183 | results.push(rect.data.length); 184 | 185 | // iterate through rects 186 | for (var k = 0, N = rect.data.length; k < N;) { 187 | // rectLeft, rectTop, rectWidth, rectHeight, rectWeight 188 | var R = rect.data[k++].split(' '); 189 | for (var l = 0, M = R.length; l < M; l++) 190 | results.push(+R[l]); 191 | } 192 | 193 | results.push(node.threshold); 194 | results.push(node.left_val); 195 | results.push(node.right_val); 196 | } 197 | } 198 | 199 | return results; 200 | }; 201 | 202 | module.exports = ConverterTJS; 203 | --------------------------------------------------------------------------------