tempest-react-sdk 0.38.2 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/design/collect.mjs +19 -0
  3. package/bin/lib/design/functions.mjs +5 -0
  4. package/bin/lib/design/index.mjs +8 -3
  5. package/bin/lib/design/index.test.mjs +31 -0
  6. package/bin/lib/design/scan.mjs +34 -2
  7. package/bin/lib/design/scan.test.mjs +78 -0
  8. package/bin/lib/doctor/doctor.e2e.test.mjs +85 -0
  9. package/bin/tempest.mjs +90 -6
  10. package/dist/audio/level-meter.cjs.map +1 -1
  11. package/dist/audio/level-meter.js.map +1 -1
  12. package/dist/audio/use-audio-recorder.cjs.map +1 -1
  13. package/dist/audio/use-audio-recorder.js.map +1 -1
  14. package/dist/auth/passkey.cjs.map +1 -1
  15. package/dist/auth/passkey.js.map +1 -1
  16. package/dist/auth/use-passkey.cjs.map +1 -1
  17. package/dist/auth/use-passkey.js.map +1 -1
  18. package/dist/br/BrazilMap.cjs.map +1 -1
  19. package/dist/br/BrazilMap.js.map +1 -1
  20. package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
  21. package/dist/br/BrazilStateCitySelect.js.map +1 -1
  22. package/dist/br/BrazilStateMap.cjs.map +1 -1
  23. package/dist/br/BrazilStateMap.js.map +1 -1
  24. package/dist/br/PixQRCode.cjs.map +1 -1
  25. package/dist/br/PixQRCode.js.map +1 -1
  26. package/dist/br/boleto.cjs.map +1 -1
  27. package/dist/br/boleto.js.map +1 -1
  28. package/dist/br/pix.cjs.map +1 -1
  29. package/dist/br/pix.js.map +1 -1
  30. package/dist/br.d.ts +8 -0
  31. package/dist/capture/media-recorder.cjs.map +1 -1
  32. package/dist/capture/media-recorder.js.map +1 -1
  33. package/dist/capture/use-barcode-scanner.cjs.map +1 -1
  34. package/dist/capture/use-barcode-scanner.js.map +1 -1
  35. package/dist/capture/use-screen-capture.cjs.map +1 -1
  36. package/dist/capture/use-screen-capture.js.map +1 -1
  37. package/dist/capture/use-speech-recognition.cjs.map +1 -1
  38. package/dist/capture/use-speech-recognition.js.map +1 -1
  39. package/dist/capture/use-video-recorder.cjs.map +1 -1
  40. package/dist/capture/use-video-recorder.js.map +1 -1
  41. package/dist/charts/types.cjs.map +1 -1
  42. package/dist/charts/types.js.map +1 -1
  43. package/dist/charts.d.ts +8 -0
  44. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  45. package/dist/components/AIChat/AIChat.js.map +1 -1
  46. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  47. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  48. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  49. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  50. package/dist/components/AppBar/AppBar.cjs.map +1 -1
  51. package/dist/components/AppBar/AppBar.js.map +1 -1
  52. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
  53. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
  54. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
  55. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
  56. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
  57. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
  58. package/dist/components/Button/Button.cjs.map +1 -1
  59. package/dist/components/Button/Button.js.map +1 -1
  60. package/dist/components/Calendar/Calendar.cjs.map +1 -1
  61. package/dist/components/Calendar/Calendar.js.map +1 -1
  62. package/dist/components/Carousel/Carousel.cjs.map +1 -1
  63. package/dist/components/Carousel/Carousel.js.map +1 -1
  64. package/dist/components/Chat/Chat.cjs.map +1 -1
  65. package/dist/components/Chat/Chat.js.map +1 -1
  66. package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
  67. package/dist/components/ChipInput/ChipInput.js.map +1 -1
  68. package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
  69. package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
  70. package/dist/components/Combobox/Combobox.cjs.map +1 -1
  71. package/dist/components/Combobox/Combobox.js.map +1 -1
  72. package/dist/components/Command/Command.cjs.map +1 -1
  73. package/dist/components/Command/Command.js.map +1 -1
  74. package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
  75. package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
  76. package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
  77. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  78. package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
  79. package/dist/components/CopyButton/CopyButton.js.map +1 -1
  80. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  81. package/dist/components/DataTable/DataTable.js.map +1 -1
  82. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  83. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  84. package/dist/components/DataTable/EditableCell.cjs.map +1 -1
  85. package/dist/components/DataTable/EditableCell.js.map +1 -1
  86. package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
  87. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  88. package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
  89. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  90. package/dist/components/Drawer/Drawer.cjs.map +1 -1
  91. package/dist/components/Drawer/Drawer.js.map +1 -1
  92. package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  93. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  94. package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
  95. package/dist/components/Dropzone/Dropzone.js.map +1 -1
  96. package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
  97. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  98. package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
  99. package/dist/components/FilterBar/FilterBar.js.map +1 -1
  100. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
  101. package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
  102. package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
  103. package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
  104. package/dist/components/Kanban/Kanban.cjs.map +1 -1
  105. package/dist/components/Kanban/Kanban.js.map +1 -1
  106. package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
  107. package/dist/components/Lightbox/Lightbox.js.map +1 -1
  108. package/dist/components/ListTile/ListTile.cjs.map +1 -1
  109. package/dist/components/ListTile/ListTile.js.map +1 -1
  110. package/dist/components/Markdown/Markdown.cjs.map +1 -1
  111. package/dist/components/Markdown/Markdown.js.map +1 -1
  112. package/dist/components/Markdown/markdown-parse.cjs.map +1 -1
  113. package/dist/components/Markdown/markdown-parse.js.map +1 -1
  114. package/dist/components/Menubar/Menubar.cjs.map +1 -1
  115. package/dist/components/Menubar/Menubar.js.map +1 -1
  116. package/dist/components/Modal/Modal.cjs.map +1 -1
  117. package/dist/components/Modal/Modal.js.map +1 -1
  118. package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
  119. package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
  120. package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
  121. package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
  122. package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
  123. package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
  124. package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
  125. package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
  126. package/dist/components/Page/Page.cjs.map +1 -1
  127. package/dist/components/Page/Page.js.map +1 -1
  128. package/dist/components/Pagination/Pagination.cjs.map +1 -1
  129. package/dist/components/Pagination/Pagination.js.map +1 -1
  130. package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
  131. package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
  132. package/dist/components/PinInput/PinInput.cjs.map +1 -1
  133. package/dist/components/PinInput/PinInput.js.map +1 -1
  134. package/dist/components/Popover/Popover.cjs.map +1 -1
  135. package/dist/components/Popover/Popover.js.map +1 -1
  136. package/dist/components/Progress/Progress.cjs.map +1 -1
  137. package/dist/components/Progress/Progress.js.map +1 -1
  138. package/dist/components/QRCode/qr-encode.cjs.map +1 -1
  139. package/dist/components/QRCode/qr-encode.js.map +1 -1
  140. package/dist/components/Radio/Radio.cjs.map +1 -1
  141. package/dist/components/Radio/Radio.js.map +1 -1
  142. package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
  143. package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
  144. package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
  145. package/dist/components/RatingStars/RatingStars.js.map +1 -1
  146. package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
  147. package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
  148. package/dist/components/Resizable/Resizable.cjs.map +1 -1
  149. package/dist/components/Resizable/Resizable.js.map +1 -1
  150. package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
  151. package/dist/components/Scheduler/Scheduler.js.map +1 -1
  152. package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
  153. package/dist/components/Sidebar/Sidebar.js.map +1 -1
  154. package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
  155. package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
  156. package/dist/components/Slider/Slider.cjs.map +1 -1
  157. package/dist/components/Slider/Slider.js.map +1 -1
  158. package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
  159. package/dist/components/Sparkline/Sparkline.js.map +1 -1
  160. package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
  161. package/dist/components/StepperInput/StepperInput.js.map +1 -1
  162. package/dist/components/Table/Table.cjs.map +1 -1
  163. package/dist/components/Table/Table.js.map +1 -1
  164. package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
  165. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  166. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  167. package/dist/components/Toast/ToastProvider.js.map +1 -1
  168. package/dist/components/Tour/Tour.cjs.map +1 -1
  169. package/dist/components/Tour/Tour.js.map +1 -1
  170. package/dist/components/Transfer/Transfer.cjs.map +1 -1
  171. package/dist/components/Transfer/Transfer.js.map +1 -1
  172. package/dist/components/TreeView/TreeView.cjs.map +1 -1
  173. package/dist/components/TreeView/TreeView.js.map +1 -1
  174. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  175. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  176. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  177. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  178. package/dist/components/Wizard/Wizard.cjs.map +1 -1
  179. package/dist/components/Wizard/Wizard.js.map +1 -1
  180. package/dist/editor/RichTextEditor.cjs.map +1 -1
  181. package/dist/editor/RichTextEditor.js.map +1 -1
  182. package/dist/forms/FormField.cjs.map +1 -1
  183. package/dist/forms/FormField.js.map +1 -1
  184. package/dist/geo/TrajectoryMap.cjs.map +1 -1
  185. package/dist/geo/TrajectoryMap.js.map +1 -1
  186. package/dist/geo/estimate.cjs.map +1 -1
  187. package/dist/geo/estimate.js.map +1 -1
  188. package/dist/geo/projection.cjs.map +1 -1
  189. package/dist/geo/projection.js.map +1 -1
  190. package/dist/hooks/use-event-listener.cjs.map +1 -1
  191. package/dist/hooks/use-event-listener.js.map +1 -1
  192. package/dist/hooks/use-local-storage.cjs.map +1 -1
  193. package/dist/hooks/use-local-storage.js.map +1 -1
  194. package/dist/hooks/use-sortable.cjs.map +1 -1
  195. package/dist/hooks/use-sortable.js.map +1 -1
  196. package/dist/http/api-client.cjs.map +1 -1
  197. package/dist/http/api-client.js.map +1 -1
  198. package/dist/http/errors.cjs.map +1 -1
  199. package/dist/http/errors.js.map +1 -1
  200. package/dist/http/resumable-upload.cjs.map +1 -1
  201. package/dist/http/resumable-upload.js.map +1 -1
  202. package/dist/http/upload-with-progress.cjs.map +1 -1
  203. package/dist/http/upload-with-progress.js.map +1 -1
  204. package/dist/i18n/I18nProvider.cjs.map +1 -1
  205. package/dist/i18n/I18nProvider.js.map +1 -1
  206. package/dist/imaging/canvas.cjs.map +1 -1
  207. package/dist/imaging/canvas.js.map +1 -1
  208. package/dist/imaging.d.ts +5 -0
  209. package/dist/logger/logger.cjs.map +1 -1
  210. package/dist/logger/logger.js.map +1 -1
  211. package/dist/oauth/GoogleSignIn.cjs.map +1 -1
  212. package/dist/oauth/GoogleSignIn.js.map +1 -1
  213. package/dist/offline/create-offline-sync.cjs.map +1 -1
  214. package/dist/offline/create-offline-sync.js.map +1 -1
  215. package/dist/perf/cache-size.cjs +1 -1
  216. package/dist/perf/cache-size.cjs.map +1 -1
  217. package/dist/perf/cache-size.js +27 -6
  218. package/dist/perf/cache-size.js.map +1 -1
  219. package/dist/sse/create-event-stream.cjs.map +1 -1
  220. package/dist/sse/create-event-stream.js.map +1 -1
  221. package/dist/styles.css +1 -1
  222. package/dist/sw/background-sync.cjs.map +1 -1
  223. package/dist/sw/background-sync.js.map +1 -1
  224. package/dist/sw/cache.cjs.map +1 -1
  225. package/dist/sw/cache.js.map +1 -1
  226. package/dist/sw.d.ts +12 -0
  227. package/dist/tabular/compact.cjs.map +1 -1
  228. package/dist/tabular/compact.js.map +1 -1
  229. package/dist/tabular/predictor.cjs.map +1 -1
  230. package/dist/tabular/predictor.js.map +1 -1
  231. package/dist/tabular.d.ts +7 -2
  232. package/dist/tempest-react-sdk.d.ts +133 -6
  233. package/dist/theme/ThemeProvider.cjs.map +1 -1
  234. package/dist/theme/ThemeProvider.js.map +1 -1
  235. package/dist/theme/color.cjs.map +1 -1
  236. package/dist/theme/color.js.map +1 -1
  237. package/dist/theme/create-theme.cjs.map +1 -1
  238. package/dist/theme/create-theme.js.map +1 -1
  239. package/dist/theme/data-viz-ramps.cjs +1 -1
  240. package/dist/theme/data-viz-ramps.cjs.map +1 -1
  241. package/dist/theme/data-viz-ramps.js +1 -1
  242. package/dist/theme/data-viz-ramps.js.map +1 -1
  243. package/dist/utils/storage.cjs.map +1 -1
  244. package/dist/utils/storage.js.map +1 -1
  245. package/dist/vision/core/canvas.cjs +1 -1
  246. package/dist/vision/core/canvas.cjs.map +1 -1
  247. package/dist/vision/core/canvas.js +4 -4
  248. package/dist/vision/core/canvas.js.map +1 -1
  249. package/dist/vision/core/exceptions.cjs +1 -1
  250. package/dist/vision/core/exceptions.cjs.map +1 -1
  251. package/dist/vision/core/exceptions.js +2 -2
  252. package/dist/vision/core/exceptions.js.map +1 -1
  253. package/dist/vision/core/graph.cjs.map +1 -1
  254. package/dist/vision/core/graph.js.map +1 -1
  255. package/dist/vision/core/metadata.cjs +2 -2
  256. package/dist/vision/core/metadata.cjs.map +1 -1
  257. package/dist/vision/core/metadata.js +10 -7
  258. package/dist/vision/core/metadata.js.map +1 -1
  259. package/dist/vision/core/providers.cjs.map +1 -1
  260. package/dist/vision/core/providers.js.map +1 -1
  261. package/dist/vision/core/session.cjs +1 -1
  262. package/dist/vision/core/session.cjs.map +1 -1
  263. package/dist/vision/core/session.js +8 -5
  264. package/dist/vision/core/session.js.map +1 -1
  265. package/dist/vision/core/timing.cjs.map +1 -1
  266. package/dist/vision/core/timing.js.map +1 -1
  267. package/dist/vision/fusion.cjs +2 -0
  268. package/dist/vision/fusion.cjs.map +1 -0
  269. package/dist/vision/fusion.js +42 -0
  270. package/dist/vision/fusion.js.map +1 -0
  271. package/dist/vision/index.cjs +1 -1
  272. package/dist/vision/index.cjs.map +1 -1
  273. package/dist/vision/index.js +23 -20
  274. package/dist/vision/index.js.map +1 -1
  275. package/dist/vision/io/image.cjs.map +1 -1
  276. package/dist/vision/io/image.js.map +1 -1
  277. package/dist/vision/labels.cjs +1 -1
  278. package/dist/vision/labels.cjs.map +1 -1
  279. package/dist/vision/labels.js +7 -4
  280. package/dist/vision/labels.js.map +1 -1
  281. package/dist/vision/luminance.cjs.map +1 -1
  282. package/dist/vision/luminance.js.map +1 -1
  283. package/dist/vision/postprocess/classification.cjs.map +1 -1
  284. package/dist/vision/postprocess/classification.js.map +1 -1
  285. package/dist/vision/postprocess/detection.cjs +1 -1
  286. package/dist/vision/postprocess/detection.cjs.map +1 -1
  287. package/dist/vision/postprocess/detection.js +3 -10
  288. package/dist/vision/postprocess/detection.js.map +1 -1
  289. package/dist/vision/postprocess/segmentation.cjs +1 -1
  290. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  291. package/dist/vision/postprocess/segmentation.js +11 -15
  292. package/dist/vision/postprocess/segmentation.js.map +1 -1
  293. package/dist/vision/preprocess/image.cjs.map +1 -1
  294. package/dist/vision/preprocess/image.js.map +1 -1
  295. package/dist/vision/preprocess/pipeline.cjs +2 -0
  296. package/dist/vision/preprocess/pipeline.cjs.map +1 -0
  297. package/dist/vision/preprocess/pipeline.js +61 -0
  298. package/dist/vision/preprocess/pipeline.js.map +1 -0
  299. package/dist/vision/results.cjs +1 -1
  300. package/dist/vision/results.cjs.map +1 -1
  301. package/dist/vision/results.js +23 -2
  302. package/dist/vision/results.js.map +1 -1
  303. package/dist/vision/tasks/base.cjs +1 -1
  304. package/dist/vision/tasks/base.cjs.map +1 -1
  305. package/dist/vision/tasks/base.js +9 -2
  306. package/dist/vision/tasks/base.js.map +1 -1
  307. package/dist/vision/tasks/classifier.cjs.map +1 -1
  308. package/dist/vision/tasks/classifier.js.map +1 -1
  309. package/dist/vision/tasks/detectClassify.cjs +2 -0
  310. package/dist/vision/tasks/detectClassify.cjs.map +1 -0
  311. package/dist/vision/tasks/detectClassify.js +221 -0
  312. package/dist/vision/tasks/detectClassify.js.map +1 -0
  313. package/dist/vision/tasks/detector.cjs +1 -1
  314. package/dist/vision/tasks/detector.cjs.map +1 -1
  315. package/dist/vision/tasks/detector.js +54 -29
  316. package/dist/vision/tasks/detector.js.map +1 -1
  317. package/dist/vision/tasks/segmenter.cjs +1 -1
  318. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  319. package/dist/vision/tasks/segmenter.js +53 -28
  320. package/dist/vision/tasks/segmenter.js.map +1 -1
  321. package/dist/vision/types.cjs.map +1 -1
  322. package/dist/vision/types.js.map +1 -1
  323. package/dist/vision.cjs +1 -1
  324. package/dist/vision.d.ts +1517 -956
  325. package/dist/vision.js +25 -22
  326. package/dist/vite/tempest-icons.cjs.map +1 -1
  327. package/dist/vite/tempest-icons.js.map +1 -1
  328. package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
  329. package/dist/vite/tempest-pwa-icons.js.map +1 -1
  330. package/dist/ws/create-web-socket.cjs.map +1 -1
  331. package/dist/ws/create-web-socket.js.map +1 -1
  332. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.cjs","names":[],"sources":["../../../src/vision/preprocess/pipeline.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Fused letterbox → CHW float32 pipeline with reusable buffers.\n *\n * The composable primitives in {@link ./image.js} each allocate and each walk\n * their input end to end, which is the right shape for a library but the wrong\n * shape for a video loop. Chaining them costs eleven full-buffer passes and six\n * large allocations per frame:\n *\n * `getImageData` → RGBA→RGB → RGB→RGBA → `putImageData` → `drawImage` →\n * `getImageData` → RGBA→RGB → fill → row copies → `toFloat32` → `toCHW`.\n *\n * This module collapses the second half of that into two: one `drawImage` that\n * resizes *and* positions the content inside the padded target in a single\n * accelerated operation, and one loop that reads the resulting RGBA and writes\n * planar float32 directly. The intermediate `RGBImage` at target size, the fill\n * loop, the row copies and the two 4.9 MB `Float32Array` allocations all go\n * away.\n *\n * The primitives stay exactly as they are — they are public API and they are\n * what makes a custom pipeline writable. This is the fast path the built-in\n * tasks take.\n */\n\nimport {\n createCanvas,\n get2DContext,\n rgbToImageData,\n type Canvas2D,\n type Context2D,\n} from \"../core/canvas\";\nimport type { RGBImage } from \"../types\";\n\nconst INV_255 = 1 / 255;\n\n/** Geometry of a letterbox, plus the planar tensor data it produced. */\nexport interface FusedLetterboxResult {\n /** CHW float32 in `[0, 1]`, length `3 * targetHeight * targetWidth`. */\n readonly data: Float32Array;\n /** Factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels. */\n readonly padLeft: number;\n /** Vertical padding in pixels. */\n readonly padTop: number;\n /**\n * Whether {@link data} is the pipeline's reusable buffer.\n *\n * `true` means the next {@link LetterboxPipeline.run} overwrites it, so a\n * caller keeping the values past its own inference has to copy them.\n */\n readonly reused: boolean;\n}\n\n/**\n * Reusable letterbox → tensor pipeline for one target resolution.\n *\n * Holds a target canvas and an output buffer across calls, so a steady stream\n * of frames at the same size allocates nothing. Create one per task, not per\n * frame.\n */\nexport class LetterboxPipeline {\n private readonly _targetWidth: number;\n private readonly _targetHeight: number;\n private readonly _fill: readonly [number, number, number];\n private readonly _target: Canvas2D;\n private readonly _targetContext: Context2D;\n private readonly _buffer: Float32Array;\n private _source: Canvas2D | null = null;\n private _sourceContext: Context2D | null = null;\n private _bufferInUse = false;\n\n /**\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param fill RGB padding colour; defaults to YOLO grey.\n */\n constructor(\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n ) {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid letterbox target ${targetWidth}x${targetHeight}.`);\n }\n this._targetWidth = targetWidth;\n this._targetHeight = targetHeight;\n this._fill = fill;\n this._target = createCanvas(targetWidth, targetHeight);\n this._targetContext = get2DContext(this._target, { willReadFrequently: true });\n this._targetContext.imageSmoothingEnabled = true;\n this._targetContext.imageSmoothingQuality = \"high\";\n this._buffer = new Float32Array(3 * targetHeight * targetWidth);\n }\n\n /** The `[width, height]` this pipeline letterboxes into. */\n get targetSize(): readonly [number, number] {\n return [this._targetWidth, this._targetHeight];\n }\n\n /**\n * Letterbox an image and write it as planar float32.\n *\n * The returned buffer is reused between calls unless a previous result is\n * still checked out — {@link release} marks it free again. A second `run`\n * before the first is released allocates a fresh buffer rather than\n * corrupting it, so concurrent `predict()` calls on one task stay correct at\n * the cost of the allocation they were trying to avoid.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n */\n run(image: RGBImage): FusedLetterboxResult {\n const targetWidth = this._targetWidth;\n const targetHeight = this._targetHeight;\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const scaledWidth = Math.round(image.width * scale);\n const scaledHeight = Math.round(image.height * scale);\n const padLeft = Math.floor((targetWidth - scaledWidth) / 2);\n const padTop = Math.floor((targetHeight - scaledHeight) / 2);\n\n const source = this._ensureSource(image.width, image.height);\n source.putImageData(rgbToImageData(image), 0, 0);\n\n const context = this._targetContext;\n if (\n padLeft > 0 ||\n padTop > 0 ||\n scaledWidth !== targetWidth ||\n scaledHeight !== targetHeight\n ) {\n context.fillStyle = `rgb(${this._fill[0]},${this._fill[1]},${this._fill[2]})`;\n context.fillRect(0, 0, targetWidth, targetHeight);\n }\n context.drawImage(\n this._source as CanvasImageSource,\n 0,\n 0,\n image.width,\n image.height,\n padLeft,\n padTop,\n scaledWidth,\n scaledHeight,\n );\n\n const rgba = context.getImageData(0, 0, targetWidth, targetHeight).data;\n const reused = !this._bufferInUse;\n const data = reused ? this._buffer : new Float32Array(3 * targetHeight * targetWidth);\n this._bufferInUse = true;\n\n const plane = targetWidth * targetHeight;\n for (let pixel = 0, offset = 0; pixel < plane; pixel++, offset += 4) {\n data[pixel] = (rgba[offset] as number) * INV_255;\n data[plane + pixel] = (rgba[offset + 1] as number) * INV_255;\n data[2 * plane + pixel] = (rgba[offset + 2] as number) * INV_255;\n }\n\n return { data, scale, padLeft, padTop, reused };\n }\n\n /**\n * Mark the reusable buffer free again.\n *\n * Call it once the tensor built from a {@link run} result has been handed to\n * ONNX Runtime and the run has resolved — after that the values are inside\n * the WASM heap and the buffer can be overwritten.\n */\n release(): void {\n this._bufferInUse = false;\n }\n\n /**\n * Grow the scratch source canvas to fit an image, reusing it when possible.\n *\n * A canvas is only reallocated when a frame arrives at a different size than\n * the last one, which for a camera or video source is never after the first.\n *\n * @param width Source width in pixels.\n * @param height Source height in pixels.\n */\n private _ensureSource(width: number, height: number): Context2D {\n if (\n this._source === null ||\n this._source.width !== width ||\n this._source.height !== height\n ) {\n this._source = createCanvas(width, height);\n this._sourceContext = get2DContext(this._source);\n }\n return this._sourceContext as Context2D;\n }\n}\n\n/**\n * Build a zero-filled CHW tensor payload for a warm-up run.\n *\n * @param width Model input width in pixels.\n * @param height Model input height in pixels.\n */\nexport function zeroTensorData(width: number, height: number): Float32Array {\n return new Float32Array(3 * height * width);\n}\n\n/**\n * Letterbox an image into planar float32 without keeping any state.\n *\n * The allocation-free path is {@link LetterboxPipeline}; this is the one-shot\n * form, for a caller who wants the fused behaviour without owning a pipeline.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param fill RGB padding colour; defaults to YOLO grey.\n */\nexport function letterboxToTensorData(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): FusedLetterboxResult {\n return new LetterboxPipeline(targetWidth, targetHeight, fill).run(image);\n}\n"],"mappings":"sCAiCA,IAAM,EAAU,EAAI,IA4BP,EAAb,KAA+B,CAC3B,aACA,cACA,MACA,QACA,eACA,QACA,QAAmC,KACnC,eAA2C,KAC3C,aAAuB,GAOvB,YACI,EACA,EACA,EAA0C,CAAC,IAAK,IAAK,GAAG,EAC1D,CACE,GAAI,GAAe,GAAK,GAAgB,EACpC,MAAU,MAAM,4BAA4B,EAAY,GAAG,EAAa,EAAE,EAE9E,KAAK,aAAe,EACpB,KAAK,cAAgB,EACrB,KAAK,MAAQ,EACb,KAAK,QAAU,EAAA,aAAa,EAAa,CAAY,EACrD,KAAK,eAAiB,EAAA,aAAa,KAAK,QAAS,CAAE,mBAAoB,EAAK,CAAC,EAC7E,KAAK,eAAe,sBAAwB,GAC5C,KAAK,eAAe,sBAAwB,OAC5C,KAAK,QAAU,IAAI,aAAa,EAAI,EAAe,CAAW,CAClE,CAGA,IAAI,YAAwC,CACxC,MAAO,CAAC,KAAK,aAAc,KAAK,aAAa,CACjD,CAaA,IAAI,EAAuC,CACvC,IAAM,EAAc,KAAK,aACnB,EAAe,KAAK,cACpB,EAAQ,KAAK,IAAI,EAAc,EAAM,MAAO,EAAe,EAAM,MAAM,EACvE,EAAc,KAAK,MAAM,EAAM,MAAQ,CAAK,EAC5C,EAAe,KAAK,MAAM,EAAM,OAAS,CAAK,EAC9C,EAAU,KAAK,OAAO,EAAc,GAAe,CAAC,EACpD,EAAS,KAAK,OAAO,EAAe,GAAgB,CAAC,EAG3D,KADoB,cAAc,EAAM,MAAO,EAAM,MACrD,CAAA,CAAO,aAAa,EAAA,eAAe,CAAK,EAAG,EAAG,CAAC,EAE/C,IAAM,EAAU,KAAK,gBAEjB,EAAU,GACV,EAAS,GACT,IAAgB,GAChB,IAAiB,KAEjB,EAAQ,UAAY,OAAO,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,GAAG,GAC3E,EAAQ,SAAS,EAAG,EAAG,EAAa,CAAY,GAEpD,EAAQ,UACJ,KAAK,QACL,EACA,EACA,EAAM,MACN,EAAM,OACN,EACA,EACA,EACA,CACJ,EAEA,IAAM,EAAO,EAAQ,aAAa,EAAG,EAAG,EAAa,CAAY,CAAC,CAAC,KAC7D,EAAS,CAAC,KAAK,aACf,EAAO,EAAS,KAAK,QAAU,IAAI,aAAa,EAAI,EAAe,CAAW,EACpF,KAAK,aAAe,GAEpB,IAAM,EAAQ,EAAc,EAC5B,IAAK,IAAI,EAAQ,EAAG,EAAS,EAAG,EAAQ,EAAO,IAAS,GAAU,EAC9D,EAAK,GAAU,EAAK,GAAqB,EACzC,EAAK,EAAQ,GAAU,EAAK,EAAS,GAAgB,EACrD,EAAK,EAAI,EAAQ,GAAU,EAAK,EAAS,GAAgB,EAG7D,MAAO,CAAE,OAAM,QAAO,UAAS,SAAQ,QAAO,CAClD,CASA,SAAgB,CACZ,KAAK,aAAe,EACxB,CAWA,cAAsB,EAAe,EAA2B,CAS5D,OAPI,KAAK,UAAY,MACjB,KAAK,QAAQ,QAAU,GACvB,KAAK,QAAQ,SAAW,KAExB,KAAK,QAAU,EAAA,aAAa,EAAO,CAAM,EACzC,KAAK,eAAiB,EAAA,aAAa,KAAK,OAAO,GAE5C,KAAK,cAChB,CACJ,EAQA,SAAgB,EAAe,EAAe,EAA8B,CACxE,OAAO,IAAI,aAAa,EAAI,EAAS,CAAK,CAC9C,CAaA,SAAgB,EACZ,EACA,EACA,EACA,EAA0C,CAAC,IAAK,IAAK,GAAG,EACpC,CACpB,OAAO,IAAI,EAAkB,EAAa,EAAc,CAAI,CAAC,CAAC,IAAI,CAAK,CAC3E"}
