Jelajahi Sumber

Update darknet.js

Lutz Roeder 6 tahun lalu
induk
melakukan
e057e172a3
2 mengubah file dengan 241 tambahan dan 183 penghapusan
  1. 89 50
      src/darknet-metadata.json
  2. 152 133
      src/darknet.js

+ 89 - 50
src/darknet-metadata.json

@@ -4,14 +4,14 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "filters", "visible": false, "default": 1 },
-        { "name": "size", "default": 1 },
-        { "name": "stride", "default": 1 },
-        { "name": "groups", "default": 1 },
-        { "name": "padding", "default": 0 },
-        { "name": "pad", "type": "boolean", "default": false },
-        { "name": "batch_normalize", "type": "boolean", "default": false },
-        { "name": "activation", "default": "logistic" }
+        { "name": "filters", "type": "int32", "visible": false, "default": 1 },
+        { "name": "size", "type": "int32", "default": 1 },
+        { "name": "stride", "type": "int32", "default": 1 },
+        { "name": "groups", "type": "int32", "default": 1 },
+        { "name": "padding", "type": "int32", "default": 0 },
+        { "name": "pad", "type": "int32", "default": 0 },
+        { "name": "batch_normalize", "type": "int32", "default": 0 },
+        { "name": "activation", "type": "string", "default": "logistic" }
       ]
     }
   },
@@ -20,13 +20,13 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "filters", "visible": false, "default": 1 },
-        { "name": "size", "default": 1 },
-        { "name": "stride", "default": 1 },
-        { "name": "padding", "default": 0 },
-        { "name": "pad", "type": "boolean", "default": false },
-        { "name": "batch_normalize", "type": "boolean", "default": false },
-        { "name": "activation", "default": "logistic" }
+        { "name": "filters", "type": "int32", "visible": false, "default": 1 },
+        { "name": "size", "type": "int32", "default": 1 },
+        { "name": "stride", "type": "int32", "default": 1 },
+        { "name": "padding", "type": "int32", "default": 0 },
+        { "name": "pad", "type": "int32", "default": 0 },
+        { "name": "batch_normalize", "type": "int32", "default": 0 },
+        { "name": "activation", "type": "string", "default": "logistic" }
       ]
     }
   },
@@ -35,7 +35,7 @@
     "schema": {
       "category": "Dropout",
       "attributes": [
-        { "name": "probability", "default": 0.5 }
+        { "name": "probability", "type": "float32", "default": 0.5 }
       ]
     }
   },
@@ -44,7 +44,7 @@
     "schema": {
       "category": "Pool",
       "attributes": [
-        { "name": "stride", "default": 1 }
+        { "name": "stride", "type": "int32", "default": 1 }
       ]
     }
   },
@@ -59,8 +59,8 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "output", "visible": false, "default": 1 },
-        { "name": "activation", "default": "logistic" }
+        { "name": "output", "type": "int32", "visible": false, "default": 1 },
+        { "name": "activation", "type": "string", "default": "logistic" }
       ]
     }
   },
@@ -69,7 +69,7 @@
     "schema": {
         "category": "Activation",
         "attributes": [
-          { "name": "groups", "default": 1 }
+          { "name": "groups", "type": "int32", "default": 1 }
         ]
     }
   },
@@ -78,8 +78,8 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "output", "visible": false, "default": 1 },
-        { "name": "batch_normalize", "type": "boolean", "default": false }
+        { "name": "output", "type": "int32", "visible": false, "default": 1 },
+        { "name": "batch_normalize", "type": "int32", "default": 0 }
       ]
     }
   },
@@ -88,7 +88,7 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "output", "visible": false, "default": 1 }
+        { "name": "output", "type": "int32", "visible": false, "default": 1 }
       ]
     }
   },
@@ -97,10 +97,10 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "batch_normalize", "type": "boolean", "default": false },
+        { "name": "batch_normalize", "type": "int32", "default": 0 },
         { "name": "activation", "default": "logistic" },
-        { "name": "output_filters", "default": 1 },
-        { "name": "hidden_filters", "default": 1 }
+        { "name": "output_filters", "type": "int32", "default": 1 },
+        { "name": "hidden_filters", "type": "int32", "default": 1 }
       ]
     }
   },
