tengine.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // Experimental
  2. import * as base from './base.js';
  3. const tengine = {};
  4. tengine.ModelFactory = class {
  5. match(context) {
  6. const reader = tengine.Reader.open(context.stream);
  7. if (reader) {
  8. context.type = 'tengine';
  9. context.target = reader;
  10. }
  11. }
  12. async open(context) {
  13. const metadata = await tengine.Metadata.open(context);
  14. const reader = context.target;
  15. reader.read();
  16. return new tengine.Model(metadata, reader);
  17. }
  18. };
  19. tengine.Model = class {
  20. constructor(metadata, reader) {
  21. this.format = `Tengine v${reader.version}`;
  22. this.metadata = new Map();
  23. this.metadata.set('source', reader.source);
  24. this.graphs = reader.graphs.map((graph) => new tengine.Graph(metadata, graph));
  25. }
  26. };
  27. tengine.Graph = class {
  28. constructor(metadata, graph) {
  29. this.name = graph.id.toString();
  30. this.inputs = [];
  31. this.outputs = [];
  32. this.nodes = [];
  33. const tensors = graph.tensors.map((tensor) => new tengine.Value(tensor));
  34. for (const input of graph.inputs) {
  35. const node = graph.nodes[input];
  36. this.inputs.push(new tengine.Argument(node.name, node.outputs.map((output) => tensors[output])));
  37. }
  38. for (const output of graph.outputs) {
  39. const node = graph.nodes[output];
  40. this.outputs.push(new tengine.Argument(node.name, node.outputs.map((output) => tensors[output])));
  41. }
  42. for (const node of graph.nodes) {
  43. switch (node.type) {
  44. case 'INPUT':
  45. case 'Const':
  46. break;
  47. default:
  48. this.nodes.push(new tengine.Node(metadata, node, tensors));
  49. break;
  50. }
  51. }
  52. }
  53. };
  54. tengine.Argument = class {
  55. constructor(name, value) {
  56. this.name = name;
  57. this.value = value;
  58. }
  59. };
  60. tengine.Value = class {
  61. constructor(tensor) {
  62. this.name = tensor.name;
  63. this.type = new tengine.TensorType(tensor.dataType, new tengine.TensorShape(tensor.dims));
  64. this.initializer = (tensor.type === 2) ? new tengine.Tensor(this.type, tensor.buffer) : null;
  65. }
  66. };
  67. tengine.Node = class {
  68. constructor(metadata, node, tensors) {
  69. this.name = node.name;
  70. const type = node.type;
  71. const version = node.version;
  72. this.inputs = [];
  73. this.outputs = [];
  74. this.attributes = [];
  75. this.type = metadata.type(type, version) || { name: type };
  76. for (let i = 0; i < node.params.length; i++) {
  77. const metadata = (this.type && this.type.attributes && i < this.type.attributes.length) ? this.type.attributes[i] : null;
  78. const name = metadata ? metadata.name : i.toString();
  79. this.attributes.push(new tengine.Attribute(metadata, name, node.params[i]));
  80. }
  81. const inputs = node.inputs;
  82. let inputIndex = 0;
  83. if (this.type && this.type.inputs) {
  84. for (const inputDef of this.type.inputs) {
  85. if (inputIndex < inputs.length || inputDef.option != 'optional') {
  86. const inputCount = (inputDef.option == 'variadic') ? (inputs.length - inputIndex) : 1;
  87. const inputArguments = inputs.slice(inputIndex, inputIndex + inputCount).filter((id) => id != '' || inputDef.option != 'optional').map((id) => tensors[id]);
  88. this.inputs.push(new tengine.Argument(inputDef.name, inputArguments));
  89. inputIndex += inputCount;
  90. }
  91. }
  92. } else {
  93. this.inputs.push(...inputs.slice(inputIndex).map((id, index) => {
  94. const inputName = ((inputIndex + index) == 0) ? 'input' : (inputIndex + index).toString();
  95. return new tengine.Argument(inputName, [ tensors[id] ]);
  96. }));
  97. }
  98. const outputs = node.outputs;
  99. let outputIndex = 0;
  100. if (this.type && this.type.outputs) {
  101. for (const outputDef of this.type.outputs) {
  102. if (outputIndex < outputs.length || outputDef.option != 'optional') {
  103. const outputCount = (outputDef.option == 'variadic') ? (outputs.length - outputIndex) : 1;
  104. const outputArguments = outputs.slice(outputIndex, outputIndex + outputCount).map((id) => tensors[id]);
  105. this.outputs.push(new tengine.Argument(outputDef.name, outputArguments));
  106. outputIndex += outputCount;
  107. }
  108. }
  109. } else {
  110. this.outputs.push(...outputs.slice(outputIndex).map((id, index) => {
  111. const outputName = ((outputIndex + index) == 0) ? 'output' : (outputIndex + index).toString();
  112. return new tengine.Argument(outputName, [ tensors[id] ]);
  113. }));
  114. }
  115. }
  116. };
  117. tengine.Attribute = class {
  118. constructor(metadata, key, value) {
  119. this.type = '';
  120. this.name = key;
  121. this.value = value;
  122. if (metadata) {
  123. this.name = metadata.name;
  124. if (metadata.type) {
  125. this.type = metadata.type;
  126. }
  127. if (metadata.visible === false) {
  128. this.visible = false;
  129. } else if (Object.prototype.hasOwnProperty.call(metadata, 'default')) {
  130. if (this.value == metadata.default || (this.value && this.value.toString() == metadata.default.toString())) {
  131. this.visible = false;
  132. }
  133. }
  134. }
  135. }
  136. };
  137. tengine.Tensor = class {
  138. constructor(type, values) {
  139. this.type = type;
  140. this.values = values;
  141. }
  142. };
  143. tengine.TensorType = class {
  144. constructor(dataType, shape) {
  145. switch (dataType) {
  146. case 0: this.dataType = 'float32'; break;
  147. case 1: this.dataType = 'float16'; break;
  148. case 2: this.dataType = 'int8'; break;
  149. case 3: this.dataType = 'uint8'; break;
  150. case 4: this.dataType = 'int32'; break;
  151. case 5: this.dataType = 'int16'; break;
  152. default: throw new tengine.Error(`Unsupported data type'${dataType}'.`);
  153. }
  154. this.shape = shape;
  155. }
  156. toString() {
  157. return this.dataType + this.shape.toString();
  158. }
  159. };
  160. tengine.TensorShape = class {
  161. constructor(dimensions) {
  162. this.dimensions = dimensions;
  163. }
  164. toString() {
  165. return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',')}]`) : '';
  166. }
  167. };
  168. tengine.Metadata = class {
  169. static async open(context) {
  170. if (tengine.Metadata._metadata) {
  171. return tengine.Metadata._metadata;
  172. }
  173. try {
  174. const data = await context.request('tengine-metadata.json');
  175. tengine.Metadata._metadata = new tengine.Metadata(data);
  176. return tengine.Metadata._metadata;
  177. } catch (error) {
  178. tengine.Metadata._metadata = new tengine.Metadata(null);
  179. return tengine.Metadata._metadata;
  180. }
  181. }
  182. constructor(data) {
  183. this._map = new Map();
  184. if (data) {
  185. const metadata = JSON.parse(data);
  186. for (const item of metadata) {
  187. if (item.name) {
  188. const version = item.version || 0;
  189. const name = `${item.name}:${version}`;
  190. this._map.set(name, item);
  191. }
  192. }
  193. }
  194. }
  195. type(name, version) {
  196. let current = version;
  197. while (current > 0) {
  198. if (this._map.has(`${name}:${current}`)) {
  199. break;
  200. }
  201. current--;
  202. }
  203. if (current >= 0) {
  204. const schema = this._map.get(`${name}:${current}`);
  205. if (current !== version) {
  206. this._map.set(`${name}:${version}`, schema);
  207. }
  208. return schema;
  209. }
  210. return null;
  211. }
  212. };
  213. tengine.Reader = class {
  214. static open(stream) {
  215. if (stream && stream.length > 4) {
  216. const buffer = stream.peek(2);
  217. if (buffer[0] < 4 && buffer[1] === 0) {
  218. return new tengine.Reader(stream);
  219. }
  220. }
  221. return null;
  222. }
  223. constructor(stream) {
  224. this.stream = stream;
  225. // https://github.com/OAID/Tengine/wiki/The-format-of-tmfile
  226. // https://github.com/OAID/Tengine/blob/tengine-lite/source/serializer/tmfile/tm2_format.h
  227. }
  228. read() {
  229. const types = new Map();
  230. const register = (index, version, name, params) => {
  231. types.set(`${index}:${version}`, { name: name, params: params });
  232. };
  233. const operator = (index, version) => {
  234. let current = version;
  235. while (current >= 0) {
  236. if (types.has(`${index}:${current}`)) {
  237. break;
  238. }
  239. current--;
  240. }
  241. if (current >= 0) {
  242. const schema = types.get(`${index}:${current}`);
  243. if (current !== version) {
  244. types.set(`${index}:${version}`, schema);
  245. }
  246. return schema;
  247. }
  248. return null;
  249. };
  250. register(0, 0, 'Accuracy', []);
  251. register(1, 0, 'BatchNormalization', [ 'f', 'f', 'i' ]);
  252. register(2, 0, 'BilinearResize', [ 'f', 'f', 'i' ]);
  253. register(3, 0, 'Concat', [ 'i' ]);
  254. register(4, 0, 'Const', []);
  255. register(5, 0, 'Convolution', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  256. register(6, 0, 'Deconvolution', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  257. register(7, 0, 'DetectionOutput', [ 'i', 'i', 'i', 'f', 'f' ]);
  258. register(8, 0, 'DropOut', []);
  259. register(9, 0, 'Eltwise', [ 'i', 'i' ]);
  260. register(10, 0, 'Flatten', [ 'i' ]);
  261. register(11, 0, 'FullyConnected', [ 'i' ]);
  262. register(12, 0, 'INPUT', []);
  263. register(13, 0, 'LRN', [ 'i', 'f', 'f', 'i', 'f' ]);
  264. register(14, 0, 'Normalize', [ 'i', 'i' ]);
  265. register(15, 0, 'Permute', [ 'i', 'i', 'i', 'i', 'i' ]);
  266. register(16, 0, 'Pooling', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  267. register(17, 0, 'Prelu', []);
  268. register(18, 0, 'PriorBox', [ 'f[]', 'f[]', 'f[]', 'f[]', 'i', 'i', 'i', 'i', 'i', 'f', 'f', 'f', 'i', 'i' ]);
  269. register(19, 0, 'Region', [ 'i', 'i', 'i', 'i', 'f', 'f', 'f[]' ]);
  270. register(20, 0, 'ReLU', [ 'f' ]);
  271. register(21, 0, 'ReLU6', []);
  272. register(22, 0, 'Reorg', [ 'i' ]);
  273. register(23, 0, 'Reshape', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  274. // register(23, 0, 'Reshape', [ 'i', 'i', 'i[]' ]);
  275. register(24, 0, 'RoiPooling', [ 'i', 'i', 'f' ]);
  276. register(25, 0, 'RPN', [ 'f[]', 'f[]', 'i', 'i', 'i', 'i', 'i', 'f', 'anchors' ]);
  277. register(26, 0, 'Scale', [ 'i', 'i', 'i' ]);
  278. register(27, 0, 'Slice', [ 'i', 'i[]', 'i[]', 'i[]', 'i', 'i', 'i', 'i', 'i' ]);
  279. register(28, 0, 'SoftMax', [ 'i' ]);
  280. register(29, 0, 'Split', [ 'i', 'i', 'boolean', 'boolean', 'i[]' ]);
  281. register(30, 0, 'DetectionPostProcess', [ 'i', 'i', 'f', 'f', 'i', 'f[]' ]);
  282. register(31, 0, 'Gemm', [ 'f', 'f', 'i', 'i' ]);
  283. register(32, 0, 'Generic', [ 'i', 'i', 'string' ]);
  284. register(33, 0, 'Logistic', []);
  285. register(34, 0, 'LSTM', [ 'f', 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  286. register(35, 0, 'RNN', [ 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  287. register(36, 0, 'TanH', []);
  288. register(37, 0, 'Sigmoid', []);
  289. register(38, 0, 'Squeeze', [ 'i', 'i', 'i', 'i' ]);
  290. register(39, 0, 'FusedbnScaleRelu', []);
  291. register(40, 0, 'Pad', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'f' ]);
  292. register(41, 0, 'StridedSlice', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  293. register(42, 0, 'ArgMax', [ 'i' ]);
  294. register(43, 0, 'ArgMin', [ 'i' ]);
  295. register(44, 0, 'TopKV2', [ 'i', 'i' ]);
  296. register(45, 0, 'Reduction', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  297. register(46, 0, 'Max', []);
  298. register(47, 0, 'Min', []);
  299. register(48, 0, 'GRU', [ 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  300. register(49, 0, 'Addn', 'i');
  301. register(50, 0, 'SwapAxis', [ 'i', 'i' ]);
  302. register(51, 0, 'Upsample', [ 'f' ]);
  303. register(52, 0, 'SpaceToBatchND', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  304. register(53, 0, 'BatchToSpaceND', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  305. register(54, 0, 'Resize', [ 'f', 'f', 'i' ]);
  306. register(55, 0, 'ShuffleChannel', [ 'i' ]);
  307. register(56, 0, 'Crop', [ 'i', 'i', 'i', 'i', 'i', 'i', 'boolean', 'i', 'i' ]);
  308. register(57, 0, 'ROIAlign', [ 'i', 'i', 'f' ]);
  309. register(58, 0, 'Psroipooling', [ 'i', 'i', 'f', 'i' ]);
  310. register(59, 0, 'Unary', [ 'i' ]);
  311. register(60, 0, 'Expanddims', [ 'i' ]);
  312. register(61, 0, 'Bias', [ 'i' ]);
  313. register(62, 0, 'Noop', []);
  314. register(63, 0, 'Threshold', [ 'f' ]);
  315. register(64, 0, 'Hardsigmoid', [ 'f', 'f' ]);
  316. register(65, 0, 'Embed', [ 'f', 'f', 'f', 'f' ]);
  317. register(66, 0, 'InstanceNorm', [ 'f' ]);
  318. register(67, 0, 'MVN', [ 'i', 'i', 'f' ]);
  319. register(68, 0, 'Absval', []);
  320. register(69, 0, 'Cast', [ 'i', 'i' ]);
  321. register(70, 0, 'HardSwish', [ 'f', 'f' ]);
  322. register(71, 0, 'Interp', [ 'i', 'f', 'f', 'i', 'i' ]);
  323. register(72, 0, 'SELU', [ 'f', 'f' ]);
  324. register(73, 0, 'ELU', [ 'f' ]);
  325. register(74, 0, 'BroadMul', []);
  326. register(75, 0, 'Logical', [ 'i' ]);
  327. register(76, 0, 'Gather', [ 'i', 'i' ]);
  328. register(77, 0, 'Transpose', [ 'i[]' ]);
  329. register(78, 0, 'Comparison', [ 'i' ]);
  330. register(79, 0, 'SpaceToDepth', [ 'i' ]);
  331. register(80, 0, 'DepthToSpace', [ 'i' ]);
  332. register(81, 0, 'Reverse', []);
  333. register(82, 0, 'SparseToDense', [ 'i','i','i' ]);
  334. register(83, 0, 'Ceil', []);
  335. register(84, 0, 'SquaredDifference', []);
  336. register(85, 0, 'Round', []);
  337. register(86, 0, 'ZerosLike', []);
  338. register(87, 0, 'Clip', [ 'f','f' ]);
  339. register(88, 0, 'Unsqueeze', [ 'i[]' ]);
  340. register(89, 0, 'ReduceL2', [ 'i','i' ]);
  341. register(90, 0, 'Mean', []);
  342. register(91, 0, 'MatMul', []);
  343. register(92, 0, 'Expand', ['i[]']);
  344. register(93, 0, 'Scatter', ['i','boolean']);
  345. register(94, 0, 'Shape', []);
  346. register(95, 0, 'Where', []);
  347. register(96, 0, 'Tile', ['i','i']);
  348. register(97, 0, 'Mish', []);
  349. register(98, 0, 'L2Pool', []);
  350. register(99, 0, 'LogSoftmax', []);
  351. register(100, 0, 'ReLU1', []);
  352. register(101, 0, 'L2Normalization', []);
  353. register(102, 0, 'PackModel', ['i','i']);
  354. register(103, 0, 'Num', []);
  355. const buffer = this.stream.peek();
  356. const reader = new tengine.BinaryReader(buffer);
  357. this._majorVersion = reader.uint16();
  358. this._minorVersion = reader.uint16();
  359. if (this._majorVersion !== 2) {
  360. throw new tengine.Error(`Unsupported format version 'v${this._majorVersion}.${this._minorVersion}'.`);
  361. }
  362. this._compileVersion = reader.uint16();
  363. reader.skip(2); // struct align
  364. reader.seek(reader.uint32()); // root table
  365. this._originalFormat = reader.int32();
  366. this._subFormat = reader.int32();
  367. this.graphs = [];
  368. const subgraphOffsets = reader.uint32s();
  369. for (const subgraphOffset of subgraphOffsets) {
  370. reader.seek(subgraphOffset);
  371. const subgraph = {};
  372. subgraph.id = reader.int32();
  373. subgraph.graphLayout = reader.int32();
  374. /*
  375. if (graphLayout == 0) {
  376. return "NCHW";
  377. }
  378. if (graphLayout == 1) {
  379. return "NHWC";
  380. }
  381. */
  382. subgraph.originalLayout = reader.int32();
  383. subgraph.inputs = reader.uint32s();
  384. subgraph.outputs = reader.uint32s();
  385. const nodeOffsets = reader.uint32s();
  386. const tensorOffsets = reader.uint32s();
  387. const bufferOffsets = reader.uint32s();
  388. subgraph.name = reader.string();
  389. subgraph.nodes = [];
  390. subgraph.tensors = [];
  391. this.graphs.push(subgraph);
  392. // nodes
  393. for (const nodeOffset of nodeOffsets) {
  394. reader.seek(nodeOffset);
  395. const node = {};
  396. node.id = reader.int32();
  397. node.inputs = reader.uint32s();
  398. node.outputs = reader.uint32s();
  399. const typeOffset = reader.int32();
  400. node.name = reader.string();
  401. const attributeOffsets = reader.uint32s();
  402. node.dynamicShape = reader.boolean();
  403. reader.seek(typeOffset);
  404. node.version = reader.int32();
  405. const index = reader.int32();
  406. const paramsOffset = reader.uint32();
  407. const schema = operator(index, node.version);
  408. node.type = schema ? schema.name : index.toString();
  409. const paramTypes = schema ? schema.params : [];
  410. node.params = [];
  411. if (paramsOffset) {
  412. reader.seek(paramsOffset);
  413. for (const paramType of paramTypes) {
  414. if (paramType !== 'boolean') {
  415. reader.align(4);
  416. }
  417. switch (paramType) {
  418. case 'i':
  419. node.params.push(reader.int32());
  420. break;
  421. case 'f':
  422. node.params.push(reader.float32());
  423. break;
  424. case 'i[]':
  425. node.params.push(reader.int32s());
  426. break;
  427. case 'f[]':
  428. node.params.push(reader.float32s());
  429. break;
  430. case 'boolean':
  431. node.params.push(reader.boolean());
  432. break;
  433. case 'string':
  434. node.params.push(reader.string());
  435. break;
  436. case 'anchors':
  437. node.params.push(reader.anchors(4));
  438. break;
  439. default:
  440. throw new tengine.Error(`Unsupported param type '${paramType}' in '${node.type}'.`);
  441. }
  442. }
  443. }
  444. if (node.type === 'Slice') {
  445. node.params[6] = (this._originalFormat == 5) ? node.params[6] : 0;
  446. }
  447. node.attributes = attributeOffsets.map((attributeOffset) => {
  448. reader.seek(attributeOffset);
  449. const name = reader.string();
  450. const value = reader.string();
  451. const type = reader.int32();
  452. return { name: name, value: value, type: type };
  453. });
  454. subgraph.nodes.push(node);
  455. }
  456. // buffers
  457. const buffers = bufferOffsets.map((bufferOffset) => {
  458. reader.seek(bufferOffset);
  459. const size = reader.uint32();
  460. const offset = reader.int32();
  461. if (offset !== 0) {
  462. reader.seek(offset);
  463. return reader.read(size);
  464. }
  465. return null;
  466. });
  467. // tensors
  468. subgraph.tensors = tensorOffsets.map((tensorOffset) => {
  469. reader.seek(tensorOffset);
  470. const tensor = {};
  471. tensor.id = reader.int32();
  472. tensor.buffer = buffers[reader.int32()];
  473. tensor.dims = reader.int32s();
  474. tensor.name = reader.string();
  475. const quantparamsOffset = reader.int32();
  476. tensor.layout = reader.int32();
  477. tensor.type = reader.int32(); // ar = 1, const = 2, input = 3, vdep, unknown
  478. tensor.dataType = reader.int32();
  479. if (quantparamsOffset) {
  480. reader.seek(quantparamsOffset);
  481. tensor.quantparams = {
  482. zeroPoint: reader.int32(),
  483. scale: reader.float32(),
  484. width: reader.int32()
  485. };
  486. }
  487. return tensor;
  488. });
  489. for (const node of subgraph.nodes) {
  490. if (node.type === 'Convolution') {
  491. switch (subgraph.graphLayout) {
  492. case 0: // NCHW
  493. /* eslint-disable prefer-destructuring */
  494. node.params[6] = subgraph.tensors[node.inputs[1]].dims[1];
  495. /* eslint-enable prefer-destructuring */
  496. break;
  497. case 1: // NHWC
  498. /* eslint-disable prefer-destructuring */
  499. node.params[6] = subgraph.tensors[node.inputs[1]].dims[3];
  500. /* eslint-enable prefer-destructuring */
  501. break;
  502. default:
  503. throw new tengine.Error(`Unsupported 'Convolution' layout '${subgraph.graphLayout}'.`);
  504. }
  505. }
  506. }
  507. }
  508. delete this.stream;
  509. }
  510. get version() {
  511. return `${this._majorVersion}.${this._minorVersion}`;
  512. }
  513. get source() {
  514. switch (this._originalFormat) {
  515. case 0: return '';
  516. case 1: return 'Tengine';
  517. case 2: return 'Caffe';
  518. case 3: return 'ONNX';
  519. case 4: return 'MXNet';
  520. case 5: return 'TensorFlow';
  521. case 6: return 'TensorFlow Lite';
  522. case 7: return 'Darknet';
  523. case 8: return `DLA v${this._subFormat}`;
  524. case 9: return 'ncnn';
  525. case 10: return 'MegEngine';
  526. case 11: return 'OneFlow';
  527. case 12: return 'Horizon';
  528. case 13: return 'Bitman';
  529. default: throw new tengine.Error(`Unsupported source '${this._originalFormat}'.`);
  530. }
  531. }
  532. };
  533. tengine.BinaryReader = class extends base.BinaryReader {
  534. string() {
  535. const position = this.uint32();
  536. let content = '';
  537. if (position) {
  538. const next = this._position;
  539. this.seek(position);
  540. const size = this.uint32();
  541. this.seek(this.uint32());
  542. for (let i = 0; i < size - 1; i++) {
  543. content += String.fromCharCode(this._buffer[this._position++]);
  544. }
  545. this.seek(next);
  546. }
  547. return content;
  548. }
  549. uint32s() {
  550. const values = [];
  551. const offset = this.uint32();
  552. if (offset) {
  553. const next = this.position;
  554. this.seek(offset);
  555. const count = this.uint32();
  556. for (let i = 0; i < count; i++) {
  557. values.push(this.uint32());
  558. }
  559. this.seek(next);
  560. }
  561. return values;
  562. }
  563. int32s() {
  564. const values = [];
  565. const offset = this.uint32();
  566. if (offset) {
  567. const next = this.position;
  568. this.seek(offset);
  569. const count = this.uint32();
  570. for (let i = 0; i < count; i++) {
  571. values.push(this.int32());
  572. }
  573. this.seek(next);
  574. }
  575. return values;
  576. }
  577. float32s() {
  578. const values = [];
  579. const offset = this.uint32();
  580. if (offset) {
  581. const next = this.position;
  582. this.seek(offset);
  583. const count = this.uint32();
  584. for (let i = 0; i < count; i++) {
  585. values.push(this.float32());
  586. }
  587. this.seek(next);
  588. }
  589. return values;
  590. }
  591. anchors(length) {
  592. const arrays = [];
  593. const offset = this.uint32();
  594. if (offset) {
  595. const next = this._position;
  596. this.seek(offset);
  597. const count = this.uint32();
  598. for (let i = 0; i < count; i++) {
  599. const array = [];
  600. for (let j = 0; j < length; j++) {
  601. array.push(this.float32());
  602. }
  603. arrays.push(array);
  604. }
  605. this.seek(next);
  606. }
  607. return arrays;
  608. }
  609. };
  610. tengine.Error = class extends Error {
  611. constructor(message) {
  612. super(message);
  613. this.name = 'Error loading Tengine model.';
  614. }
  615. };
  616. export const ModelFactory = tengine.ModelFactory;