@@ -0,0 +1,61 @@
1
+ import { createCanvas as e, get2DContext as t, rgbToImageData as n } from "../core/canvas.js";
2
+ //#region src/vision/preprocess/pipeline.ts
3
+ var r = 1 / 255, i = class {
4
+ _targetWidth;
5
+ _targetHeight;
6
+ _fill;
7
+ _target;
8
+ _targetContext;
9
+ _buffer;
10
+ _source = null;
11
+ _sourceContext = null;
12
+ _bufferInUse = !1;
13
+ constructor(n, r, i = [
14
+ 114,
15
+ 114,
16
+ 114
17
+ ]) {
18
+ if (n <= 0 || r <= 0) throw Error(`Invalid letterbox target ${n}x${r}.`);
19
+ this._targetWidth = n, this._targetHeight = r, this._fill = i, this._target = e(n, r), this._targetContext = t(this._target, { willReadFrequently: !0 }), this._targetContext.imageSmoothingEnabled = !0, this._targetContext.imageSmoothingQuality = "high", this._buffer = new Float32Array(3 * r * n);
20
+ }
21
+ get targetSize() {
22
+ return [this._targetWidth, this._targetHeight];
23
+ }
24
+ run(e) {
25
+ let t = this._targetWidth, i = this._targetHeight, a = Math.min(t / e.width, i / e.height), o = Math.round(e.width * a), s = Math.round(e.height * a), c = Math.floor((t - o) / 2), l = Math.floor((i - s) / 2);
26
+ this._ensureSource(e.width, e.height).putImageData(n(e), 0, 0);
27
+ let u = this._targetContext;
28
+ (c > 0 || l > 0 || o !== t || s !== i) && (u.fillStyle = `rgb(${this._fill[0]},${this._fill[1]},${this._fill[2]})`, u.fillRect(0, 0, t, i)), u.drawImage(this._source, 0, 0, e.width, e.height, c, l, o, s);
29
+ let d = u.getImageData(0, 0, t, i).data, f = !this._bufferInUse, p = f ? this._buffer : new Float32Array(3 * i * t);
30
+ this._bufferInUse = !0;
31
+ let m = t * i;
32
+ for (let e = 0, t = 0; e < m; e++, t += 4) p[e] = d[t] * r, p[m + e] = d[t + 1] * r, p[2 * m + e] = d[t + 2] * r;
33
+ return {
34
+ data: p,
35
+ scale: a,
36
+ padLeft: c,
37
+ padTop: l,
38
+ reused: f
39
+ };
40
+ }
41
+ release() {
42
+ this._bufferInUse = !1;
43
+ }
44
+ _ensureSource(n, r) {
45
+ return (this._source === null || this._source.width !== n || this._source.height !== r) && (this._source = e(n, r), this._sourceContext = t(this._source)), this._sourceContext;
46
+ }
47
+ };
48
+ function a(e, t) {
49
+ return new Float32Array(3 * t * e);
50
+ }
51
+ function o(e, t, n, r = [
52
+ 114,
53
+ 114,
54
+ 114
55
+ ]) {
56
+ return new i(t, n, r).run(e);
57
+ }
58
+ //#endregion
59
+ export { i as LetterboxPipeline, o as letterboxToTensorData, a as zeroTensorData };
60
+
61
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","names":[],"sources":["../../../src/vision/preprocess/pipeline.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Fused letterbox → CHW float32 pipeline with reusable buffers.\n *\n * The composable primitives in {@link ./image.js} each allocate and each walk\n * their input end to end, which is the right shape for a library but the wrong\n * shape for a video loop. Chaining them costs eleven full-buffer passes and six\n * large allocations per frame:\n *\n * `getImageData` → RGBA→RGB → RGB→RGBA → `putImageData` → `drawImage` →\n * `getImageData` → RGBA→RGB → fill → row copies → `toFloat32` → `toCHW`.\n *\n * This module collapses the second half of that into two: one `drawImage` that\n * resizes *and* positions the content inside the padded target in a single\n * accelerated operation, and one loop that reads the resulting RGBA and writes\n * planar float32 directly. The intermediate `RGBImage` at target size, the fill\n * loop, the row copies and the two 4.9 MB `Float32Array` allocations all go\n * away.\n *\n * The primitives stay exactly as they are — they are public API and they are\n * what makes a custom pipeline writable. This is the fast path the built-in\n * tasks take.\n */\n\nimport {\n createCanvas,\n get2DContext,\n rgbToImageData,\n type Canvas2D,\n type Context2D,\n} from \"../core/canvas\";\nimport type { RGBImage } from \"../types\";\n\nconst INV_255 = 1 / 255;\n\n/** Geometry of a letterbox, plus the planar tensor data it produced. */\nexport interface FusedLetterboxResult {\n /** CHW float32 in `[0, 1]`, length `3 * targetHeight * targetWidth`. */\n readonly data: Float32Array;\n /** Factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels. */\n readonly padLeft: number;\n /** Vertical padding in pixels. */\n readonly padTop: number;\n /**\n * Whether {@link data} is the pipeline's reusable buffer.\n *\n * `true` means the next {@link LetterboxPipeline.run} overwrites it, so a\n * caller keeping the values past its own inference has to copy them.\n */\n readonly reused: boolean;\n}\n\n/**\n * Reusable letterbox → tensor pipeline for one target resolution.\n *\n * Holds a target canvas and an output buffer across calls, so a steady stream\n * of frames at the same size allocates nothing. Create one per task, not per\n * frame.\n */\nexport class LetterboxPipeline {\n private readonly _targetWidth: number;\n private readonly _targetHeight: number;\n private readonly _fill: readonly [number, number, number];\n private readonly _target: Canvas2D;\n private readonly _targetContext: Context2D;\n private readonly _buffer: Float32Array;\n private _source: Canvas2D | null = null;\n private _sourceContext: Context2D | null = null;\n private _bufferInUse = false;\n\n /**\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param fill RGB padding colour; defaults to YOLO grey.\n */\n constructor(\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n ) {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid letterbox target ${targetWidth}x${targetHeight}.`);\n }\n this._targetWidth = targetWidth;\n this._targetHeight = targetHeight;\n this._fill = fill;\n this._target = createCanvas(targetWidth, targetHeight);\n this._targetContext = get2DContext(this._target, { willReadFrequently: true });\n this._targetContext.imageSmoothingEnabled = true;\n this._targetContext.imageSmoothingQuality = \"high\";\n this._buffer = new Float32Array(3 * targetHeight * targetWidth);\n }\n\n /** The `[width, height]` this pipeline letterboxes into. */\n get targetSize(): readonly [number, number] {\n return [this._targetWidth, this._targetHeight];\n }\n\n /**\n * Letterbox an image and write it as planar float32.\n *\n * The returned buffer is reused between calls unless a previous result is\n * still checked out — {@link release} marks it free again. A second `run`\n * before the first is released allocates a fresh buffer rather than\n * corrupting it, so concurrent `predict()` calls on one task stay correct at\n * the cost of the allocation they were trying to avoid.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n */\n run(image: RGBImage): FusedLetterboxResult {\n const targetWidth = this._targetWidth;\n const targetHeight = this._targetHeight;\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const scaledWidth = Math.round(image.width * scale);\n const scaledHeight = Math.round(image.height * scale);\n const padLeft = Math.floor((targetWidth - scaledWidth) / 2);\n const padTop = Math.floor((targetHeight - scaledHeight) / 2);\n\n const source = this._ensureSource(image.width, image.height);\n source.putImageData(rgbToImageData(image), 0, 0);\n\n const context = this._targetContext;\n if (\n padLeft > 0 ||\n padTop > 0 ||\n scaledWidth !== targetWidth ||\n scaledHeight !== targetHeight\n ) {\n context.fillStyle = `rgb(${this._fill[0]},${this._fill[1]},${this._fill[2]})`;\n context.fillRect(0, 0, targetWidth, targetHeight);\n }\n context.drawImage(\n this._source as CanvasImageSource,\n 0,\n 0,\n image.width,\n image.height,\n padLeft,\n padTop,\n scaledWidth,\n scaledHeight,\n );\n\n const rgba = context.getImageData(0, 0, targetWidth, targetHeight).data;\n const reused = !this._bufferInUse;\n const data = reused ? this._buffer : new Float32Array(3 * targetHeight * targetWidth);\n this._bufferInUse = true;\n\n const plane = targetWidth * targetHeight;\n for (let pixel = 0, offset = 0; pixel < plane; pixel++, offset += 4) {\n data[pixel] = (rgba[offset] as number) * INV_255;\n data[plane + pixel] = (rgba[offset + 1] as number) * INV_255;\n data[2 * plane + pixel] = (rgba[offset + 2] as number) * INV_255;\n }\n\n return { data, scale, padLeft, padTop, reused };\n }\n\n /**\n * Mark the reusable buffer free again.\n *\n * Call it once the tensor built from a {@link run} result has been handed to\n * ONNX Runtime and the run has resolved — after that the values are inside\n * the WASM heap and the buffer can be overwritten.\n */\n release(): void {\n this._bufferInUse = false;\n }\n\n /**\n * Grow the scratch source canvas to fit an image, reusing it when possible.\n *\n * A canvas is only reallocated when a frame arrives at a different size than\n * the last one, which for a camera or video source is never after the first.\n *\n * @param width Source width in pixels.\n * @param height Source height in pixels.\n */\n private _ensureSource(width: number, height: number): Context2D {\n if (\n this._source === null ||\n this._source.width !== width ||\n this._source.height !== height\n ) {\n this._source = createCanvas(width, height);\n this._sourceContext = get2DContext(this._source);\n }\n return this._sourceContext as Context2D;\n }\n}\n\n/**\n * Build a zero-filled CHW tensor payload for a warm-up run.\n *\n * @param width Model input width in pixels.\n * @param height Model input height in pixels.\n */\nexport function zeroTensorData(width: number, height: number): Float32Array {\n return new Float32Array(3 * height * width);\n}\n\n/**\n * Letterbox an image into planar float32 without keeping any state.\n *\n * The allocation-free path is {@link LetterboxPipeline}; this is the one-shot\n * form, for a caller who wants the fused behaviour without owning a pipeline.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param fill RGB padding colour; defaults to YOLO grey.\n */\nexport function letterboxToTensorData(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): FusedLetterboxResult {\n return new LetterboxPipeline(targetWidth, targetHeight, fill).run(image);\n}\n"],"mappings":";;AAiCA,IAAM,IAAU,IAAI,KA4BP,IAAb,MAA+B;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA,UAAmC;CACnC,iBAA2C;CAC3C,eAAuB;CAOvB,YACI,GACA,GACA,IAA0C;EAAC;EAAK;EAAK;CAAG,GAC1D;EACE,IAAI,KAAe,KAAK,KAAgB,GACpC,MAAU,MAAM,4BAA4B,EAAY,GAAG,EAAa,EAAE;EAS9E,AAPA,KAAK,eAAe,GACpB,KAAK,gBAAgB,GACrB,KAAK,QAAQ,GACb,KAAK,UAAU,EAAa,GAAa,CAAY,GACrD,KAAK,iBAAiB,EAAa,KAAK,SAAS,EAAE,oBAAoB,GAAK,CAAC,GAC7E,KAAK,eAAe,wBAAwB,IAC5C,KAAK,eAAe,wBAAwB,QAC5C,KAAK,UAAU,IAAI,aAAa,IAAI,IAAe,CAAW;CAClE;CAGA,IAAI,aAAwC;EACxC,OAAO,CAAC,KAAK,cAAc,KAAK,aAAa;CACjD;CAaA,IAAI,GAAuC;EACvC,IAAM,IAAc,KAAK,cACnB,IAAe,KAAK,eACpB,IAAQ,KAAK,IAAI,IAAc,EAAM,OAAO,IAAe,EAAM,MAAM,GACvE,IAAc,KAAK,MAAM,EAAM,QAAQ,CAAK,GAC5C,IAAe,KAAK,MAAM,EAAM,SAAS,CAAK,GAC9C,IAAU,KAAK,OAAO,IAAc,KAAe,CAAC,GACpD,IAAS,KAAK,OAAO,IAAe,KAAgB,CAAC;EAG3D,KADoB,cAAc,EAAM,OAAO,EAAM,MACrD,CAAA,CAAO,aAAa,EAAe,CAAK,GAAG,GAAG,CAAC;EAE/C,IAAM,IAAU,KAAK;EAUrB,CARI,IAAU,KACV,IAAS,KACT,MAAgB,KAChB,MAAiB,OAEjB,EAAQ,YAAY,OAAO,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,GAAG,IAC3E,EAAQ,SAAS,GAAG,GAAG,GAAa,CAAY,IAEpD,EAAQ,UACJ,KAAK,SACL,GACA,GACA,EAAM,OACN,EAAM,QACN,GACA,GACA,GACA,CACJ;EAEA,IAAM,IAAO,EAAQ,aAAa,GAAG,GAAG,GAAa,CAAY,CAAC,CAAC,MAC7D,IAAS,CAAC,KAAK,cACf,IAAO,IAAS,KAAK,UAAU,IAAI,aAAa,IAAI,IAAe,CAAW;EACpF,KAAK,eAAe;EAEpB,IAAM,IAAQ,IAAc;EAC5B,KAAK,IAAI,IAAQ,GAAG,IAAS,GAAG,IAAQ,GAAO,KAAS,KAAU,GAG9D,AAFA,EAAK,KAAU,EAAK,KAAqB,GACzC,EAAK,IAAQ,KAAU,EAAK,IAAS,KAAgB,GACrD,EAAK,IAAI,IAAQ,KAAU,EAAK,IAAS,KAAgB;EAG7D,OAAO;GAAE;GAAM;GAAO;GAAS;GAAQ;EAAO;CAClD;CASA,UAAgB;EACZ,KAAK,eAAe;CACxB;CAWA,cAAsB,GAAe,GAA2B;EAS5D,QAPI,KAAK,YAAY,QACjB,KAAK,QAAQ,UAAU,KACvB,KAAK,QAAQ,WAAW,OAExB,KAAK,UAAU,EAAa,GAAO,CAAM,GACzC,KAAK,iBAAiB,EAAa,KAAK,OAAO,IAE5C,KAAK;CAChB;AACJ;AAQA,SAAgB,EAAe,GAAe,GAA8B;CACxE,OAAO,IAAI,aAAa,IAAI,IAAS,CAAK;AAC9C;AAaA,SAAgB,EACZ,GACA,GACA,GACA,IAA0C;CAAC;CAAK;CAAK;AAAG,GACpC;CACpB,OAAO,IAAI,EAAkB,GAAa,GAAc,CAAI,CAAC,CAAC,IAAI,CAAK;AAC3E"}
@@ -1,2 +1,2 @@
1
- var e={load:0,preprocess:0,inference:0,postprocess:0},t=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},n=class{data;constructor(e){this.data=e}get length(){return this.data.length}get shape(){return[this.length]}get top1(){if(this.data.length===0)return 0;let e=0,t=this.data[0];for(let n=1;n<this.data.length;n++){let r=this.data[n];r>t&&(e=n,t=r)}return e}get top1conf(){return this.data.length===0?0:this.data[this.top1]}get top5(){return this._topK(5).indices}get top5conf(){return this._topK(5).values}_topK(e){let t=Math.min(e,this.data.length),n=[];for(let e=0;e<this.data.length;e++)n.push(e);n.sort((e,t)=>this.data[t]-this.data[e]);let r=new Int32Array(t),i=new Float32Array(t);for(let e=0;e<t;e++)r[e]=n[e],i[e]=this.data[n[e]];return{indices:r,values:i}}},r=class{data;xyxy;origShape;constructor(e,t,n){this.data=e,this.xyxy=t,this.origShape=n}get length(){return this.data.length}get shape(){return[this.length]}[Symbol.iterator](){return this.data[Symbol.iterator]()}},i=class{boxes;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.boxes=t,this.detections=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},a=class{probs;result;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.probs=t,this.result=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get cls(){return this.probs.top1}get conf(){return this.probs.top1conf}get name(){return this.names[this.cls]??`class_${this.cls}`}get probabilities(){return this.result.probabilities}},o=class{boxes;masks;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o,s=null,c=e){this.boxes=t,this.masks=n,this.detections=r,this.names=i,this.origImg=a,this.origShape=o,this.path=s,this.speed=c}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}};exports.Boxes=t,exports.ClassificationResults=a,exports.DetectionResults=i,exports.Masks=r,exports.Probs=n,exports.SegmentationResults=o;
1
+ var e={load:0,preprocess:0,inference:0,postprocess:0},t=class{xyxy;cls;conf;origShape;constructor(e,t,n,r){this.xyxy=e,this.cls=t,this.conf=n,this.origShape=r}get length(){return this.cls.length}get shape(){return[this.length,4]}get xywh(){let e=new Float32Array(this.xyxy.length);for(let t=0;t<this.length;t++){let n=this.xyxy[t*4],r=this.xyxy[t*4+1],i=this.xyxy[t*4+2],a=this.xyxy[t*4+3];e[t*4]=(n+i)/2,e[t*4+1]=(r+a)/2,e[t*4+2]=i-n,e[t*4+3]=a-r}return e}get xyxyn(){let[e,t]=this.origShape,n=new Float32Array(this.xyxy.length);if(this.length===0||t<=0||e<=0)return n;for(let r=0;r<this.length;r++)n[r*4]=this.xyxy[r*4]/t,n[r*4+1]=this.xyxy[r*4+1]/e,n[r*4+2]=this.xyxy[r*4+2]/t,n[r*4+3]=this.xyxy[r*4+3]/e;return n}get xywhn(){let e=this.xywh,[t,n]=this.origShape;if(this.length===0||n<=0||t<=0)return e;for(let r=0;r<this.length;r++)e[r*4]=e[r*4]/n,e[r*4+1]=e[r*4+1]/t,e[r*4+2]=e[r*4+2]/n,e[r*4+3]=e[r*4+3]/t;return e}get data(){let e=new Float32Array(this.length*6);for(let t=0;t<this.length;t++)e[t*6]=this.xyxy[t*4],e[t*6+1]=this.xyxy[t*4+1],e[t*6+2]=this.xyxy[t*4+2],e[t*6+3]=this.xyxy[t*4+3],e[t*6+4]=this.conf[t],e[t*6+5]=this.cls[t];return e}},n=class{data;constructor(e){this.data=e}get length(){return this.data.length}get shape(){return[this.length]}get top1(){if(this.data.length===0)return 0;let e=0,t=this.data[0];for(let n=1;n<this.data.length;n++){let r=this.data[n];r>t&&(e=n,t=r)}return e}get top1conf(){return this.data.length===0?0:this.data[this.top1]}get top5(){return this._topK(5).indices}get top5conf(){return this._topK(5).values}_topK(e){let t=Math.min(e,this.data.length),n=[];for(let e=0;e<this.data.length;e++)n.push(e);n.sort((e,t)=>this.data[t]-this.data[e]);let r=new Int32Array(t),i=new Float32Array(t);for(let e=0;e<t;e++)r[e]=n[e],i[e]=this.data[n[e]];return{indices:r,values:i}}},r=class{data;xyxy;origShape;constructor(e,t,n){this.data=e,this.xyxy=t,this.origShape=n}get length(){return this.data.length}get shape(){return[this.length]}[Symbol.iterator](){return this.data[Symbol.iterator]()}},i=class{boxes;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.boxes=t,this.detections=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},a=class{boxes;detections;names;classifierNames;origImg;origShape;path;speed;constructor(t,n,r,i,a,o,s=null,c=e){this.boxes=t,this.detections=n,this.names=r,this.classifierNames=i,this.origImg=a,this.origShape=o,this.path=s,this.speed=c}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}},o=class{probs;result;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o=null,s=e){this.probs=t,this.result=n,this.names=r,this.origImg=i,this.origShape=a,this.path=o,this.speed=s}get cls(){return this.probs.top1}get conf(){return this.probs.top1conf}get name(){return this.names[this.cls]??`class_${this.cls}`}get probabilities(){return this.result.probabilities}},s=class{boxes;masks;detections;names;origImg;origShape;path;speed;constructor(t,n,r,i,a,o,s=null,c=e){this.boxes=t,this.masks=n,this.detections=r,this.names=i,this.origImg=a,this.origShape=o,this.path=s,this.speed=c}get length(){return this.detections.length}get(e){return this.detections[e]}[Symbol.iterator](){return this.detections[Symbol.iterator]()}};exports.Boxes=t,exports.ClassificationResults=o,exports.DetectClassifyResults=a,exports.DetectionResults=i,exports.Masks=r,exports.Probs=n,exports.SegmentationResults=s;
2
2
  //# sourceMappingURL=results.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"results.cjs","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"results.cjs","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image envelope for a fused detect→classify pipeline.\n *\n * Structurally a {@link DetectionResults} with a second class map: every\n * detection it yields carries a populated `classification`, and the two stages\n * have their own, unrelated label spaces — a detector that finds `sheep`\n * feeding a classifier that answers `famacha_3` shares no class ids with it.\n * Merging them into one `names` record would make `cls` and\n * `classification.cls` look comparable when they are not.\n *\n * ```typescript\n * const result = (await pipeline.predict(\"flock.jpg\"))[0];\n * for (const detection of result) {\n * console.log(detection.name, detection.conf, detection.classification?.name);\n * }\n * ```\n */\nexport class DetectClassifyResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly classifierNames: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