@@ -109,9 +109,10 @@
     "schema": {
       "category": "Layer",
       "attributes": [
-        { "name": "output", "visible": false },
-        { "name": "hidden", "visible": false },
-        { "name": "batch_normalize", "type": "boolean", "default": false }
+        { "name": "output", "type": "int32", "visible": false },
+        { "name": "hidden", "type": "int32", "visible": false },
+        { "name": "batch_normalize", "type": "int32", "default": 0 },
+        { "name": "activation", "type": "string", "default": "logistic" }
       ]
     }
   },
@@ -120,10 +121,10 @@
     "schema": {
       "category": "Shape",
       "attributes": [
-        { "name": "flip", "type": "boolean" },
-        { "name": "exposure", "default": 1 },
-        { "name": "saturation", "default": 1 },
-        { "name": "angle", "default": 0 }
+        { "name": "flip", "type": "int32", "default": 0 },
+        { "name": "exposure", "type": "float32", "default": 1 },
+        { "name": "saturation", "type": "float32", "default": 1 },
+        { "name": "angle", "type": "float32", "default": 0 }
       ]
     }
   },
@@ -132,9 +133,9 @@
     "schema": {
       "attributes": [
         { "name": "stride", "default": 1 },
-        { "name": "reverse", "type": "boolean", "default": false },
-        { "name": "flatten", "type": "boolean", "default": false },
-        { "name": "extra", "type": "boolean", "default": false }
+        { "name": "reverse", "type": "int32", "default": 0 },
+        { "name": "flatten", "type": "int32", "default": 0 },
+        { "name": "extra", "type": "int32", "default": 0 }
       ]
     }
   },
@@ -143,7 +144,8 @@
     "schema": {
       "category": "Tensor",
       "attributes": [
-        { "name": "activation", "default": "linear" }
+        { "name": "from", "type": "int32" },
+        { "name": "activation", "type": "string", "default": "linear" }
       ]
     }
   },
@@ -158,17 +160,20 @@
     "schema": {
       "category": "Normalization",
       "attributes": [
-        { "name": "alpha", "default": 0.0001 },
-        { "name": "beta", "default": 0.75 },
-        { "name": "kappa", "default": 1 },
-        { "name": "size", "default": 1 }
+        { "name": "alpha", "type": "float32", "default": 0.0001 },
+        { "name": "beta", "type": "float32", "default": 0.75 },
+        { "name": "kappa", "type": "float32", "default": 1 },
+        { "name": "size", "type": "int32", "default": 1 }
       ]
     }
   },
   {
     "name": "route",
     "schema": {
-      "category": "Tensor"
+      "category": "Tensor",
+      "attributes": [
+        { "name": "layers", "type": "string" }
+      ]
     }
   },
   {
@@ -205,7 +210,7 @@
     "name": "upsample",
     "schema": {
       "attributes": [
-        { "name": "stride", "default": 2 }
+        { "name": "stride", "type": "int32", "default": 2 }
       ]
     }
   },