@@ -120,6 +120,27 @@ var e = {
120
120
  return this.detections[Symbol.iterator]();
121
121
  }
122
122
  }, a = class {
123
+ boxes;
124
+ detections;
125
+ names;
126
+ classifierNames;
127
+ origImg;
128
+ origShape;
129
+ path;
130
+ speed;
131
+ constructor(t, n, r, i, a, o, s = null, c = e) {
132
+ this.boxes = t, this.detections = n, this.names = r, this.classifierNames = i, this.origImg = a, this.origShape = o, this.path = s, this.speed = c;
133
+ }
134
+ get length() {
135
+ return this.detections.length;
136
+ }
137
+ get(e) {
138
+ return this.detections[e];
139
+ }
140
+ [Symbol.iterator]() {
141
+ return this.detections[Symbol.iterator]();
142
+ }
143
+ }, o = class {
123
144
  probs;
124
145
  result;
125
146
  names;
@@ -142,7 +163,7 @@ var e = {
142
163
  get probabilities() {
143
164
  return this.result.probabilities;
144
165
  }
145
- }, o = class {
166
+ }, s = class {
146
167
  boxes;
147
168
  masks;
148
169
  detections;
@@ -165,6 +186,6 @@ var e = {
165
186
  }
166
187
  };
167
188
  //#endregion
168
- export { t as Boxes, a as ClassificationResults, i as DetectionResults, r as Masks, n as Probs, o as SegmentationResults };
189
+ export { t as Boxes, o as ClassificationResults, a as DetectClassifyResults, i as DetectionResults, r as Masks, n as Probs, s as SegmentationResults };
169
190
 
170
191
  //# sourceMappingURL=results.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"results.js","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"results.js","names":[],"sources":["../../src/vision/results.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Per-image result envelopes — Ultralytics-style `Results` for the SDK.\n *\n * Each `predict()` call returns a 1-element array of these envelopes,\n * mirroring `YOLO(\"img.jpg\")`. Each envelope holds:\n *\n * - A bulk-array view of the predictions (`Boxes`, `Probs`, `Masks`) with\n * the exact attribute names Ultralytics uses (`xyxy`, `xywh`, `xyxyn`,\n * `xywhn`, `cls`, `conf`, `data`, `top1`, `top5`).\n * - Per-instance dataclasses (`DetectionResult`, `SegmentationResult`,\n * `ClassProbability`) for callers who prefer the OO interface.\n * - `names`: `Record<number, string>` matching Ultralytics' `model.names`.\n * - `origImg` / `origShape` / `path`: provenance for the original input.\n * - `speed`: per-stage timings of the `predict()` call that produced it.\n */\n\nimport { type Speed } from \"./core/timing\";\nimport {\n type ClassificationResult,\n type DetectionResult,\n type RGBImage,\n type SegmentationResult,\n} from \"./types\";\n\n/**\n * Zero timings for an envelope built outside a `predict()` call.\n *\n * Hand-constructed envelopes (tests, adapters) have nothing to measure, and\n * zeros keep `speed.inference` a plain `number` at every call site instead of\n * forcing an optional check that only ever fires for synthetic data.\n */\nconst NO_SPEED: Speed = { load: 0, preprocess: 0, inference: 0, postprocess: 0 };\n\n/**\n * Bulk numpy-style view of detected boxes for a single image.\n *\n * Mirrors Ultralytics' `Boxes` interface. Coordinates in {@link xyxy} and\n * {@link xywh} are absolute pixels in the original image; the `*n` variants\n * are normalized to `[0, 1]` using `origShape`.\n */\nexport class Boxes {\n /**\n * @param xyxy Flat array of length `4 * N` in `[x1, y1, x2, y2, ...]` order.\n * @param cls One class index per box, length `N`.\n * @param conf One confidence per box, length `N`.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly xyxy: Float32Array,\n public readonly cls: Int32Array,\n public readonly conf: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of detected boxes. */\n get length(): number {\n return this.cls.length;\n }\n\n /** `[N, 4]` shape of the `xyxy` view. */\n get shape(): readonly [number, number] {\n return [this.length, 4];\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` flat array in absolute pixels. */\n get xywh(): Float32Array {\n const out = new Float32Array(this.xyxy.length);\n for (let i = 0; i < this.length; i++) {\n const x1 = this.xyxy[i * 4] as number;\n const y1 = this.xyxy[i * 4 + 1] as number;\n const x2 = this.xyxy[i * 4 + 2] as number;\n const y2 = this.xyxy[i * 4 + 3] as number;\n out[i * 4] = (x1 + x2) / 2;\n out[i * 4 + 1] = (y1 + y2) / 2;\n out[i * 4 + 2] = x2 - x1;\n out[i * 4 + 3] = y2 - y1;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[x1, y1, x2, y2]` normalized to `[0, 1]`. */\n get xyxyn(): Float32Array {\n const [h, w] = this.origShape;\n const out = new Float32Array(this.xyxy.length);\n if (this.length === 0 || w <= 0 || h <= 0) return out;\n for (let i = 0; i < this.length; i++) {\n out[i * 4] = (this.xyxy[i * 4] as number) / w;\n out[i * 4 + 1] = (this.xyxy[i * 4 + 1] as number) / h;\n out[i * 4 + 2] = (this.xyxy[i * 4 + 2] as number) / w;\n out[i * 4 + 3] = (this.xyxy[i * 4 + 3] as number) / h;\n }\n return out;\n }\n\n /** Boxes as `[N, 4]` `[cx, cy, w, h]` normalized to `[0, 1]`. */\n get xywhn(): Float32Array {\n const xywh = this.xywh;\n const [h, w] = this.origShape;\n if (this.length === 0 || w <= 0 || h <= 0) return xywh;\n for (let i = 0; i < this.length; i++) {\n xywh[i * 4] = (xywh[i * 4] as number) / w;\n xywh[i * 4 + 1] = (xywh[i * 4 + 1] as number) / h;\n xywh[i * 4 + 2] = (xywh[i * 4 + 2] as number) / w;\n xywh[i * 4 + 3] = (xywh[i * 4 + 3] as number) / h;\n }\n return xywh;\n }\n\n /**\n * Concatenated `[N, 6]` array of `[x1, y1, x2, y2, conf, cls]`.\n *\n * Matches Ultralytics' `boxes.data`.\n */\n get data(): Float32Array {\n const out = new Float32Array(this.length * 6);\n for (let i = 0; i < this.length; i++) {\n out[i * 6] = this.xyxy[i * 4] as number;\n out[i * 6 + 1] = this.xyxy[i * 4 + 1] as number;\n out[i * 6 + 2] = this.xyxy[i * 4 + 2] as number;\n out[i * 6 + 3] = this.xyxy[i * 4 + 3] as number;\n out[i * 6 + 4] = this.conf[i] as number;\n out[i * 6 + 5] = this.cls[i] as number;\n }\n return out;\n }\n}\n\n/**\n * Top-k classification probabilities for a single image.\n *\n * Mirrors Ultralytics' `Probs` interface.\n */\nexport class Probs {\n /** @param data `[numClasses]` per-class probabilities, indexed by class id. */\n constructor(public readonly data: Float32Array) {}\n\n /** Number of classes. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[numClasses]` shape of the underlying vector. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n /** Index of the most probable class. */\n get top1(): number {\n if (this.data.length === 0) return 0;\n let best = 0;\n let bestVal = this.data[0] as number;\n for (let i = 1; i < this.data.length; i++) {\n const v = this.data[i] as number;\n if (v > bestVal) {\n best = i;\n bestVal = v;\n }\n }\n return best;\n }\n\n /** Probability of the top-1 class. */\n get top1conf(): number {\n if (this.data.length === 0) return 0;\n return this.data[this.top1] as number;\n }\n\n /** Indices of the top-5 most probable classes, descending. */\n get top5(): Int32Array {\n return this._topK(5).indices;\n }\n\n /** Probabilities of the top-5 classes, descending. */\n get top5conf(): Float32Array {\n return this._topK(5).values;\n }\n\n private _topK(k: number): { indices: Int32Array; values: Float32Array } {\n const n = Math.min(k, this.data.length);\n const order: number[] = [];\n for (let i = 0; i < this.data.length; i++) order.push(i);\n order.sort((a, b) => (this.data[b] as number) - (this.data[a] as number));\n const indices = new Int32Array(n);\n const values = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n indices[i] = order[i] as number;\n values[i] = this.data[order[i] as number] as number;\n }\n return { indices, values };\n }\n}\n\n/**\n * Per-instance binary masks for a single image.\n *\n * Each mask is cropped to its instance's bounding box. To paint masks onto\n * a full-image canvas, use `xyxy[i]` as the top-left target.\n */\nexport class Masks {\n /**\n * @param data Per-instance binary masks (`Mask` objects from `types.ts`).\n * @param xyxy Flat `[N, 4]` of bounding-box coordinates in original pixels.\n * @param origShape `[height, width]` of the original image.\n */\n constructor(\n public readonly data: ReadonlyArray<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }>,\n public readonly xyxy: Float32Array,\n public readonly origShape: readonly [number, number],\n ) {}\n\n /** Number of instance masks. */\n get length(): number {\n return this.data.length;\n }\n\n /** `[N]` shape of the masks collection. */\n get shape(): readonly [number] {\n return [this.length];\n }\n\n [Symbol.iterator](): Iterator<{\n readonly data: Uint8Array;\n readonly width: number;\n readonly height: number;\n }> {\n return this.data[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image detection envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link DetectionResult} entries, so legacy\n * code that did `for (const d of detector.predict(img))` only needs an\n * extra `[0]` to bridge:\n *\n * ```typescript\n * for (const d of (await detector.predict(img))[0]) {\n * console.log(d.cls, d.conf, d.box.xyxy);\n * }\n * ```\n *\n * For numpy-style bulk access, use the `boxes` collection.\n */\nexport class DetectionResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image envelope for a fused detect→classify pipeline.\n *\n * Structurally a {@link DetectionResults} with a second class map: every\n * detection it yields carries a populated `classification`, and the two stages\n * have their own, unrelated label spaces — a detector that finds `sheep`\n * feeding a classifier that answers `famacha_3` shares no class ids with it.\n * Merging them into one `names` record would make `cls` and\n * `classification.cls` look comparable when they are not.\n *\n * ```typescript\n * const result = (await pipeline.predict(\"flock.jpg\"))[0];\n * for (const detection of result) {\n * console.log(detection.name, detection.conf, detection.classification?.name);\n * }\n * ```\n */\nexport class DetectClassifyResults implements Iterable<DetectionResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly detections: readonly DetectionResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly classifierNames: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving detections. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance detections. */\n get(index: number): DetectionResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<DetectionResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n\n/**\n * Per-image classification envelope (Ultralytics-style `Results`).\n */\nexport class ClassificationResults {\n constructor(\n public readonly probs: Probs,\n public readonly result: ClassificationResult,\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Top-1 class index (Ultralytics-style alias). */\n get cls(): number {\n return this.probs.top1;\n }\n\n /** Top-1 confidence (Ultralytics-style alias). */\n get conf(): number {\n return this.probs.top1conf;\n }\n\n /** Top-1 class name. */\n get name(): string {\n return this.names[this.cls] ?? `class_${this.cls}`;\n }\n\n /** Per-class probability list, sorted descending (legacy field). */\n get probabilities(): readonly ClassificationResult[\"probabilities\"][number][] {\n return this.result.probabilities;\n }\n}\n\n/**\n * Per-image instance-segmentation envelope (Ultralytics-style `Results`).\n *\n * Iterating yields per-instance {@link SegmentationResult} entries. `boxes`\n * and `masks` mirror Ultralytics' bulk-array views.\n */\nexport class SegmentationResults implements Iterable<SegmentationResult> {\n constructor(\n public readonly boxes: Boxes,\n public readonly masks: Masks,\n public readonly detections: readonly SegmentationResult[],\n public readonly names: Readonly<Record<number, string>>,\n public readonly origImg: RGBImage,\n public readonly origShape: readonly [number, number],\n public readonly path: string | null = null,\n public readonly speed: Readonly<Speed> = NO_SPEED,\n ) {}\n\n /** Number of surviving instances. */\n get length(): number {\n return this.detections.length;\n }\n\n /** Index into the per-instance results. */\n get(index: number): SegmentationResult | undefined {\n return this.detections[index];\n }\n\n [Symbol.iterator](): Iterator<SegmentationResult> {\n return this.detections[Symbol.iterator]();\n }\n}\n"],"mappings":";AAgCA,IAAM,IAAkB;CAAE,MAAM;CAAG,YAAY;CAAG,WAAW;CAAG,aAAa;AAAE,GASlE,IAAb,MAAmB;CAQK;CACA;CACA;CACA;CAJpB,YACI,GACA,GACA,GACA,GACF;EADkB,AAHA,KAAA,OAAA,GACA,KAAA,MAAA,GACA,KAAA,OAAA,GACA,KAAA,YAAA;CACjB;CAGH,IAAI,SAAiB;EACjB,OAAO,KAAK,IAAI;CACpB;CAGA,IAAI,QAAmC;EACnC,OAAO,CAAC,KAAK,QAAQ,CAAC;CAC1B;CAGA,IAAI,OAAqB;EACrB,IAAM,IAAM,IAAI,aAAa,KAAK,KAAK,MAAM;EAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GAClC,IAAM,IAAK,KAAK,KAAK,IAAI,IACnB,IAAK,KAAK,KAAK,IAAI,IAAI,IACvB,IAAK,KAAK,KAAK,IAAI,IAAI,IACvB,IAAK,KAAK,KAAK,IAAI,IAAI;GAI7B,AAHA,EAAI,IAAI,MAAM,IAAK,KAAM,GACzB,EAAI,IAAI,IAAI,MAAM,IAAK,KAAM,GAC7B,EAAI,IAAI,IAAI,KAAK,IAAK,GACtB,EAAI,IAAI,IAAI,KAAK,IAAK;EAC1B;EACA,OAAO;CACX;CAGA,IAAI,QAAsB;EACtB,IAAM,CAAC,GAAG,KAAK,KAAK,WACd,IAAM,IAAI,aAAa,KAAK,KAAK,MAAM;EAC7C,IAAI,KAAK,WAAW,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO;EAClD,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAI7B,AAHA,EAAI,IAAI,KAAM,KAAK,KAAK,IAAI,KAAgB,GAC5C,EAAI,IAAI,IAAI,KAAM,KAAK,KAAK,IAAI,IAAI,KAAgB,GACpD,EAAI,IAAI,IAAI,KAAM,KAAK,KAAK,IAAI,IAAI,KAAgB,GACpD,EAAI,IAAI,IAAI,KAAM,KAAK,KAAK,IAAI,IAAI,KAAgB;EAExD,OAAO;CACX;CAGA,IAAI,QAAsB;EACtB,IAAM,IAAO,KAAK,MACZ,CAAC,GAAG,KAAK,KAAK;EACpB,IAAI,KAAK,WAAW,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO;EAClD,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAI7B,AAHA,EAAK,IAAI,KAAM,EAAK,IAAI,KAAgB,GACxC,EAAK,IAAI,IAAI,KAAM,EAAK,IAAI,IAAI,KAAgB,GAChD,EAAK,IAAI,IAAI,KAAM,EAAK,IAAI,IAAI,KAAgB,GAChD,EAAK,IAAI,IAAI,KAAM,EAAK,IAAI,IAAI,KAAgB;EAEpD,OAAO;CACX;CAOA,IAAI,OAAqB;EACrB,IAAM,IAAM,IAAI,aAAa,KAAK,SAAS,CAAC;EAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAM7B,AALA,EAAI,IAAI,KAAK,KAAK,KAAK,IAAI,IAC3B,EAAI,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,IACnC,EAAI,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,IACnC,EAAI,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,IACnC,EAAI,IAAI,IAAI,KAAK,KAAK,KAAK,IAC3B,EAAI,IAAI,IAAI,KAAK,KAAK,IAAI;EAE9B,OAAO;CACX;AACJ,GAOa,IAAb,MAAmB;CAEa;CAA5B,YAAY,GAAoC;EAApB,KAAA,OAAA;CAAqB;CAGjD,IAAI,SAAiB;EACjB,OAAO,KAAK,KAAK;CACrB;CAGA,IAAI,QAA2B;EAC3B,OAAO,CAAC,KAAK,MAAM;CACvB;CAGA,IAAI,OAAe;EACf,IAAI,KAAK,KAAK,WAAW,GAAG,OAAO;EACnC,IAAI,IAAO,GACP,IAAU,KAAK,KAAK;EACxB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK;GACvC,IAAM,IAAI,KAAK,KAAK;GACpB,AAAI,IAAI,MACJ,IAAO,GACP,IAAU;EAElB;EACA,OAAO;CACX;CAGA,IAAI,WAAmB;EAEnB,OADI,KAAK,KAAK,WAAW,IAAU,IAC5B,KAAK,KAAK,KAAK;CAC1B;CAGA,IAAI,OAAmB;EACnB,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC;CACzB;CAGA,IAAI,WAAyB;EACzB,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC;CACzB;CAEA,MAAc,GAA0D;EACpE,IAAM,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,GAChC,IAAkB,CAAC;EACzB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK,EAAM,KAAK,CAAC;EACvD,EAAM,MAAM,GAAG,MAAO,KAAK,KAAK,KAAiB,KAAK,KAAK,EAAa;EACxE,IAAM,IAAU,IAAI,WAAW,CAAC,GAC1B,IAAS,IAAI,aAAa,CAAC;EACjC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAEnB,AADA,EAAQ,KAAK,EAAM,IACnB,EAAO,KAAK,KAAK,KAAK,EAAM;EAEhC,OAAO;GAAE;GAAS;EAAO;CAC7B;AACJ,GAQa,IAAb,MAAmB;CAOK;CAKA;CACA;CAPpB,YACI,GAKA,GACA,GACF;EADkB,AANA,KAAA,OAAA,GAKA,KAAA,OAAA,GACA,KAAA,YAAA;CACjB;CAGH,IAAI,SAAiB;EACjB,OAAO,KAAK,KAAK;CACrB;CAGA,IAAI,QAA2B;EAC3B,OAAO,CAAC,KAAK,MAAM;CACvB;CAEA,CAAC,OAAO,YAIL;EACC,OAAO,KAAK,KAAK,OAAO,SAAS,CAAC;CACtC;AACJ,GAiBa,IAAb,MAAmE;CAE3C;CACA;CACA;CACA;CACA;CACA;CACA;CAPpB,YACI,GACA,GACA,GACA,GACA,GACA,IAAsC,MACtC,IAAyC,GAC3C;EADkB,AANA,KAAA,QAAA,GACA,KAAA,aAAA,GACA,KAAA,QAAA,GACA,KAAA,UAAA,GACA,KAAA,YAAA,GACA,KAAA,OAAA,GACA,KAAA,QAAA;CACjB;CAGH,IAAI,SAAiB;EACjB,OAAO,KAAK,WAAW;CAC3B;CAGA,IAAI,GAA4C;EAC5C,OAAO,KAAK,WAAW;CAC3B;CAEA,CAAC,OAAO,YAAuC;EAC3C,OAAO,KAAK,WAAW,OAAO,SAAS,CAAC;CAC5C;AACJ,GAmBa,IAAb,MAAwE;CAEhD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CARpB,YACI,GACA,GACA,GACA,GACA,GACA,GACA,IAAsC,MACtC,IAAyC,GAC3C;EADkB,AAPA,KAAA,QAAA,GACA,KAAA,aAAA,GACA,KAAA,QAAA,GACA,KAAA,kBAAA,GACA,KAAA,UAAA,GACA,KAAA,YAAA,GACA,KAAA,OAAA,GACA,KAAA,QAAA;CACjB;CAGH,IAAI,SAAiB;EACjB,OAAO,KAAK,WAAW;CAC3B;CAGA,IAAI,GAA4C;EAC5C,OAAO,KAAK,WAAW;CAC3B;CAEA,CAAC,OAAO,YAAuC;EAC3C,OAAO,KAAK,WAAW,OAAO,SAAS,CAAC;CAC5C;AACJ,GAKa,IAAb,MAAmC;CAEX;CACA;CACA;CACA;CACA;CACA;CACA;CAPpB,YACI,GACA,GACA,GACA,GACA,GACA,IAAsC,MACtC,IAAyC,GAC3C;EADkB,AANA,KAAA,QAAA,GACA,KAAA,SAAA,GACA,KAAA,QAAA,GACA,KAAA,UAAA,GACA,KAAA,YAAA,GACA,KAAA,OAAA,GACA,KAAA,QAAA;CACjB;CAGH,IAAI,MAAc;EACd,OAAO,KAAK,MAAM;CACtB;CAGA,IAAI,OAAe;EACf,OAAO,KAAK,MAAM;CACtB;CAGA,IAAI,OAAe;EACf,OAAO,KAAK,MAAM,KAAK,QAAQ,SAAS,KAAK;CACjD;CAGA,IAAI,gBAA0E;EAC1E,OAAO,KAAK,OAAO;CACvB;AACJ,GAQa,IAAb,MAAyE;CAEjD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CARpB,YACI,GACA,GACA,GACA,GACA,GACA,GACA,IAAsC,MACtC,IAAyC,GAC3C;EADkB,AAPA,KAAA,QAAA,GACA,KAAA,QAAA,GACA,KAAA,aAAA,GACA,KAAA,QAAA,GACA,KAAA,UAAA,GACA,KAAA,YAAA,GACA,KAAA,OAAA,GACA,KAAA,QAAA;CACjB;CAGH,IAAI,SAAiB;EACjB,OAAO,KAAK,WAAW;CAC3B;CAGA,IAAI,GAA+C;EAC/C,OAAO,KAAK,WAAW;CAC3B;CAEA,CAAC,OAAO,YAA0C;EAC9C,OAAO,KAAK,WAAW,OAAO,SAAS,CAAC;CAC5C;AACJ"}
@@ -1,2 +1,2 @@
1
- var e=class{_session;constructor(e){this._session=e}get session(){return this._session}};exports.VisionTask=e;
1
+ const e=require("../core/exceptions.cjs");var t=class{_session;constructor(e){this._session=e}get session(){return this._session}};function n(e){return e.toFixed(6).replace(/0+$/,``).replace(/\.$/,``)}function r(t,r){if(!(!r.raiseOnEmpty||t>0))throw new e.NoDetectionsError(`No detections${r.path?` in ${r.path}`:``}${r.classes===void 0?``:` among classes [${[...r.classes].sort((e,t)=>e-t).join(`, `)}]`}: nothing cleared confThreshold=${n(r.confThreshold)}.`)}exports.VisionTask=t,exports.requireDetections=r;
2
2
  //# sourceMappingURL=base.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.cjs","names":[],"sources":["../../../src/vision/tasks/base.ts"],"sourcesContent":["/**\n * Common foundation for task-oriented vision SDK objects.\n *\n * The base only owns the {@link OrtSession} — label resolution lives in each\n * subclass because how `numClasses` is read from the model differs per task.\n */\n\nimport type { OrtSession } from \"../core/session\";\n\nexport abstract class VisionTask {\n protected constructor(protected readonly _session: OrtSession) {}\n\n /** The underlying {@link OrtSession} used to run inference. */\n get session(): OrtSession {\n return this._session;\n }\n}\n"],"mappings":"AASA,IAAsB,EAAtB,KAAiC,CACY,SAAzC,YAAsB,EAAyC,CAAtB,KAAA,SAAA,CAAuB,CAGhE,IAAI,SAAsB,CACtB,OAAO,KAAK,QAChB,CACJ"}
1
+ {"version":3,"file":"base.cjs","names":[],"sources":["../../../src/vision/tasks/base.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Common foundation for task-oriented vision SDK objects.\n *\n * The base only owns the {@link OrtSession} — label resolution lives in each\n * subclass because how `numClasses` is read from the model differs per task.\n */\n\nimport { NoDetectionsError } from \"../core/exceptions\";\nimport type { OrtSession } from \"../core/session\";\n\nexport abstract class VisionTask {\n protected constructor(protected readonly _session: OrtSession) {}\n\n /** The underlying {@link OrtSession} used to run inference. */\n get session(): OrtSession {\n return this._session;\n }\n}\n\n/**\n * Render a confidence threshold the way the Python SDK renders it.\n *\n * JavaScript and Python disagree on how a number becomes text. A whole\n * threshold is `1` here and `1.0` there; JavaScript holds off on exponent\n * notation until `1e-7` while Python switches at `1e-5`. A fused pipeline is\n * built once and runs under both runtimes from the same file, so a message that\n * quotes the threshold has to quote it identically — otherwise the two SDKs\n * describe the same run with two different numbers.\n *\n * Six decimals with the trailing zeros trimmed covers every threshold a caller\n * can meaningfully set and agrees byte for byte with `_format_threshold` in the\n * Python SDK's `tasks/base.py`. The pairing is fixed by a shared table in both\n * test suites, so a change on one side that is not mirrored on the other fails.\n *\n * @param value The threshold to render.\n * @returns The threshold as text, without trailing zeros or a trailing dot.\n */\nfunction formatThreshold(value: number): string {\n return value.toFixed(6).replace(/0+$/, \"\").replace(/\\.$/, \"\");\n}\n\n/**\n * Turn an empty result into an error, when the caller asked for that.\n *\n * Shared by every task that can come back with nothing — {@link Detector},\n * {@link Segmenter} and {@link DetectClassify} — so the three agree on when\n * they throw and on what the message says. The message names the two settings\n * that decide the outcome, because \"no detections\" on its own leaves the reader\n * unable to tell a blank image from a threshold set too high.\n *\n * @param count How many detections survived every filter.\n * @param options The flag for this call, the threshold actually applied (after\n * any per-call override), the class allowlist if one narrowed the search, and\n * the source path when the input was one.\n * @throws {@link NoDetectionsError} when the flag is set and `count` is zero.\n */\nexport function requireDetections(\n count: number,\n options: {\n readonly raiseOnEmpty: boolean;\n readonly confThreshold: number;\n readonly classes: readonly number[] | undefined;\n readonly path: string | null;\n },\n): void {\n if (!options.raiseOnEmpty || count > 0) return;\n const where = options.path ? ` in ${options.path}` : \"\";\n const narrowed =\n options.classes === undefined\n ? \"\"\n : ` among classes [${[...options.classes].sort((a, b) => a - b).join(\", \")}]`;\n throw new NoDetectionsError(\n `No detections${where}${narrowed}: nothing cleared confThreshold=${formatThreshold(options.confThreshold)}.`,\n );\n}\n"],"mappings":"0CAWA,IAAsB,EAAtB,KAAiC,CACY,SAAzC,YAAsB,EAAyC,CAAtB,KAAA,SAAA,CAAuB,CAGhE,IAAI,SAAsB,CACtB,OAAO,KAAK,QAChB,CACJ,EAoBA,SAAS,EAAgB,EAAuB,CAC5C,OAAO,EAAM,QAAQ,CAAC,CAAC,CAAC,QAAQ,MAAO,EAAE,CAAC,CAAC,QAAQ,MAAO,EAAE,CAChE,CAiBA,SAAgB,EACZ,EACA,EAMI,CACA,MAAC,EAAQ,cAAgB,EAAQ,GAMrC,MAAM,IAAI,EAAA,kBACN,gBANU,EAAQ,KAAO,OAAO,EAAQ,OAAS,KAEjD,EAAQ,UAAY,IAAA,GACd,GACA,mBAAmB,CAAC,GAAG,EAAQ,OAAO,CAAC,CAAC,MAAM,EAAG,IAAM,EAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,GAE9C,kCAAkC,EAAgB,EAAQ,aAAa,EAAE,EAC9G,CACJ"}
@@ -1,5 +1,6 @@
1
+ import { NoDetectionsError as e } from "../core/exceptions.js";
1
2
  //#region src/vision/tasks/base.ts
2
- var e = class {
3
+ var t = class {
3
4
  _session;
4
5
  constructor(e) {
5
6
  this._session = e;
@@ -8,7 +9,13 @@ var e = class {
8
9
  return this._session;
9
10
  }
10
11
  };
12
+ function n(e) {
13
+ return e.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
14
+ }
15
+ function r(t, r) {
16
+ if (!(!r.raiseOnEmpty || t > 0)) throw new e(`No detections${r.path ? ` in ${r.path}` : ""}${r.classes === void 0 ? "" : ` among classes [${[...r.classes].sort((e, t) => e - t).join(", ")}]`}: nothing cleared confThreshold=${n(r.confThreshold)}.`);
17
+ }
11
18
  //#endregion
12
- export { e as VisionTask };
19
+ export { t as VisionTask, r as requireDetections };
13
20
 
14
21
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../../../src/vision/tasks/base.ts"],"sourcesContent":["/**\n * Common foundation for task-oriented vision SDK objects.\n *\n * The base only owns the {@link OrtSession} — label resolution lives in each\n * subclass because how `numClasses` is read from the model differs per task.\n */\n\nimport type { OrtSession } from \"../core/session\";\n\nexport abstract class VisionTask {\n protected constructor(protected readonly _session: OrtSession) {}\n\n /** The underlying {@link OrtSession} used to run inference. */\n get session(): OrtSession {\n return this._session;\n }\n}\n"],"mappings":";AASA,IAAsB,IAAtB,MAAiC;CACY;CAAzC,YAAsB,GAAyC;EAAtB,KAAA,WAAA;CAAuB;CAGhE,IAAI,UAAsB;EACtB,OAAO,KAAK;CAChB;AACJ"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../../src/vision/tasks/base.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Common foundation for task-oriented vision SDK objects.\n *\n * The base only owns the {@link OrtSession} — label resolution lives in each\n * subclass because how `numClasses` is read from the model differs per task.\n */\n\nimport { NoDetectionsError } from \"../core/exceptions\";\nimport type { OrtSession } from \"../core/session\";\n\nexport abstract class VisionTask {\n protected constructor(protected readonly _session: OrtSession) {}\n\n /** The underlying {@link OrtSession} used to run inference. */\n get session(): OrtSession {\n return this._session;\n }\n}\n\n/**\n * Render a confidence threshold the way the Python SDK renders it.\n *\n * JavaScript and Python disagree on how a number becomes text. A whole\n * threshold is `1` here and `1.0` there; JavaScript holds off on exponent\n * notation until `1e-7` while Python switches at `1e-5`. A fused pipeline is\n * built once and runs under both runtimes from the same file, so a message that\n * quotes the threshold has to quote it identically — otherwise the two SDKs\n * describe the same run with two different numbers.\n *\n * Six decimals with the trailing zeros trimmed covers every threshold a caller\n * can meaningfully set and agrees byte for byte with `_format_threshold` in the\n * Python SDK's `tasks/base.py`. The pairing is fixed by a shared table in both\n * test suites, so a change on one side that is not mirrored on the other fails.\n *\n * @param value The threshold to render.\n * @returns The threshold as text, without trailing zeros or a trailing dot.\n */\nfunction formatThreshold(value: number): string {\n return value.toFixed(6).replace(/0+$/, \"\").replace(/\\.$/, \"\");\n}\n\n/**\n * Turn an empty result into an error, when the caller asked for that.\n *\n * Shared by every task that can come back with nothing — {@link Detector},\n * {@link Segmenter} and {@link DetectClassify} — so the three agree on when\n * they throw and on what the message says. The message names the two settings\n * that decide the outcome, because \"no detections\" on its own leaves the reader\n * unable to tell a blank image from a threshold set too high.\n *\n * @param count How many detections survived every filter.\n * @param options The flag for this call, the threshold actually applied (after\n * any per-call override), the class allowlist if one narrowed the search, and\n * the source path when the input was one.\n * @throws {@link NoDetectionsError} when the flag is set and `count` is zero.\n */\nexport function requireDetections(\n count: number,\n options: {\n readonly raiseOnEmpty: boolean;\n readonly confThreshold: number;\n readonly classes: readonly number[] | undefined;\n readonly path: string | null;\n },\n): void {\n if (!options.raiseOnEmpty || count > 0) return;\n const where = options.path ? ` in ${options.path}` : \"\";\n const narrowed =\n options.classes === undefined\n ? \"\"\n : ` among classes [${[...options.classes].sort((a, b) => a - b).join(\", \")}]`;\n throw new NoDetectionsError(\n `No detections${where}${narrowed}: nothing cleared confThreshold=${formatThreshold(options.confThreshold)}.`,\n );\n}\n"],"mappings":";;AAWA,IAAsB,IAAtB,MAAiC;CACY;CAAzC,YAAsB,GAAyC;EAAtB,KAAA,WAAA;CAAuB;CAGhE,IAAI,UAAsB;EACtB,OAAO,KAAK;CAChB;AACJ;AAoBA,SAAS,EAAgB,GAAuB;CAC5C,OAAO,EAAM,QAAQ,CAAC,CAAC,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE;AAChE;AAiBA,SAAgB,EACZ,GACA,GAMI;CACA,OAAC,EAAQ,gBAAgB,IAAQ,IAMrC,MAAM,IAAI,EACN,gBANU,EAAQ,OAAO,OAAO,EAAQ,SAAS,KAEjD,EAAQ,YAAY,KAAA,IACd,KACA,mBAAmB,CAAC,GAAG,EAAQ,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,GAE9C,kCAAkC,EAAgB,EAAQ,aAAa,EAAE,EAC9G;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"classifier.cjs","names":[],"sources":["../../../src/vision/tasks/classifier.ts"],"sourcesContent":["/**\n * Image classification task using ONNX Runtime Web.\n */\n\nimport type * as ort from \"onnxruntime-web\";\n\nimport { type ModelSource, type OrtSessionOptions, OrtSession } from \"../core/session\";\nimport { SpeedTimer } from \"../core/timing\";\nimport { type ImageInput, loadImage } from \"../io/image\";\nimport { classificationNumClasses, resolveInputSize } from \"../core/graph\";\nimport { modelNames } from \"../core/metadata\";\nimport { type LabelSpec, resolveLabels } from \"../labels\";\nimport { softmax, topK } from \"../postprocess/classification\";\nimport { normalize, resize, toCHW, toFloat32Tensor } from \"../preprocess/image\";\nimport { ClassificationResults, Probs } from \"../results\";\nimport { VisionTask } from \"./base\";\nimport { type ClassProbability, type ClassificationResult, type RGBImage } from \"../types\";\n\nconst IMAGENET_MEAN: readonly [number, number, number] = [0.485, 0.456, 0.406];\nconst IMAGENET_STD: readonly [number, number, number] = [0.229, 0.224, 0.225];\n\nexport interface ClassifierOptions extends OrtSessionOptions {\n /**\n * Class label spec — see {@link resolveLabels}.\n *\n * Optional: when omitted, the names the export baked into the model are used\n * (Ultralytics writes them as `names` in the metadata map). Only when the\n * model carries none does this fall back to generated `class_<id>` labels.\n * Passing a spec always wins, for a model whose names are wrong or absent.\n */\n readonly labels?: LabelSpec;\n /**\n * Number of classes the model can predict.\n *\n * Optional: inferred from the classification head's declared output shape\n * `(B, nc)`. Pass it to validate that the supplied labels match the model.\n */\n readonly numClasses?: number;\n /**\n * Model input `[width, height]` in pixels.\n *\n * Only used when the model's graph leaves its spatial axes dynamic: a graph\n * that declares a static size always wins, since that is the only shape ONNX\n * Runtime will accept. Defaults to `[224, 224]`.\n */\n readonly inputSize?: readonly [number, number];\n /** Per-channel RGB mean used for normalization. Defaults to ImageNet. */\n readonly mean?: readonly [number, number, number];\n /** Per-channel RGB standard deviation. Defaults to ImageNet. */\n readonly std?: readonly [number, number, number];\n /**\n * If `true` (default), apply softmax to the raw model output. Set to\n * `false` for models whose final layer already produces a probability\n * distribution.\n */\n readonly applySoftmax?: boolean;\n}\n\nexport interface ClassifierPredictOptions {\n /**\n * If set, the per-class probability list in `results[0].result.probabilities`\n * is truncated to the top-K entries. The bulk `probs` view always exposes\n * the full vector.\n */\n readonly topK?: number;\n}\n\n/**\n * Image classifier wrapping an ONNX model with ImageNet-style preprocessing.\n *\n * `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a\n * single image), mirroring Ultralytics' API. The envelope exposes a `probs`\n * collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the\n * legacy per-class probability list with names already resolved.\n *\n * Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,\n * NCHW layout, batch size 1, softmax applied to the raw output.\n *\n * @example\n * ```typescript\n * const clf = await Classifier.create(\"/models/resnet50.onnx\", {\n * labels: [\"tench\", \"goldfish\", ...] // 1000 ImageNet labels\n * });\n * const r = (await clf.predict(\"/images/dog.jpg\"))[0];\n * console.log(r.cls, r.conf, r.name);\n * console.log(r.probs.top5, r.probs.top5conf);\n * ```\n */\nexport class Classifier extends VisionTask {\n private constructor(\n session: OrtSession,\n private readonly _labels: readonly string[],\n private readonly _names: Readonly<Record<number, string>>,\n private readonly _inputSize: readonly [number, number],\n private readonly _mean: readonly [number, number, number],\n private readonly _std: readonly [number, number, number],\n private readonly _applySoftmax: boolean,\n ) {\n super(session);\n }\n\n /** Load the model and resolve labels. */\n static async create(model: ModelSource, options: ClassifierOptions = {}): Promise<Classifier> {\n const session = await OrtSession.create(model, options);\n const numClasses =\n options.numClasses ?? classificationNumClasses(session.outputShape) ?? undefined;\n const labels = resolveLabels(options.labels ?? modelNames(session.metadata), {\n numClasses,\n });\n const names: Record<number, string> = {};\n for (let i = 0; i < labels.length; i++) {\n names[i] = labels[i] as string;\n }\n return new Classifier(\n session,\n labels,\n names,\n resolveInputSize({\n graphShape: session.inputShape,\n requested: options.inputSize,\n fallback: [224, 224],\n }),\n options.mean ?? IMAGENET_MEAN,\n options.std ?? IMAGENET_STD,\n options.applySoftmax ?? true,\n );\n }\n\n /** Class labels indexed by class id. */\n get labels(): readonly string[] {\n return this._labels;\n }\n\n /** Class id → class name dict (matches Ultralytics' `model.names`). */\n get names(): Readonly<Record<number, string>> {\n return this._names;\n }\n\n /**\n * The `[width, height]` this task preprocesses to.\n *\n * Resolved at creation time from the model's graph when it declares a static\n * input, so reading it back tells you the resolution inference really runs at\n * — not merely what was requested.\n */\n get inputSize(): readonly [number, number] {\n return this._inputSize;\n }\n\n /** Number of classes the model can predict. */\n get numClasses(): number {\n return this._labels.length;\n }\n\n /** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */\n async call(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n return this.predict(image, options);\n }\n\n /** Run classification on a single image. */\n async predict(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n const timer = new SpeedTimer();\n const path = typeof image === \"string\" ? image : null;\n const original = await loadImage(image);\n timer.stage(\"load\");\n const tensor = this._preprocess(original);\n timer.stage(\"preprocess\");\n const outputs = await this._session.run({ [this._session.inputName]: tensor });\n timer.stage(\"inference\");\n const firstOutputName = this._session.outputNames[0];\n if (firstOutputName === undefined) {\n throw new Error(\"Classifier model has no outputs.\");\n }\n const raw = outputs[firstOutputName];\n if (raw === undefined) {\n throw new Error(\n `Classifier model output ${firstOutputName} missing from run() result.`,\n );\n }\n const fullProbs = this._postprocess(raw.data as Float32Array);\n\n const { indices, values } = topK(fullProbs, options.topK ?? null);\n const probabilities: ClassProbability[] = [];\n for (let i = 0; i < indices.length; i++) {\n const id = indices[i] as number;\n const className = this._labels[id] ?? `class_${id}`;\n probabilities.push({\n classId: id,\n className,\n probability: values[i] as number,\n cls: id,\n name: className,\n conf: values[i] as number,\n });\n }\n if (probabilities.length === 0) {\n throw new Error(\"Classifier produced no probabilities (empty output).\");\n }\n\n const top = probabilities[0] as ClassProbability;\n const result: ClassificationResult = {\n classId: top.classId,\n className: top.className,\n confidence: top.probability,\n cls: top.classId,\n name: top.className,\n conf: top.probability,\n image: original,\n probabilities,\n };\n\n const orig: readonly [number, number] = [original.height, original.width];\n const probs = new Probs(fullProbs);\n timer.stage(\"postprocess\");\n return [\n new ClassificationResults(\n probs,\n result,\n this._names,\n original,\n orig,\n path,\n timer.speed(),\n ),\n ];\n }\n\n private _preprocess(image: RGBImage): ort.Tensor {\n const [tw, th] = this._inputSize;\n const resized = resize(image, tw, th);\n const normalized = normalize(resized, this._mean, this._std);\n const chw = toCHW(normalized, resized.width, resized.height, 3);\n return toFloat32Tensor(chw, [1, 3, resized.height, resized.width]);\n }\n\n private _postprocess(raw: Float32Array): Float32Array {\n return this._applySoftmax ? softmax(raw) : new Float32Array(raw);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"classifier.cjs","names":[],"sources":["../../../src/vision/tasks/classifier.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image classification task using ONNX Runtime Web.\n */\n\nimport type * as ort from \"onnxruntime-web\";\n\nimport { type ModelSource, type OrtSessionOptions, OrtSession } from \"../core/session\";\nimport { SpeedTimer } from \"../core/timing\";\nimport { type ImageInput, loadImage } from \"../io/image\";\nimport { classificationNumClasses, resolveInputSize } from \"../core/graph\";\nimport { modelNames } from \"../core/metadata\";\nimport { type LabelSpec, resolveLabels } from \"../labels\";\nimport { softmax, topK } from \"../postprocess/classification\";\nimport { normalize, resize, toCHW, toFloat32Tensor } from \"../preprocess/image\";\nimport { ClassificationResults, Probs } from \"../results\";\nimport { VisionTask } from \"./base\";\nimport { type ClassProbability, type ClassificationResult, type RGBImage } from \"../types\";\n\nconst IMAGENET_MEAN: readonly [number, number, number] = [0.485, 0.456, 0.406];\nconst IMAGENET_STD: readonly [number, number, number] = [0.229, 0.224, 0.225];\n\nexport interface ClassifierOptions extends OrtSessionOptions {\n /**\n * Class label spec — see {@link resolveLabels}.\n *\n * Optional: when omitted, the names the export baked into the model are used\n * (Ultralytics writes them as `names` in the metadata map). Only when the\n * model carries none does this fall back to generated `class_<id>` labels.\n * Passing a spec always wins, for a model whose names are wrong or absent.\n */\n readonly labels?: LabelSpec;\n /**\n * Number of classes the model can predict.\n *\n * Optional: inferred from the classification head's declared output shape\n * `(B, nc)`. Pass it to validate that the supplied labels match the model.\n */\n readonly numClasses?: number;\n /**\n * Model input `[width, height]` in pixels.\n *\n * Only used when the model's graph leaves its spatial axes dynamic: a graph\n * that declares a static size always wins, since that is the only shape ONNX\n * Runtime will accept. Defaults to `[224, 224]`.\n */\n readonly inputSize?: readonly [number, number];\n /** Per-channel RGB mean used for normalization. Defaults to ImageNet. */\n readonly mean?: readonly [number, number, number];\n /** Per-channel RGB standard deviation. Defaults to ImageNet. */\n readonly std?: readonly [number, number, number];\n /**\n * If `true` (default), apply softmax to the raw model output. Set to\n * `false` for models whose final layer already produces a probability\n * distribution.\n */\n readonly applySoftmax?: boolean;\n}\n\nexport interface ClassifierPredictOptions {\n /**\n * If set, the per-class probability list in `results[0].result.probabilities`\n * is truncated to the top-K entries. The bulk `probs` view always exposes\n * the full vector.\n */\n readonly topK?: number;\n}\n\n/**\n * Image classifier wrapping an ONNX model with ImageNet-style preprocessing.\n *\n * `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a\n * single image), mirroring Ultralytics' API. The envelope exposes a `probs`\n * collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the\n * legacy per-class probability list with names already resolved.\n *\n * Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,\n * NCHW layout, batch size 1, softmax applied to the raw output.\n *\n * @example\n * ```typescript\n * const clf = await Classifier.create(\"/models/resnet50.onnx\", {\n * labels: [\"tench\", \"goldfish\", ...] // 1000 ImageNet labels\n * });\n * const r = (await clf.predict(\"/images/dog.jpg\"))[0];\n * console.log(r.cls, r.conf, r.name);\n * console.log(r.probs.top5, r.probs.top5conf);\n * ```\n */\nexport class Classifier extends VisionTask {\n private constructor(\n session: OrtSession,\n private readonly _labels: readonly string[],\n private readonly _names: Readonly<Record<number, string>>,\n private readonly _inputSize: readonly [number, number],\n private readonly _mean: readonly [number, number, number],\n private readonly _std: readonly [number, number, number],\n private readonly _applySoftmax: boolean,\n ) {\n super(session);\n }\n\n /** Load the model and resolve labels. */\n static async create(model: ModelSource, options: ClassifierOptions = {}): Promise<Classifier> {\n const session = await OrtSession.create(model, options);\n const numClasses =\n options.numClasses ?? classificationNumClasses(session.outputShape) ?? undefined;\n const labels = resolveLabels(options.labels ?? modelNames(session.metadata), {\n numClasses,\n });\n const names: Record<number, string> = {};\n for (let i = 0; i < labels.length; i++) {\n names[i] = labels[i] as string;\n }\n return new Classifier(\n session,\n labels,\n names,\n resolveInputSize({\n graphShape: session.inputShape,\n requested: options.inputSize,\n fallback: [224, 224],\n }),\n options.mean ?? IMAGENET_MEAN,\n options.std ?? IMAGENET_STD,\n options.applySoftmax ?? true,\n );\n }\n\n /** Class labels indexed by class id. */\n get labels(): readonly string[] {\n return this._labels;\n }\n\n /** Class id → class name dict (matches Ultralytics' `model.names`). */\n get names(): Readonly<Record<number, string>> {\n return this._names;\n }\n\n /**\n * The `[width, height]` this task preprocesses to.\n *\n * Resolved at creation time from the model's graph when it declares a static\n * input, so reading it back tells you the resolution inference really runs at\n * — not merely what was requested.\n */\n get inputSize(): readonly [number, number] {\n return this._inputSize;\n }\n\n /** Number of classes the model can predict. */\n get numClasses(): number {\n return this._labels.length;\n }\n\n /** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */\n async call(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n return this.predict(image, options);\n }\n\n /** Run classification on a single image. */\n async predict(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n const timer = new SpeedTimer();\n const path = typeof image === \"string\" ? image : null;\n const original = await loadImage(image);\n timer.stage(\"load\");\n const tensor = this._preprocess(original);\n timer.stage(\"preprocess\");\n const outputs = await this._session.run({ [this._session.inputName]: tensor });\n timer.stage(\"inference\");\n const firstOutputName = this._session.outputNames[0];\n if (firstOutputName === undefined) {\n throw new Error(\"Classifier model has no outputs.\");\n }\n const raw = outputs[firstOutputName];\n if (raw === undefined) {\n throw new Error(\n `Classifier model output ${firstOutputName} missing from run() result.`,\n );\n }\n const fullProbs = this._postprocess(raw.data as Float32Array);\n\n const { indices, values } = topK(fullProbs, options.topK ?? null);\n const probabilities: ClassProbability[] = [];\n for (let i = 0; i < indices.length; i++) {\n const id = indices[i] as number;\n const className = this._labels[id] ?? `class_${id}`;\n probabilities.push({\n classId: id,\n className,\n probability: values[i] as number,\n cls: id,\n name: className,\n conf: values[i] as number,\n });\n }\n if (probabilities.length === 0) {\n throw new Error(\"Classifier produced no probabilities (empty output).\");\n }\n\n const top = probabilities[0] as ClassProbability;\n const result: ClassificationResult = {\n classId: top.classId,\n className: top.className,\n confidence: top.probability,\n cls: top.classId,\n name: top.className,\n conf: top.probability,\n image: original,\n probabilities,\n };\n\n const orig: readonly [number, number] = [original.height, original.width];\n const probs = new Probs(fullProbs);\n timer.stage(\"postprocess\");\n return [\n new ClassificationResults(\n probs,\n result,\n this._names,\n original,\n orig,\n path,\n timer.speed(),\n ),\n ];\n }\n\n private _preprocess(image: RGBImage): ort.Tensor {\n const [tw, th] = this._inputSize;\n const resized = resize(image, tw, th);\n const normalized = normalize(resized, this._mean, this._std);\n const chw = toCHW(normalized, resized.width, resized.height, 3);\n return toFloat32Tensor(chw, [1, 3, resized.height, resized.width]);\n }\n\n private _postprocess(raw: Float32Array): Float32Array {\n return this._applySoftmax ? softmax(raw) : new Float32Array(raw);\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"classifier.js","names":[],"sources":["../../../src/vision/tasks/classifier.ts"],"sourcesContent":["/**\n * Image classification task using ONNX Runtime Web.\n */\n\nimport type * as ort from \"onnxruntime-web\";\n\nimport { type ModelSource, type OrtSessionOptions, OrtSession } from \"../core/session\";\nimport { SpeedTimer } from \"../core/timing\";\nimport { type ImageInput, loadImage } from \"../io/image\";\nimport { classificationNumClasses, resolveInputSize } from \"../core/graph\";\nimport { modelNames } from \"../core/metadata\";\nimport { type LabelSpec, resolveLabels } from \"../labels\";\nimport { softmax, topK } from \"../postprocess/classification\";\nimport { normalize, resize, toCHW, toFloat32Tensor } from \"../preprocess/image\";\nimport { ClassificationResults, Probs } from \"../results\";\nimport { VisionTask } from \"./base\";\nimport { type ClassProbability, type ClassificationResult, type RGBImage } from \"../types\";\n\nconst IMAGENET_MEAN: readonly [number, number, number] = [0.485, 0.456, 0.406];\nconst IMAGENET_STD: readonly [number, number, number] = [0.229, 0.224, 0.225];\n\nexport interface ClassifierOptions extends OrtSessionOptions {\n /**\n * Class label spec — see {@link resolveLabels}.\n *\n * Optional: when omitted, the names the export baked into the model are used\n * (Ultralytics writes them as `names` in the metadata map). Only when the\n * model carries none does this fall back to generated `class_<id>` labels.\n * Passing a spec always wins, for a model whose names are wrong or absent.\n */\n readonly labels?: LabelSpec;\n /**\n * Number of classes the model can predict.\n *\n * Optional: inferred from the classification head's declared output shape\n * `(B, nc)`. Pass it to validate that the supplied labels match the model.\n */\n readonly numClasses?: number;\n /**\n * Model input `[width, height]` in pixels.\n *\n * Only used when the model's graph leaves its spatial axes dynamic: a graph\n * that declares a static size always wins, since that is the only shape ONNX\n * Runtime will accept. Defaults to `[224, 224]`.\n */\n readonly inputSize?: readonly [number, number];\n /** Per-channel RGB mean used for normalization. Defaults to ImageNet. */\n readonly mean?: readonly [number, number, number];\n /** Per-channel RGB standard deviation. Defaults to ImageNet. */\n readonly std?: readonly [number, number, number];\n /**\n * If `true` (default), apply softmax to the raw model output. Set to\n * `false` for models whose final layer already produces a probability\n * distribution.\n */\n readonly applySoftmax?: boolean;\n}\n\nexport interface ClassifierPredictOptions {\n /**\n * If set, the per-class probability list in `results[0].result.probabilities`\n * is truncated to the top-K entries. The bulk `probs` view always exposes\n * the full vector.\n */\n readonly topK?: number;\n}\n\n/**\n * Image classifier wrapping an ONNX model with ImageNet-style preprocessing.\n *\n * `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a\n * single image), mirroring Ultralytics' API. The envelope exposes a `probs`\n * collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the\n * legacy per-class probability list with names already resolved.\n *\n * Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,\n * NCHW layout, batch size 1, softmax applied to the raw output.\n *\n * @example\n * ```typescript\n * const clf = await Classifier.create(\"/models/resnet50.onnx\", {\n * labels: [\"tench\", \"goldfish\", ...] // 1000 ImageNet labels\n * });\n * const r = (await clf.predict(\"/images/dog.jpg\"))[0];\n * console.log(r.cls, r.conf, r.name);\n * console.log(r.probs.top5, r.probs.top5conf);\n * ```\n */\nexport class Classifier extends VisionTask {\n private constructor(\n session: OrtSession,\n private readonly _labels: readonly string[],\n private readonly _names: Readonly<Record<number, string>>,\n private readonly _inputSize: readonly [number, number],\n private readonly _mean: readonly [number, number, number],\n private readonly _std: readonly [number, number, number],\n private readonly _applySoftmax: boolean,\n ) {\n super(session);\n }\n\n /** Load the model and resolve labels. */\n static async create(model: ModelSource, options: ClassifierOptions = {}): Promise<Classifier> {\n const session = await OrtSession.create(model, options);\n const numClasses =\n options.numClasses ?? classificationNumClasses(session.outputShape) ?? undefined;\n const labels = resolveLabels(options.labels ?? modelNames(session.metadata), {\n numClasses,\n });\n const names: Record<number, string> = {};\n for (let i = 0; i < labels.length; i++) {\n names[i] = labels[i] as string;\n }\n return new Classifier(\n session,\n labels,\n names,\n resolveInputSize({\n graphShape: session.inputShape,\n requested: options.inputSize,\n fallback: [224, 224],\n }),\n options.mean ?? IMAGENET_MEAN,\n options.std ?? IMAGENET_STD,\n options.applySoftmax ?? true,\n );\n }\n\n /** Class labels indexed by class id. */\n get labels(): readonly string[] {\n return this._labels;\n }\n\n /** Class id → class name dict (matches Ultralytics' `model.names`). */\n get names(): Readonly<Record<number, string>> {\n return this._names;\n }\n\n /**\n * The `[width, height]` this task preprocesses to.\n *\n * Resolved at creation time from the model's graph when it declares a static\n * input, so reading it back tells you the resolution inference really runs at\n * — not merely what was requested.\n */\n get inputSize(): readonly [number, number] {\n return this._inputSize;\n }\n\n /** Number of classes the model can predict. */\n get numClasses(): number {\n return this._labels.length;\n }\n\n /** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */\n async call(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n return this.predict(image, options);\n }\n\n /** Run classification on a single image. */\n async predict(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n const timer = new SpeedTimer();\n const path = typeof image === \"string\" ? image : null;\n const original = await loadImage(image);\n timer.stage(\"load\");\n const tensor = this._preprocess(original);\n timer.stage(\"preprocess\");\n const outputs = await this._session.run({ [this._session.inputName]: tensor });\n timer.stage(\"inference\");\n const firstOutputName = this._session.outputNames[0];\n if (firstOutputName === undefined) {\n throw new Error(\"Classifier model has no outputs.\");\n }\n const raw = outputs[firstOutputName];\n if (raw === undefined) {\n throw new Error(\n `Classifier model output ${firstOutputName} missing from run() result.`,\n );\n }\n const fullProbs = this._postprocess(raw.data as Float32Array);\n\n const { indices, values } = topK(fullProbs, options.topK ?? null);\n const probabilities: ClassProbability[] = [];\n for (let i = 0; i < indices.length; i++) {\n const id = indices[i] as number;\n const className = this._labels[id] ?? `class_${id}`;\n probabilities.push({\n classId: id,\n className,\n probability: values[i] as number,\n cls: id,\n name: className,\n conf: values[i] as number,\n });\n }\n if (probabilities.length === 0) {\n throw new Error(\"Classifier produced no probabilities (empty output).\");\n }\n\n const top = probabilities[0] as ClassProbability;\n const result: ClassificationResult = {\n classId: top.classId,\n className: top.className,\n confidence: top.probability,\n cls: top.classId,\n name: top.className,\n conf: top.probability,\n image: original,\n probabilities,\n };\n\n const orig: readonly [number, number] = [original.height, original.width];\n const probs = new Probs(fullProbs);\n timer.stage(\"postprocess\");\n return [\n new ClassificationResults(\n probs,\n result,\n this._names,\n original,\n orig,\n path,\n timer.speed(),\n ),\n ];\n }\n\n private _preprocess(image: RGBImage): ort.Tensor {\n const [tw, th] = this._inputSize;\n const resized = resize(image, tw, th);\n const normalized = normalize(resized, this._mean, this._std);\n const chw = toCHW(normalized, resized.width, resized.height, 3);\n return toFloat32Tensor(chw, [1, 3, resized.height, resized.width]);\n }\n\n private _postprocess(raw: Float32Array): Float32Array {\n return this._applySoftmax ? softmax(raw) : new Float32Array(raw);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"classifier.js","names":[],"sources":["../../../src/vision/tasks/classifier.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image classification task using ONNX Runtime Web.\n */\n\nimport type * as ort from \"onnxruntime-web\";\n\nimport { type ModelSource, type OrtSessionOptions, OrtSession } from \"../core/session\";\nimport { SpeedTimer } from \"../core/timing\";\nimport { type ImageInput, loadImage } from \"../io/image\";\nimport { classificationNumClasses, resolveInputSize } from \"../core/graph\";\nimport { modelNames } from \"../core/metadata\";\nimport { type LabelSpec, resolveLabels } from \"../labels\";\nimport { softmax, topK } from \"../postprocess/classification\";\nimport { normalize, resize, toCHW, toFloat32Tensor } from \"../preprocess/image\";\nimport { ClassificationResults, Probs } from \"../results\";\nimport { VisionTask } from \"./base\";\nimport { type ClassProbability, type ClassificationResult, type RGBImage } from \"../types\";\n\nconst IMAGENET_MEAN: readonly [number, number, number] = [0.485, 0.456, 0.406];\nconst IMAGENET_STD: readonly [number, number, number] = [0.229, 0.224, 0.225];\n\nexport interface ClassifierOptions extends OrtSessionOptions {\n /**\n * Class label spec — see {@link resolveLabels}.\n *\n * Optional: when omitted, the names the export baked into the model are used\n * (Ultralytics writes them as `names` in the metadata map). Only when the\n * model carries none does this fall back to generated `class_<id>` labels.\n * Passing a spec always wins, for a model whose names are wrong or absent.\n */\n readonly labels?: LabelSpec;\n /**\n * Number of classes the model can predict.\n *\n * Optional: inferred from the classification head's declared output shape\n * `(B, nc)`. Pass it to validate that the supplied labels match the model.\n */\n readonly numClasses?: number;\n /**\n * Model input `[width, height]` in pixels.\n *\n * Only used when the model's graph leaves its spatial axes dynamic: a graph\n * that declares a static size always wins, since that is the only shape ONNX\n * Runtime will accept. Defaults to `[224, 224]`.\n */\n readonly inputSize?: readonly [number, number];\n /** Per-channel RGB mean used for normalization. Defaults to ImageNet. */\n readonly mean?: readonly [number, number, number];\n /** Per-channel RGB standard deviation. Defaults to ImageNet. */\n readonly std?: readonly [number, number, number];\n /**\n * If `true` (default), apply softmax to the raw model output. Set to\n * `false` for models whose final layer already produces a probability\n * distribution.\n */\n readonly applySoftmax?: boolean;\n}\n\nexport interface ClassifierPredictOptions {\n /**\n * If set, the per-class probability list in `results[0].result.probabilities`\n * is truncated to the top-K entries. The bulk `probs` view always exposes\n * the full vector.\n */\n readonly topK?: number;\n}\n\n/**\n * Image classifier wrapping an ONNX model with ImageNet-style preprocessing.\n *\n * `predict()` returns `Promise<ClassificationResults[]>` (length 1 for a\n * single image), mirroring Ultralytics' API. The envelope exposes a `probs`\n * collection (`top1`, `top1conf`, `top5`, `top5conf`, `data`) plus the\n * legacy per-class probability list with names already resolved.\n *\n * Defaults: 224×224 RGB input, `float32` normalized with ImageNet mean/std,\n * NCHW layout, batch size 1, softmax applied to the raw output.\n *\n * @example\n * ```typescript\n * const clf = await Classifier.create(\"/models/resnet50.onnx\", {\n * labels: [\"tench\", \"goldfish\", ...] // 1000 ImageNet labels\n * });\n * const r = (await clf.predict(\"/images/dog.jpg\"))[0];\n * console.log(r.cls, r.conf, r.name);\n * console.log(r.probs.top5, r.probs.top5conf);\n * ```\n */\nexport class Classifier extends VisionTask {\n private constructor(\n session: OrtSession,\n private readonly _labels: readonly string[],\n private readonly _names: Readonly<Record<number, string>>,\n private readonly _inputSize: readonly [number, number],\n private readonly _mean: readonly [number, number, number],\n private readonly _std: readonly [number, number, number],\n private readonly _applySoftmax: boolean,\n ) {\n super(session);\n }\n\n /** Load the model and resolve labels. */\n static async create(model: ModelSource, options: ClassifierOptions = {}): Promise<Classifier> {\n const session = await OrtSession.create(model, options);\n const numClasses =\n options.numClasses ?? classificationNumClasses(session.outputShape) ?? undefined;\n const labels = resolveLabels(options.labels ?? modelNames(session.metadata), {\n numClasses,\n });\n const names: Record<number, string> = {};\n for (let i = 0; i < labels.length; i++) {\n names[i] = labels[i] as string;\n }\n return new Classifier(\n session,\n labels,\n names,\n resolveInputSize({\n graphShape: session.inputShape,\n requested: options.inputSize,\n fallback: [224, 224],\n }),\n options.mean ?? IMAGENET_MEAN,\n options.std ?? IMAGENET_STD,\n options.applySoftmax ?? true,\n );\n }\n\n /** Class labels indexed by class id. */\n get labels(): readonly string[] {\n return this._labels;\n }\n\n /** Class id → class name dict (matches Ultralytics' `model.names`). */\n get names(): Readonly<Record<number, string>> {\n return this._names;\n }\n\n /**\n * The `[width, height]` this task preprocesses to.\n *\n * Resolved at creation time from the model's graph when it declares a static\n * input, so reading it back tells you the resolution inference really runs at\n * — not merely what was requested.\n */\n get inputSize(): readonly [number, number] {\n return this._inputSize;\n }\n\n /** Number of classes the model can predict. */\n get numClasses(): number {\n return this._labels.length;\n }\n\n /** Alias for {@link predict} (parity with PyTorch `nn.Module.__call__`). */\n async call(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n return this.predict(image, options);\n }\n\n /** Run classification on a single image. */\n async predict(\n image: ImageInput,\n options: ClassifierPredictOptions = {},\n ): Promise<ClassificationResults[]> {\n const timer = new SpeedTimer();\n const path = typeof image === \"string\" ? image : null;\n const original = await loadImage(image);\n timer.stage(\"load\");\n const tensor = this._preprocess(original);\n timer.stage(\"preprocess\");\n const outputs = await this._session.run({ [this._session.inputName]: tensor });\n timer.stage(\"inference\");\n const firstOutputName = this._session.outputNames[0];\n if (firstOutputName === undefined) {\n throw new Error(\"Classifier model has no outputs.\");\n }\n const raw = outputs[firstOutputName];\n if (raw === undefined) {\n throw new Error(\n `Classifier model output ${firstOutputName} missing from run() result.`,\n );\n }\n const fullProbs = this._postprocess(raw.data as Float32Array);\n\n const { indices, values } = topK(fullProbs, options.topK ?? null);\n const probabilities: ClassProbability[] = [];\n for (let i = 0; i < indices.length; i++) {\n const id = indices[i] as number;\n const className = this._labels[id] ?? `class_${id}`;\n probabilities.push({\n classId: id,\n className,\n probability: values[i] as number,\n cls: id,\n name: className,\n conf: values[i] as number,\n });\n }\n if (probabilities.length === 0) {\n throw new Error(\"Classifier produced no probabilities (empty output).\");\n }\n\n const top = probabilities[0] as ClassProbability;\n const result: ClassificationResult = {\n classId: top.classId,\n className: top.className,\n confidence: top.probability,\n cls: top.classId,\n name: top.className,\n conf: top.probability,\n image: original,\n probabilities,\n };\n\n const orig: readonly [number, number] = [original.height, original.width];\n const probs = new Probs(fullProbs);\n timer.stage(\"postprocess\");\n return [\n new ClassificationResults(\n probs,\n result,\n this._names,\n original,\n orig,\n path,\n timer.speed(),\n ),\n ];\n }\n\n private _preprocess(image: RGBImage): ort.Tensor {\n const [tw, th] = this._inputSize;\n const resized = resize(image, tw, th);\n const normalized = normalize(resized, this._mean, this._std);\n const chw = toCHW(normalized, resized.width, resized.height, 3);\n return toFloat32Tensor(chw, [1, 3, resized.height, resized.width]);\n }\n\n private _postprocess(raw: Float32Array): Float32Array {\n return this._applySoftmax ? softmax(raw) : new Float32Array(raw);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/timing.cjs"),r=require("../results.cjs"),i=require("../labels.cjs"),a=require("../core/session.cjs"),o=require("../io/image.cjs"),s=require("../fusion.cjs"),c=require("../preprocess/image.cjs"),l=require("../preprocess/pipeline.cjs"),u=require("../postprocess/classification.cjs"),d=require("./base.cjs");var f=class f extends d.VisionTask{_spec;_labels;_names;_classifierLabels;_classifierNames;_raiseOnEmpty;constructor(e,t,n,r,i,a,o){super(e),this._spec=t,this._labels=n,this._names=r,this._classifierLabels=i,this._classifierNames=a,this._raiseOnEmpty=o}_pipelineCache=null;async warmup(e=1){let[t,n]=this._spec.inputSize;for(let r=0;r<e;r++){let e={[s.INPUT_IMAGE]:c.toFloat32Tensor(l.zeroTensorData(t,n),[1,3,n,t])};this._spec.needsSourceImage&&(e[s.INPUT_SOURCE]=c.toFloat32Tensor(l.zeroTensorData(t,n),[1,3,n,t]),e[s.INPUT_SCALE]=c.toFloat32Tensor(new Float32Array([1]),[1]),e[s.INPUT_PAD]=c.toFloat32Tensor(new Float32Array([0,0]),[2])),await this._session.run(e)}}get _pipeline(){if(this._pipelineCache===null){let[e,t]=this._spec.inputSize;this._pipelineCache=new l.LetterboxPipeline(e,t)}return this._pipelineCache}static async create(t,n={}){let r=await a.OrtSession.create(t,n),o=s.readFusionSpec(r.metadata);if(o===null)throw new e.FusionError(`This model carries no fused-pipeline metadata, so DetectClassify cannot tell how to drive it. Build one with ort_vision_sdk.compose.fuse_detect_classify, or load a plain model with Detector/Classifier instead.`);let c=i.resolveLabels(n.labels??o.detectorNames??`coco`),l=i.resolveLabels(n.classifierLabels??o.classifierNames,{numClasses:p(r)??void 0});return new f(r,o,c,m(c),l,m(l),n.raiseOnEmpty??!1)}get spec(){return this._spec}get inputSize(){return this._spec.inputSize}get labels(){return this._labels}get names(){return this._names}get classifierLabels(){return this._classifierLabels}get classifierNames(){return this._classifierNames}async call(e,t={}){return this.predict(e,t)}async predict(e,t={}){let i=new n.SpeedTimer,a=typeof e==`string`?e:null,c=await o.loadImage(e);i.stage(`load`);let{feeds:l,scale:u,padLeft:f,padTop:p}=this._preprocess(c);i.stage(`preprocess`);let m=await this._session.run(l);this._pipeline.release(),i.stage(`inference`);let v=h(m,s.OUTPUT_PROBS),S=g(m,s.OUTPUT_BOXES),C=g(m,s.OUTPUT_SCORES),w=_(m,s.OUTPUT_CLASSES),T=v.data,E=_(m,`num_detections`)[0]??0,D=Math.min(E,Math.floor(S.length/4)),O=v.dims[v.dims.length-1]??0,k=t.classes===void 0?null:new Set(t.classes),A=t.confThreshold??0,j=[];for(let e=0;e<D;e++){let n=w[e]??0,r=C[e]??0;if(r<A||k!==null&&!k.has(n))continue;let i=this._toOriginal(S,e,{scale:u,padLeft:f,padTop:p,original:c}),a=y(c,i);j.push(b(n,this._names[n]??`class_${n}`,r,i,a,this._classify(T.subarray(e*O,(e+1)*O),a,t.topK)))}d.requireDetections(j.length,{raiseOnEmpty:t.raiseOnEmpty??this._raiseOnEmpty,confThreshold:Math.max(A,this._spec.confThreshold),classes:t.classes,path:a});let M=[c.height,c.width];return i.stage(`postprocess`),[new r.DetectClassifyResults(x(j,M),j,this._names,this._classifierNames,c,M,a,i.speed())]}_preprocess(e){let[t,n]=this._spec.inputSize,r=this._pipeline.run(e),i={[s.INPUT_IMAGE]:c.toFloat32Tensor(r.data,[1,3,n,t])};return this._spec.needsSourceImage&&(i[s.INPUT_SOURCE]=v(e),i[s.INPUT_SCALE]=c.toFloat32Tensor(new Float32Array([r.scale]),[1]),i[s.INPUT_PAD]=c.toFloat32Tensor(new Float32Array([r.padLeft,r.padTop]),[2])),{feeds:i,scale:r.scale,padLeft:r.padLeft,padTop:r.padTop}}_toOriginal(e,n,r){let{scale:i,padLeft:a,padTop:o,original:s}=r,c=t=>e[n*4+t]??0,l=e=>Math.min(Math.max(e,0),s.width),u=e=>Math.min(Math.max(e,0),s.height);return new t.BoundingBox(l((c(0)-a)/i),u((c(1)-o)/i),l((c(2)-a)/i),u((c(3)-o)/i))}_classify(e,t,n){let{indices:r,values:i}=u.topK(this._spec.applySoftmax?u.softmax(e):e,n??null),a=[];for(let e=0;e<r.length;e++){let t=r[e]??0,n=i[e]??0,o=this._classifierLabels[t]??`class_${t}`;a.push({classId:t,className:o,probability:n,cls:t,name:o,conf:n})}let o=a[0]??{classId:0,className:`class_0`,probability:0,cls:0,name:`class_0`,conf:0};return{classId:o.classId,className:o.className,confidence:o.probability,cls:o.classId,name:o.className,conf:o.probability,image:t,probabilities:a}}};function p(e){let t=e.outputNames.indexOf(s.OUTPUT_PROBS);if(t<0)return null;let n=e.outputShapes[t];return n===void 0||n.length===0?null:n[n.length-1]??null}function m(e){let t={};for(let n=0;n<e.length;n++)t[n]=e[n];return t}function h(t,n){let r=t[n];if(r===void 0)throw new e.FusionError(`The fused pipeline is missing its '${n}' output.`);return r}function g(e,t){return h(e,t).data}function _(e,t){let n=h(e,t).data,r=[];for(let e=0;e<n.length;e++)r.push(Number(n[e]));return r}function v(e){return c.toFloat32Tensor(c.toCHW(c.toFloat32(e),e.width,e.height,3),[1,3,e.height,e.width])}function y(e,n){let[r,i,a,o]=n.asIntXyxy(),s=Math.max(0,r),c=Math.max(0,i),l=Math.min(e.width,a),u=Math.min(e.height,o);if(l<=s||u<=c)return new t.RGBImage(new Uint8Array,0,0);let d=l-s,f=u-c,p=new Uint8Array(d*f*3);for(let t=0;t<f;t++){let n=((c+t)*e.width+s)*3;p.set(e.data.subarray(n,n+d*3),t*d*3)}return new t.RGBImage(p,d,f)}function b(e,t,n,r,i,a){return{classId:e,className:t,confidence:n,bbox:r,cls:e,name:t,conf:n,box:r,croppedImage:i,classification:a}}function x(e,t){let n=new Float32Array(e.length*4),i=new Int32Array(e.length),a=new Float32Array(e.length);return e.forEach((e,t)=>{let[r,o,s,c]=e.bbox.xyxy;n[t*4]=r,n[t*4+1]=o,n[t*4+2]=s,n[t*4+3]=c,i[t]=e.classId,a[t]=e.confidence}),new r.Boxes(n,i,a,t)}exports.DetectClassify=f;
2
+ //# sourceMappingURL=detectClassify.cjs.map