@@ -213,13 +218,47 @@
     "name": "yolo",
     "schema": {
       "attributes": [
-        { "name": "classes", "default": 20 },
-        { "name": "num", "default": 1 },
-        { "name": "jitter", "default": 0.2 },
-        { "name": "max", "default": 90 },
-        { "name": "ignore_thresh", "default": 0.5 },
-        { "name": "truth_thresh", "default": 1 },
-        { "name": "random", "default": 0 }
+        { "name": "classes", "type": "int32", "default": 20 },
+        { "name": "num", "type": "int32", "default": 1 },
+        { "name": "jitter", "type": "float32", "default": 0.2 },
+        { "name": "max", "type": "int32", "default": 90 },
+        { "name": "ignore_thresh", "type": "float32", "default": 0.5 },
+        { "name": "truth_thresh", "type": "float32", "default": 1 },
+        { "name": "random", "type": "int32", "default": 0 }
+      ]
+    }
+  },
+  {
+    "name": "net",
+    "schema": {
+      "attributes": [
+        { "name": "batch", "type": "int32", "default": 1 },
+        { "name": "learning_rate", "type": "float32", "default": 0.001 },
+        { "name": "momentum", "type": "float32", "default": 0.9 },
+        { "name": "decay", "type": "float32", "default": 0.0001 },
+        { "name": "subdivisions", "type": "int32", "default": 1 },
+        { "name": "time_steps", "type": "int32", "default": 1 },
+        { "name": "notruth", "type": "int32", "default": 0 },
+        { "name": "random", "type": "int32", "default": 0 },
+        { "name": "adam", "type": "int32", "default": 0 },
+        { "name": "B1", "type": "int32", "default": 0.9 },
+        { "name": "B2", "type": "int32", "default": 0.999 },
+        { "name": "eps", "type": "int32", "default": 0.0000001 },
+        { "name": "height", "type": "int32", "default": 0 },
+        { "name": "width", "type": "int32", "default": 0 },
+        { "name": "channels", "type": "int32", "default": 0 },
+        { "name": "inputs", "type": "int32" },
+        { "name": "max_crop", "type": "int32" },
+        { "name": "min_crop", "type": "int32" },
+        { "name": "max_ratio", "type": "int32" },
+        { "name": "min_ratio", "type": "int32" },
+        { "name": "center", "type": "int32", "default": 0 },
+        { "name": "clip", "type": "int32", "default": 0 },
+        { "name": "angle", "type": "float32", "default": 0 },
+        { "name": "aspect", "type": "float32", "default": 1 },
+        { "name": "saturation", "type": "float32", "default": 1 },
+        { "name": "exposure", "type": "float32", "default": 1 },
+        { "name": "hue", "type": "float32", "default": 0 }
       ]
     }
   }

+ 152 - 133
src/darknet.js

@@ -17,25 +17,33 @@ darknet.ModelFactory = class {
     open(context, host) {
         return darknet.Metadata.open(host).then((metadata) => {
             const identifier = context.identifier;
-            try {
-                const reader = new darknet.CfgReader(context.text);
-                const cfg = reader.read();
-                return new darknet.Model(metadata, cfg);
-            }
-            catch (error) {
-                let message = error && error.message ? error.message : error.toString();
-                message = message.endsWith('.') ? message.substring(0, message.length - 1) : message;
-                throw new darknet.Error(message + " in '" + identifier + "'.");
-            }
+            const parts = identifier.split('.');
+            parts.pop();
+            const basename = parts.join('.');
+            return context.request(basename + '.weights', null).then((weights) => {
+                return this._openModel(metadata, identifier, context.text, weights);
+            }).catch(() => {
+                return this._openModel(metadata, identifier, context.text, null);
+            });
         });
     }
+    _openModel( metadata, identifier, cfg, weights) {
+        try {
+            return new darknet.Model(metadata, cfg, weights);
+        }
+        catch (error) {
+            let message = error && error.message ? error.message : error.toString();
+            message = message.endsWith('.') ? message.substring(0, message.length - 1) : message;
+            throw new darknet.Error(message + " in '" + identifier + "'.");
+        }
+    }
 };
 
 darknet.Model = class {
 
-    constructor(metadata, cfg) {
+    constructor(metadata, cfg, weights) {
         this._graphs = [];
-        this._graphs.push(new darknet.Graph(metadata, cfg));
+        this._graphs.push(new darknet.Graph(metadata, cfg, weights));
     }
 
     get format() {
@@ -49,45 +57,105 @@ darknet.Model = class {
 
 darknet.Graph = class {
     
-    constructor(metadata, cfg) {
+    constructor(metadata, cfg, weights) {
         this._inputs = [];
         this._outputs = [];
         this._nodes = [];
 
-        if (cfg.length === 0) {
+        // read_cfg
+        let sections = [];
+        let section = null;
+        let lines = cfg.split('\n');
+        let nu = 0;
+        while (lines.length > 0) {
+            nu++;
+            let line = lines.shift();
+            line = line.replace(/\s/g, '');
+            if (line.length > 0) {
+                switch (line[0]) {
+                    case '#':
+                    case ';':
+                        break;
+                    case '[': {
+                        section = {};
+                        section.type = line[line.length - 1] === ']' ? line.substring(1, line.length - 1) : line.substring(1);
+                        section.options = {};
+                        sections.push(section);
+                        break;
+                    }
+                    default: {
+                        if (section) {
+                            let property = line.split('=');
+                            if (property.length != 2) {
+                                throw new darknet.Error("Invalid cfg '" + line + "' at line " + nu.toString() + ".");
+                            }
+                            let key = property[0].trim();
+                            let value = property[1].trim();
+                            section.options[key] = value;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
+        for (let section of sections) {
+            section.values = {};
+            const schema = metadata.getSchema(section.type);
+            if (schema && schema.attributes) {
+                for (let attribute of schema.attributes) {
+                    if (attribute.name) {
+                        if (section.options[attribute.name] !== undefined) {
+                            switch (attribute.type) {
+                                case 'int32':
+                                    section.values[attribute.name] = parseInt(section.options[attribute.name], 10);
+                                    break;
+                                case 'float32':
+                                    section.values[attribute.name] = parseFloat(section.options[attribute.name]);
+                                    break;
+                                case 'string':
+                                    section.values[attribute.name] = section.options[attribute.name];
+                                    break;
+                            }
+                        }
+                        else if (attribute.default !== undefined) {
+                            section.values[attribute.name] = attribute.default
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sections.length === 0) {
             throw new darknet.Error('Config file has no sections.');
         }
 
-        let net = cfg.shift();
-        if (net.__type__ !== 'net' && net.__type__ !== 'network') {
+        let net = sections.shift();
+        if (net.type !== 'net' && net.type !== 'network') {
             throw new darknet.Error('First section must be [net] or [network].');
         }
 
-        net.width = net.width ? Number.parseInt(net.width, 10) : 0;
-        net.height = net.height ? Number.parseInt(net.height, 10) : 0;
-        net.channels = net.channels ? Number.parseInt(net.channels, 10) : 0;
-
-        const inputType = new darknet.TensorType('float32', new darknet.TensorShape([ net.width, net.height, net.channels ]));
+        const inputType = new darknet.TensorType('float32', new darknet.TensorShape([ net.values.width, net.values.height, net.values.channels ]));
 
-        const input = 'input';
-        this._inputs.push(new darknet.Parameter(input, true, [
-            new darknet.Argument(input, inputType, null)
+        const inputName = 'input';
+        this._inputs.push(new darknet.Parameter(inputName, true, [
+            new darknet.Argument(inputName, inputType, null)
         ]));
 
-        for (let i = 0; i < cfg.length; i++) {
-            cfg[i]._outputs = [ i.toString() ];
+        for (let i = 0; i < sections.length; i++) {
+            sections[i]._outputs = [ i.toString() ];
         }
 
-        let inputs = [ 'input' ];
-        for (let i = 0; i < cfg.length; i++) {
-            const layer = cfg[i];
+        let inputs = [ inputName ];
+        for (let i = 0; i < sections.length; i++) {
+            const layer = sections[i];
             layer._inputs = inputs;
             inputs = [ i.toString() ];
-            switch (layer.__type__) {
+            switch (layer.type) {
                 case 'shortcut': {
-                    let from = Number.parseInt(layer.from, 10);
+                    let from = Number.parseInt(layer.options.from, 10);
                     from = (from >= 0) ? from : (i + from);
-                    const shortcut = cfg[from];
+                    const shortcut = sections[from];
                     if (shortcut) {
                         layer._inputs.push(shortcut._outputs[0]);
                     }
@@ -95,10 +163,10 @@ darknet.Graph = class {
                 }
                 case 'route': {
                     layer._inputs = [];
-                    const routes = layer.layers.split(',').map((route) => Number.parseInt(route.trim(), 10));
+                    const routes = layer.options.layers.split(',').map((route) => Number.parseInt(route.trim(), 10));
                     for (let j = 0; j < routes.length; j++) {
                         const index = (routes[j] < 0) ? i + routes[j] : routes[j];
-                        const route = cfg[index];
+                        const route = sections[index];
                         if (route) {
                             layer._inputs.push(route._outputs[0]);
                         }
@@ -107,12 +175,12 @@ darknet.Graph = class {
                 }
             }
         }
-        for (let i = 0; i < cfg.length; i++) {
-            this._nodes.push(new darknet.Node(metadata, net, cfg[i], i.toString()));
+        for (let i = 0; i < sections.length; i++) {
+            this._nodes.push(new darknet.Node(metadata, net, sections[i], i.toString()));
         }
 
-        if (cfg.length > 0) {
-            const lastLayer = cfg[cfg.length - 1];
+        if (sections.length > 0) {
+            const lastLayer = sections[sections.length - 1];
             for (let i = 0; i < lastLayer._outputs.length; i++) {
                 this._outputs.push(new darknet.Parameter('output' + (i > 1 ? i.toString() : ''), true, [
                     new darknet.Argument(lastLayer._outputs[i], null, null)
@@ -184,7 +252,7 @@ darknet.Node = class {
     constructor(metadata, net, layer, name) {
         this._name = name;
         this._metadata = metadata;
-        this._operator = layer.__type__;
+        this._operator = layer.type;
         this._attributes = [];
         this._inputs = [];
         this._outputs = [];
@@ -199,31 +267,27 @@ darknet.Node = class {
                 return new darknet.Argument(output, null, null);
             })));
         }
-        switch (layer.__type__) {
+        switch (layer.type) {
             case 'convolutional':
             case 'deconvolutional':
-                layer.filters = layer.filters ? Number.parseInt(layer.filters, 10) : 1;
-                layer.size = layer.size ? Number.parseInt(layer.size, 10) : 1;
-                this._initializer('biases', [ layer.filters ]);
-                this._initializer('weights', [ net.channels, layer.size, layer.size, layer.filters ]);
-                this._batch_normalize(metadata, net, layer, layer.filters);
-                this._activation(metadata, layer, 'logistic');
+                this._initializer('biases', [ layer.values.filters ]);
+                this._initializer('weights', [ net.values.channels, layer.values.size, layer.values.size, layer.values.filters ]);
+                this._batch_normalize(metadata, net, layer, layer.values.filters);
+                this._activation(metadata, net, layer, 'logistic');
                 break;
             case 'connected':
-                layer.output = layer.output ? Number.parseInt(layer.output, 10) : 1; 
-                this._initializer('biases', [ layer.output ]);
+                this._initializer('biases', [ layer.values.output ]);
                 this._initializer('weights');
-                this._batch_normalize(metadata, net, layer, layer.output);
-                this._activation(metadata, layer, 'logistic');
+                this._batch_normalize(metadata, net, layer, layer.values.output);
+                this._activation(metadata, net, layer);
                 break;
             case 'crnn':
                 this._batch_normalize(metadata, net, layer);
-                this._activation(metadata, layer, "logistic");
+                this._activation(metadata, net, layer);
                 break;
             case 'rnn':
-                layer.output = layer.output ? Number.parseInt(layer.output, 10) : 1; 
-                this._batch_normalize(metadata, net, layer, layer.output);
-                this._activation(metadata, layer, "logistic");
+                this._batch_normalize(metadata, net, layer, layer.values.output);
+                this._activation(metadata, net, layer);
                 break;
             case 'gru':
                 this._batch_normalize(metadata, net, layer);
@@ -232,27 +296,25 @@ darknet.Node = class {
                 this._batch_normalize(metadata, net, layer);
                 break;
             case 'shortcut':
-                this._activation(metadata, net, layer, "linear");
+                this._activation(metadata, net, layer);
                 break;
             case 'batch_normalize':
-                this._initializer('scale', [ layer.size ]);
-                this._initializer('mean', [ layer.size ]);
-                this._initializer('variance', [ layer.size ]);
+                this._initializer('scale', [ layer.values.size ]);
+                this._initializer('mean', [ layer.values.size ]);
+                this._initializer('variance', [ layer.values.size ]);
                 break;
         }
 
-        switch (layer.__type__) {
+        switch (layer.type) {
             case 'shortcut':
-                delete layer.from;
+                delete layer.options.from;
                 break;
             case 'route':
-                delete layer.layers;
+                delete layer.options.layers;
                 break;
         }
-        for (let key of Object.keys(layer)) {
-            if (key != '__type__' && key != '_inputs' && key != '_outputs') {
-                this._attributes.push(new darknet.Attribute(metadata, this._operator, key, layer[key]));
-            }
+        for (let key of Object.keys(layer.options)) {
+            this._attributes.push(new darknet.Attribute(metadata, this._operator, key, layer.options[key]));
         }
     }
 
@@ -297,17 +359,20 @@ darknet.Node = class {
     }
 
     _batch_normalize(metadata, net, layer, size) {
-        if (layer.batch_normalize == "1") {
-            const batch_normalize_layer = { __type__: 'batch_normalize', _inputs: [], _outputs: [], size: size || 0 };
-            this._chain.push(new darknet.Node(metadata, net, batch_normalize_layer, this._name + ':batch_normalize'));
-            delete layer.batch_normalize;
+        if (layer.values.batch_normalize === 1) {
+            const batch_normalize_layer = { type: 'batch_normalize', options: {}, values: { size: size || 0 }, _inputs: [], _outputs: [] };
+            this._chain.push(new darknet.Node(metadata, net, batch_normalize_layer, ''));
         }
+        delete layer.options.batch_normalize;
     }
 
-    _activation(metadata, net, layer, defaultValue) {
-        if (layer.activation && layer.activation != defaultValue) {
-            this._chain.push(new darknet.Node(metadata, net, { __type__: layer.activation, _inputs: [], _outputs: [] }, this._name + ':activation'));
-            delete layer.activation;
+    _activation(metadata, net, layer) {
+        const attributeSchema = metadata.getAttributeSchema(layer.type, 'activation');
+        if (attributeSchema) {
+            if (layer.options.activation !== attributeSchema.default) {
+                this._chain.push(new darknet.Node(metadata, net, { type: layer.options.activation, options: {}, values: {}, _inputs: [], _outputs: [] }, ''));
+            }
+            delete layer.options.activation;
         }
     }
 };
@@ -317,27 +382,19 @@ darknet.Attribute = class {
     constructor(metadata, operator, name, value) {
         this._name = name;
         this._value = value;
-
-        const intValue = Number.parseInt(this._value, 10);
-        if (!Number.isNaN(this._value - intValue)) {
-            this._value = intValue;
-        }
-        else {
-            const floatValue = Number.parseFloat(this._value);
-            if (!Number.isNaN(this._value - floatValue)) {
-                this._value = floatValue;
-            }
-        }
-
         const schema = metadata.getAttributeSchema(operator, name);
         if (schema) {
-            if (schema.type == 'boolean') {
-                switch (this._value) {
-                    case 0: this._value = false; break;
-                    case 1: this._value = true; break;
+            this._type = schema.type || '';
+            switch (this._type) {
+                case 'int32': {
+                    this._value = parseInt(this._value, 10);
+                    break;
+                }
+                case 'float32': {
+                    this._value = parseFloat(this._value);
+                    break;
                 }
             }
-
             if (Object.prototype.hasOwnProperty.call(schema, 'visible') && !schema.visible) {
                 this._visible = false;
             }
@@ -353,6 +410,10 @@ darknet.Attribute = class {
         return this._name;
     }
 
+    get type() {
+        return this._type;
+    }
+
     get value() {
         return this._value;
     }
@@ -407,7 +468,7 @@ darknet.TensorType = class {
     }
 
     toString() {
-        return (this.dataType || '?') + this._shape.toString();
+        return (this._dataType || '?') + this._shape.toString();
     }
 };
 
@@ -482,48 +543,6 @@ darknet.Metadata = class {
     }
 };
 
-darknet.CfgReader = class {
-
-    constructor(text) {
-        this._lines = text.split('\n');
-        this._line = 0;
-    }
-
-    read() {
-        let options = [];
-        let section = null;
-        while (this._line < this._lines.length) {
-            let line = this._lines[this._line];
-            line = line.replace(/\s/g, '');
-            if (line.length > 0) {
-                switch (line[0]) {
-                    case '#':
-                    case ';':
-                        break;
-                    case '[':
-                        section = {};
-                        section.__type__ = line[line.length - 1] === ']' ? line.substring(1, line.length - 1) : line.substring(1);
-                        options.push(section);
-                        break;
-                    default:
-                        if (section) {
-                            let property = line.split('=');
-                            if (property.length != 2) {
-                                throw new darknet.Error("Invalid cfg '" + line + "' at line " + (this._line + 1).toString() + ".");
-                            }
-                            let key = property[0].trim();
-                            let value = property[1].trim();
-                            section[key] = value;
-                        }
-                        break;
-                }
-            }
-            this._line++;
-        }
-        return options;
-    }
-};
-
 darknet.Error = class extends Error {
     constructor(message) {
         super(message);