tempest-react-sdk 0.39.0 → 0.39.1
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.
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/access/access-control-context.cjs.map +1 -1
- package/dist/access/use-can.cjs.map +1 -1
- package/dist/app/AppProviders.cjs.map +1 -1
- package/dist/app/AppProviders.js.map +1 -1
- package/dist/audio/use-audio-recorder.cjs.map +1 -1
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-microphone.cjs.map +1 -1
- package/dist/auth/create-auth-store.cjs.map +1 -1
- package/dist/auth/lazy-with-retry.cjs.map +1 -1
- package/dist/auth/use-passkey.cjs.map +1 -1
- package/dist/br/BrazilMap.cjs +1 -1
- package/dist/br/BrazilMap.cjs.map +1 -1
- package/dist/br/BrazilMap.js +2 -2
- package/dist/br/BrazilMap.js.map +1 -1
- package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
- package/dist/br/BrazilStateCitySelect.js.map +1 -1
- package/dist/br/BrazilStateMap.cjs +1 -1
- package/dist/br/BrazilStateMap.cjs.map +1 -1
- package/dist/br/BrazilStateMap.js +2 -2
- package/dist/br/BrazilStateMap.js.map +1 -1
- package/dist/br/MapLegend.cjs.map +1 -1
- package/dist/br/MapLegend.js.map +1 -1
- package/dist/br/MapMarkers.cjs.map +1 -1
- package/dist/br/MapMarkers.js.map +1 -1
- package/dist/br/MunicipalitySearch.cjs.map +1 -1
- package/dist/br/MunicipalitySearch.js.map +1 -1
- package/dist/br/PixQRCode.cjs.map +1 -1
- package/dist/br/PixQRCode.js.map +1 -1
- package/dist/br/use-map-hover.cjs.map +1 -1
- package/dist/br/use-map-zoom.cjs.map +1 -1
- package/dist/capture/media-recorder.cjs +1 -1
- package/dist/capture/media-recorder.js +2 -2
- package/dist/capture/use-barcode-scanner.cjs +1 -1
- package/dist/capture/use-barcode-scanner.cjs.map +1 -1
- package/dist/capture/use-barcode-scanner.js +2 -2
- package/dist/capture/use-barcode-scanner.js.map +1 -1
- package/dist/capture/use-screen-capture.cjs.map +1 -1
- package/dist/capture/use-speech-recognition.cjs.map +1 -1
- package/dist/capture/use-torch.cjs.map +1 -1
- package/dist/capture/use-video-recorder.cjs.map +1 -1
- package/dist/charts/AreaChart.cjs.map +1 -1
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.cjs.map +1 -1
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/LineChart.cjs.map +1 -1
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/PieChart.cjs.map +1 -1
- package/dist/charts/PieChart.js.map +1 -1
- package/dist/charts/RadarChart.cjs.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/use-chart-colors.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.js.map +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
- package/dist/components/AIChat/AIChatComposer.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/Accordion/Accordion.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/Alert/Alert.cjs.map +1 -1
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/AppBar/AppBar.cjs.map +1 -1
- package/dist/components/AppBar/AppBar.js.map +1 -1
- package/dist/components/AppShell/AppShell.cjs.map +1 -1
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/dist/components/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
- package/dist/components/Badge/Badge.cjs.map +1 -1
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Banner/Banner.cjs.map +1 -1
- package/dist/components/Banner/Banner.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Calendar/Calendar.cjs +1 -1
- package/dist/components/Calendar/Calendar.cjs.map +1 -1
- package/dist/components/Calendar/Calendar.js +38 -41
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Card/Card.cjs.map +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Carousel/Carousel.cjs.map +1 -1
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Chat/Chat.cjs.map +1 -1
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/Chat/ChatComposer.cjs.map +1 -1
- package/dist/components/Chat/ChatComposer.js.map +1 -1
- package/dist/components/Chat/chat-groups.cjs +1 -1
- package/dist/components/Chat/chat-groups.cjs.map +1 -1
- package/dist/components/Chat/chat-groups.js +2 -2
- package/dist/components/Chat/chat-groups.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
- package/dist/components/ChipInput/ChipInput.js.map +1 -1
- package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Command/Command.cjs.map +1 -1
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
- package/dist/components/CopyButton/CopyButton.js.map +1 -1
- package/dist/components/DataList/DataList.cjs.map +1 -1
- package/dist/components/DataList/DataList.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +2 -2
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/EditableCell.cjs.map +1 -1
- package/dist/components/DataTable/EditableCell.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
- package/dist/components/Divider/Divider.cjs.map +1 -1
- package/dist/components/Divider/Divider.js.map +1 -1
- package/dist/components/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
- package/dist/components/Dropzone/Dropzone.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/FileUpload/FileUpload.cjs +1 -1
- package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
- package/dist/components/FileUpload/FileUpload.js +1 -1
- package/dist/components/FileUpload/FileUpload.js.map +1 -1
- package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar/FilterBar.js.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
- package/dist/components/Form/Form.cjs.map +1 -1
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/Image/Image.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.js +1 -1
- package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
- package/dist/components/Input/Input.cjs.map +1 -1
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.js.map +1 -1
- package/dist/components/Kanban/Kanban.cjs.map +1 -1
- package/dist/components/Kanban/Kanban.js.map +1 -1
- package/dist/components/Label/Label.cjs.map +1 -1
- package/dist/components/Label/Label.js.map +1 -1
- package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
- package/dist/components/Lightbox/Lightbox.js.map +1 -1
- package/dist/components/ListTile/ListTile.cjs.map +1 -1
- package/dist/components/ListTile/ListTile.js.map +1 -1
- package/dist/components/Markdown/Markdown.cjs +1 -1
- package/dist/components/Markdown/Markdown.cjs.map +1 -1
- package/dist/components/Markdown/Markdown.js +2 -2
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Masonry/Masonry.cjs.map +1 -1
- package/dist/components/Masonry/Masonry.js.map +1 -1
- package/dist/components/Menubar/Menubar.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.js.map +1 -1
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
- package/dist/components/Money/Money.cjs.map +1 -1
- package/dist/components/Money/Money.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/components/NProgress/NProgress.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
- package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
- package/dist/components/Page/Page.cjs.map +1 -1
- package/dist/components/Page/Page.js.map +1 -1
- package/dist/components/Pagination/Pagination.cjs.map +1 -1
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
- package/dist/components/PinInput/PinInput.cjs.map +1 -1
- package/dist/components/PinInput/PinInput.js.map +1 -1
- package/dist/components/Popover/Popover.cjs.map +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Portal/Portal.cjs.map +1 -1
- package/dist/components/Progress/Progress.cjs.map +1 -1
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/QRCode/QRCode.cjs.map +1 -1
- package/dist/components/QRCode/QRCode.js.map +1 -1
- package/dist/components/Radio/Radio.cjs.map +1 -1
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
- package/dist/components/RatingStars/RatingStars.js.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
- package/dist/components/Resizable/Resizable.cjs.map +1 -1
- package/dist/components/Resizable/Resizable.js.map +1 -1
- package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
- package/dist/components/Scheduler/Scheduler.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
- package/dist/components/Slider/Slider.cjs.map +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/Spinner/Spinner.cjs.map +1 -1
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/Stat/Stat.cjs.map +1 -1
- package/dist/components/Stat/Stat.js.map +1 -1
- package/dist/components/Stepper/Stepper.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.js.map +1 -1
- package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
- package/dist/components/StepperInput/StepperInput.js.map +1 -1
- package/dist/components/Switch/Switch.cjs.map +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
- package/dist/components/Table/Table.cjs.map +1 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Tabs/Tabs.cjs.map +1 -1
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tag/Tag.cjs.map +1 -1
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Textarea/Textarea.cjs.map +1 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/Timeline/Timeline.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.js.map +1 -1
- package/dist/components/Toast/ToastProvider.cjs.map +1 -1
- package/dist/components/Toast/ToastProvider.js.map +1 -1
- package/dist/components/Toggle/Toggle.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tour/Tour.cjs.map +1 -1
- package/dist/components/Tour/Tour.js.map +1 -1
- package/dist/components/Transfer/Transfer.cjs.map +1 -1
- package/dist/components/Transfer/Transfer.js.map +1 -1
- package/dist/components/TreeView/TreeView.cjs +1 -1
- package/dist/components/TreeView/TreeView.cjs.map +1 -1
- package/dist/components/TreeView/TreeView.js +1 -4
- package/dist/components/TreeView/TreeView.js.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
- package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
- package/dist/components/VirtualList/VirtualList.js.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.js.map +1 -1
- package/dist/data/data-provider-context.cjs.map +1 -1
- package/dist/data/use-resource.cjs.map +1 -1
- package/dist/editor/RichTextEditor.cjs.map +1 -1
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/error-boundary/use-error-handler.cjs.map +1 -1
- package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
- package/dist/forms/FormField.cjs.map +1 -1
- package/dist/forms/masked-inputs.cjs.map +1 -1
- package/dist/forms/use-viacep.cjs.map +1 -1
- package/dist/forms/use-zod-form.cjs.map +1 -1
- package/dist/geo/TrajectoryMap.cjs.map +1 -1
- package/dist/geo/TrajectoryMap.js.map +1 -1
- package/dist/geo/leaflet-map.cjs.map +1 -1
- package/dist/geo/leaflet-map.js.map +1 -1
- package/dist/geo/use-position-tracker.cjs.map +1 -1
- package/dist/hooks/use-announce.cjs.map +1 -1
- package/dist/hooks/use-async.cjs.map +1 -1
- package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-breakpoint.cjs.map +1 -1
- package/dist/hooks/use-click-outside.cjs.map +1 -1
- package/dist/hooks/use-client-filter.cjs.map +1 -1
- package/dist/hooks/use-clipboard.cjs.map +1 -1
- package/dist/hooks/use-counter.cjs.map +1 -1
- package/dist/hooks/use-debounce.cjs.map +1 -1
- package/dist/hooks/use-deep-memo.cjs.map +1 -1
- package/dist/hooks/use-disclosure.cjs.map +1 -1
- package/dist/hooks/use-document-visibility.cjs.map +1 -1
- package/dist/hooks/use-event-listener.cjs.map +1 -1
- package/dist/hooks/use-geolocation.cjs.map +1 -1
- package/dist/hooks/use-hover.cjs.map +1 -1
- package/dist/hooks/use-idle.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.cjs +1 -1
- package/dist/hooks/use-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.js +1 -1
- package/dist/hooks/use-install-prompt.js.map +1 -1
- package/dist/hooks/use-intersection-observer.cjs.map +1 -1
- package/dist/hooks/use-interval.cjs.map +1 -1
- package/dist/hooks/use-is-first-render.cjs.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.cjs +1 -1
- package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.js +1 -1
- package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
- package/dist/hooks/use-list-state.cjs.map +1 -1
- package/dist/hooks/use-local-storage.cjs.map +1 -1
- package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
- package/dist/hooks/use-long-press.cjs.map +1 -1
- package/dist/hooks/use-map.cjs.map +1 -1
- package/dist/hooks/use-media-devices.cjs.map +1 -1
- package/dist/hooks/use-media-permission.cjs.map +1 -1
- package/dist/hooks/use-media-query.cjs.map +1 -1
- package/dist/hooks/use-object-url.cjs.map +1 -1
- package/dist/hooks/use-online.cjs.map +1 -1
- package/dist/hooks/use-pagination.cjs.map +1 -1
- package/dist/hooks/use-previous.cjs.map +1 -1
- package/dist/hooks/use-queue.cjs.map +1 -1
- package/dist/hooks/use-resize-observer.cjs.map +1 -1
- package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
- package/dist/hooks/use-service-worker-update.cjs.map +1 -1
- package/dist/hooks/use-set.cjs.map +1 -1
- package/dist/hooks/use-sortable.cjs +1 -1
- package/dist/hooks/use-sortable.cjs.map +1 -1
- package/dist/hooks/use-sortable.js +0 -2
- package/dist/hooks/use-sortable.js.map +1 -1
- package/dist/hooks/use-stable-callback.cjs.map +1 -1
- package/dist/hooks/use-storage-estimate.cjs.map +1 -1
- package/dist/hooks/use-throttle.cjs.map +1 -1
- package/dist/hooks/use-timeout.cjs.map +1 -1
- package/dist/hooks/use-toggle.cjs.map +1 -1
- package/dist/hooks/use-window-size.cjs.map +1 -1
- package/dist/http/api-client.cjs +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js +7 -5
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/resumable-upload.cjs +1 -1
- package/dist/http/resumable-upload.cjs.map +1 -1
- package/dist/http/resumable-upload.js +1 -1
- package/dist/http/resumable-upload.js.map +1 -1
- package/dist/http/use-poll.cjs.map +1 -1
- package/dist/i18n/I18nProvider.cjs.map +1 -1
- package/dist/icons/Icon.cjs.map +1 -1
- package/dist/icons/IconProvider.cjs.map +1 -1
- package/dist/icons/icon-context.cjs.map +1 -1
- package/dist/icons/use-icon.cjs.map +1 -1
- package/dist/imaging/use-image-processing.cjs.map +1 -1
- package/dist/oauth/GoogleSignIn.cjs.map +1 -1
- package/dist/oauth/GoogleSignIn.js.map +1 -1
- package/dist/oauth/use-oauth-callback.cjs.map +1 -1
- package/dist/offline/use-offline-sync.cjs.map +1 -1
- package/dist/push/use-push-subscription.cjs.map +1 -1
- package/dist/query/QueryProvider.cjs.map +1 -1
- package/dist/query/constants.cjs +1 -1
- package/dist/query/constants.cjs.map +1 -1
- package/dist/query/constants.js +10 -10
- package/dist/query/constants.js.map +1 -1
- package/dist/query/create-query-keys.cjs +1 -1
- package/dist/query/create-query-keys.cjs.map +1 -1
- package/dist/query/create-query-keys.js +1 -1
- package/dist/query/create-query-keys.js.map +1 -1
- package/dist/query/offline-persistence.cjs.map +1 -1
- package/dist/query/use-cursor-query.cjs.map +1 -1
- package/dist/query/use-offline-mutation.cjs.map +1 -1
- package/dist/query/use-paginated-query.cjs.map +1 -1
- package/dist/router/AppRouter.cjs +1 -1
- package/dist/router/AppRouter.cjs.map +1 -1
- package/dist/router/AppRouter.js +7 -2
- package/dist/router/AppRouter.js.map +1 -1
- package/dist/sse/use-event-stream.cjs.map +1 -1
- package/dist/store/create-store.cjs.map +1 -1
- package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
- package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
- package/dist/theme/ThemeProvider.cjs.map +1 -1
- package/dist/theme/color.cjs +1 -1
- package/dist/theme/color.cjs.map +1 -1
- package/dist/theme/color.js +1 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/utils/cn.cjs +1 -1
- package/dist/utils/cn.cjs.map +1 -1
- package/dist/utils/cn.js +1 -1
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/objects.cjs +1 -1
- package/dist/utils/objects.cjs.map +1 -1
- package/dist/utils/objects.js +1 -1
- package/dist/utils/objects.js.map +1 -1
- package/dist/utils/xlsx.cjs +1 -1
- package/dist/utils/xlsx.cjs.map +1 -1
- package/dist/utils/xlsx.js +3 -3
- package/dist/utils/xlsx.js.map +1 -1
- package/dist/vision/core/exceptions.cjs.map +1 -1
- package/dist/vision/core/exceptions.js.map +1 -1
- package/dist/vision/core/metadata.cjs +1 -1
- package/dist/vision/core/metadata.cjs.map +1 -1
- package/dist/vision/core/metadata.js +1 -1
- package/dist/vision/core/metadata.js.map +1 -1
- package/dist/vision/io/image.cjs +1 -1
- package/dist/vision/io/image.cjs.map +1 -1
- package/dist/vision/io/image.js +4 -2
- package/dist/vision/io/image.js.map +1 -1
- package/dist/vision/preprocess/image.cjs +1 -1
- package/dist/vision/preprocess/image.cjs.map +1 -1
- package/dist/vision/preprocess/image.js +4 -2
- package/dist/vision/preprocess/image.js.map +1 -1
- package/dist/vision/tasks/base.cjs +1 -1
- package/dist/vision/tasks/base.cjs.map +1 -1
- package/dist/vision/tasks/base.js +3 -1
- package/dist/vision/tasks/base.js.map +1 -1
- package/dist/vision/tasks/classifier.cjs +1 -1
- package/dist/vision/tasks/classifier.cjs.map +1 -1
- package/dist/vision/tasks/classifier.js +2 -2
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detectClassify.cjs +1 -1
- package/dist/vision/tasks/detectClassify.cjs.map +1 -1
- package/dist/vision/tasks/detectClassify.js +16 -15
- package/dist/vision/tasks/detectClassify.js.map +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-live-luminance.cjs.map +1 -1
- package/dist/vite/create-vite-config.cjs +1 -1
- package/dist/vite/create-vite-config.cjs.map +1 -1
- package/dist/vite/create-vite-config.js +3 -3
- package/dist/vite/create-vite-config.js.map +1 -1
- package/dist/vite/tempest-icons.cjs.map +1 -1
- package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
- package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
- package/dist/ws/use-web-socket.cjs +1 -1
- package/dist/ws/use-web-socket.cjs.map +1 -1
- package/dist/ws/use-web-socket.js +5 -3
- package/dist/ws/use-web-socket.js.map +1 -1
- package/package.json +2 -2
- package/template/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"metadata.js","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"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"}
|
package/dist/vision/io/image.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(r){if(r instanceof t.RGBImage)return r;if(typeof ImageData<`u`&&r instanceof ImageData)return n.imageDataToRGB(r);if(typeof r==`string`)return i(r);if(typeof Blob<`u`&&r instanceof Blob)return a(r);if(typeof HTMLImageElement<`u`&&r instanceof HTMLImageElement)return await o(r),s(r,r.naturalWidth,r.naturalHeight);if(typeof HTMLCanvasElement<`u`&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&r instanceof OffscreenCanvas||typeof ImageBitmap<`u`&&r instanceof ImageBitmap)return s(r,r.width,r.height);throw new e.ImageLoadError(`Unsupported image source type: ${Object.prototype.toString.call(r)}`)}async function i(t){let n;try{n=await fetch(t)}catch(n){throw new e.ImageLoadError(`Failed to fetch image from ${t}: ${n.message}`,{cause:n})}if(!n.ok)throw new e.ImageLoadError(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);return a(await n.blob())}async function a(t){let n;try{n=await createImageBitmap(t)}catch(t){throw new e.ImageLoadError(`Failed to decode image blob: ${t.message}`,{cause:t})}try{return s(n,n.width,n.height)}finally{n.close()}}function o(t){return t.complete&&t.naturalWidth>0?Promise.resolve():new Promise((n,r)=>{let i=()=>{o(),n()},a=()=>{o(),r(new e.ImageLoadError(`Failed to load HTMLImageElement (load event errored)`))},o=()=>{t.removeEventListener(`load`,i),t.removeEventListener(`error`,a)};t.addEventListener(`load`,i,{once:!0}),t.addEventListener(`error`,a,{once:!0})})}function s(t,r,i){if(r===0||i===0)throw new e.ImageLoadError(`Cannot load image with zero dimension (${r}x${i}).`);let a=n.
|
|
1
|
+
const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(r){if(r instanceof t.RGBImage)return r;if(typeof ImageData<`u`&&r instanceof ImageData)return n.imageDataToRGB(r);if(typeof r==`string`)return i(r);if(typeof Blob<`u`&&r instanceof Blob)return a(r);if(typeof HTMLImageElement<`u`&&r instanceof HTMLImageElement)return await o(r),s(r,r.naturalWidth,r.naturalHeight);if(typeof HTMLCanvasElement<`u`&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&r instanceof OffscreenCanvas||typeof ImageBitmap<`u`&&r instanceof ImageBitmap)return s(r,r.width,r.height);throw new e.ImageLoadError(`Unsupported image source type: ${Object.prototype.toString.call(r)}`)}async function i(t){let n;try{n=await fetch(t)}catch(n){throw new e.ImageLoadError(`Failed to fetch image from ${t}: ${n.message}`,{cause:n})}if(!n.ok)throw new e.ImageLoadError(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);return a(await n.blob())}async function a(t){let n;try{n=await createImageBitmap(t)}catch(t){throw new e.ImageLoadError(`Failed to decode image blob: ${t.message}`,{cause:t})}try{return s(n,n.width,n.height)}finally{n.close()}}function o(t){return t.complete&&t.naturalWidth>0?Promise.resolve():new Promise((n,r)=>{let i=()=>{o(),n()},a=()=>{o(),r(new e.ImageLoadError(`Failed to load HTMLImageElement (load event errored)`))},o=()=>{t.removeEventListener(`load`,i),t.removeEventListener(`error`,a)};t.addEventListener(`load`,i,{once:!0}),t.addEventListener(`error`,a,{once:!0})})}function s(t,r,i){if(r===0||i===0)throw new e.ImageLoadError(`Cannot load image with zero dimension (${r}x${i}).`);let a=n.createCanvas(r,i),o=n.get2DContext(a);o.drawImage(t,0,0);let s=o.getImageData(0,0,r,i);return n.imageDataToRGB(s)}exports.loadImage=r;
|
|
2
2
|
//# sourceMappingURL=image.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":"oGA6BA,eAAsB,EAAU,EAAuC,CACnE,GAAI,aAAkB,EAAA,SAClB,OAAO,EAGX,GAAI,OAAO,UAAc,KAAe,aAAkB,UACtD,OAAO,EAAA,eAAe,CAAM,EAGhC,GAAI,OAAO,GAAW,SAClB,OAAO,EAAY,CAAM,EAG7B,GAAI,OAAO,KAAS,KAAe,aAAkB,KACjD,OAAO,EAAa,CAAM,EAG9B,GAAI,OAAO,iBAAqB,KAAe,aAAkB,iBAE7D,OADA,MAAM,EAAoB,CAAM,EACzB,EAAc,EAAQ,EAAO,aAAc,EAAO,aAAa,EAW1E,GARI,OAAO,kBAAsB,KAAe,aAAkB,mBAI9D,OAAO,gBAAoB,KAAe,aAAkB,iBAI5D,OAAO,YAAgB,KAAe,aAAkB,YACxD,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,EAG5D,MAAM,IAAI,EAAA,eACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E,CACJ,CAEA,eAAe,EAAY,EAAgC,CACvD,IAAI,EACJ,GAAI,CACA,EAAW,MAAM,MAAM,CAAG,CAC9B,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,8BAA8B,EAAI,IAAK,EAAc,UAAW,CACrF,MAAO,CACX,CAAC,CACL,CACA,GAAI,CAAC,EAAS,GACV,MAAM,IAAI,EAAA,eACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E,EAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT,CAC5B,CAEA,eAAe,EAAa,EAA+B,CACvD,IAAI,EACJ,GAAI,CACA,EAAS,MAAM,kBAAkB,CAAI,CACzC,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,gCAAiC,EAAc,UAAW,CAC/E,MAAO,CACX,CAAC,CACL,CACA,GAAI,CACA,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,CAC5D,QAAU,CACN,EAAO,MAAM,CACjB,CACJ,CAEA,SAAS,EAAoB,EAAsC,CAI/D,OAHI,EAAI,UAAY,EAAI,aAAe,EAC5B,QAAQ,QAAQ,EAEpB,IAAI,SAAe,EAAS,IAAW,CAC1C,IAAM,MAAqB,CACvB,EAAQ,EACR,EAAQ,CACZ,EACM,MAAsB,CACxB,EAAQ,EACR,EAAO,IAAI,EAAA,eAAe,sDAAsD,CAAC,CACrF,EACM,MAAsB,CACxB,EAAI,oBAAoB,OAAQ,CAAM,EACtC,EAAI,oBAAoB,QAAS,CAAO,CAC5C,EACA,EAAI,iBAAiB,OAAQ,EAAQ,CAAE,KAAM,EAAK,CAAC,EACnD,EAAI,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,CACzD,CAAC,CACL,CAEA,SAAS,EAAc,EAA6B,EAAe,EAA0B,CACzF,GAAI,IAAU,GAAK,IAAW,EAC1B,MAAM,IAAI,EAAA,eAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":"oGA6BA,eAAsB,EAAU,EAAuC,CACnE,GAAI,aAAkB,EAAA,SAClB,OAAO,EAGX,GAAI,OAAO,UAAc,KAAe,aAAkB,UACtD,OAAO,EAAA,eAAe,CAAM,EAGhC,GAAI,OAAO,GAAW,SAClB,OAAO,EAAY,CAAM,EAG7B,GAAI,OAAO,KAAS,KAAe,aAAkB,KACjD,OAAO,EAAa,CAAM,EAG9B,GAAI,OAAO,iBAAqB,KAAe,aAAkB,iBAE7D,OADA,MAAM,EAAoB,CAAM,EACzB,EAAc,EAAQ,EAAO,aAAc,EAAO,aAAa,EAW1E,GARI,OAAO,kBAAsB,KAAe,aAAkB,mBAI9D,OAAO,gBAAoB,KAAe,aAAkB,iBAI5D,OAAO,YAAgB,KAAe,aAAkB,YACxD,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,EAG5D,MAAM,IAAI,EAAA,eACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E,CACJ,CAEA,eAAe,EAAY,EAAgC,CACvD,IAAI,EACJ,GAAI,CACA,EAAW,MAAM,MAAM,CAAG,CAC9B,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,8BAA8B,EAAI,IAAK,EAAc,UAAW,CACrF,MAAO,CACX,CAAC,CACL,CACA,GAAI,CAAC,EAAS,GACV,MAAM,IAAI,EAAA,eACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E,EAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT,CAC5B,CAEA,eAAe,EAAa,EAA+B,CACvD,IAAI,EACJ,GAAI,CACA,EAAS,MAAM,kBAAkB,CAAI,CACzC,OAAS,EAAK,CACV,MAAM,IAAI,EAAA,eAAe,gCAAiC,EAAc,UAAW,CAC/E,MAAO,CACX,CAAC,CACL,CACA,GAAI,CACA,OAAO,EAAc,EAAQ,EAAO,MAAO,EAAO,MAAM,CAC5D,QAAU,CACN,EAAO,MAAM,CACjB,CACJ,CAEA,SAAS,EAAoB,EAAsC,CAI/D,OAHI,EAAI,UAAY,EAAI,aAAe,EAC5B,QAAQ,QAAQ,EAEpB,IAAI,SAAe,EAAS,IAAW,CAC1C,IAAM,MAAqB,CACvB,EAAQ,EACR,EAAQ,CACZ,EACM,MAAsB,CACxB,EAAQ,EACR,EAAO,IAAI,EAAA,eAAe,sDAAsD,CAAC,CACrF,EACM,MAAsB,CACxB,EAAI,oBAAoB,OAAQ,CAAM,EACtC,EAAI,oBAAoB,QAAS,CAAO,CAC5C,EACA,EAAI,iBAAiB,OAAQ,EAAQ,CAAE,KAAM,EAAK,CAAC,EACnD,EAAI,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,CACzD,CAAC,CACL,CAEA,SAAS,EAAc,EAA6B,EAAe,EAA0B,CACzF,GAAI,IAAU,GAAK,IAAW,EAC1B,MAAM,IAAI,EAAA,eAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG,EAE1F,IAAM,EAAS,EAAA,aAAa,EAAO,CAAM,EACnC,EAAM,EAAA,aAAa,CAAM,EAC/B,EAAI,UAAU,EAAU,EAAG,CAAC,EAC5B,IAAM,EAAY,EAAI,aAAa,EAAG,EAAG,EAAO,CAAM,EACtD,OAAO,EAAA,eAAe,CAAS,CACnC"}
|
package/dist/vision/io/image.js
CHANGED
|
@@ -48,8 +48,10 @@ function c(t) {
|
|
|
48
48
|
}
|
|
49
49
|
function l(t, a, o) {
|
|
50
50
|
if (a === 0 || o === 0) throw new e(`Cannot load image with zero dimension (${a}x${o}).`);
|
|
51
|
-
let s =
|
|
52
|
-
|
|
51
|
+
let s = n(a, o), c = r(s);
|
|
52
|
+
c.drawImage(t, 0, 0);
|
|
53
|
+
let l = c.getImageData(0, 0, a, o);
|
|
54
|
+
return i(l);
|
|
53
55
|
}
|
|
54
56
|
//#endregion
|
|
55
57
|
export { a as loadImage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":";;;;AA6BA,eAAsB,EAAU,GAAuC;CACnE,IAAI,aAAkB,GAClB,OAAO;CAGX,IAAI,OAAO,YAAc,OAAe,aAAkB,WACtD,OAAO,EAAe,CAAM;CAGhC,IAAI,OAAO,KAAW,UAClB,OAAO,EAAY,CAAM;CAG7B,IAAI,OAAO,OAAS,OAAe,aAAkB,MACjD,OAAO,EAAa,CAAM;CAG9B,IAAI,OAAO,mBAAqB,OAAe,aAAkB,kBAE7D,OADA,MAAM,EAAoB,CAAM,GACzB,EAAc,GAAQ,EAAO,cAAc,EAAO,aAAa;CAW1E,IARI,OAAO,oBAAsB,OAAe,aAAkB,qBAI9D,OAAO,kBAAoB,OAAe,aAAkB,mBAI5D,OAAO,cAAgB,OAAe,aAAkB,aACxD,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAG5D,MAAM,IAAI,EACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E;AACJ;AAEA,eAAe,EAAY,GAAgC;CACvD,IAAI;CACJ,IAAI;EACA,IAAW,MAAM,MAAM,CAAG;CAC9B,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,8BAA8B,EAAI,IAAK,EAAc,WAAW,EACrF,OAAO,EACX,CAAC;CACL;CACA,IAAI,CAAC,EAAS,IACV,MAAM,IAAI,EACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E;CAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT;AAC5B;AAEA,eAAe,EAAa,GAA+B;CACvD,IAAI;CACJ,IAAI;EACA,IAAS,MAAM,kBAAkB,CAAI;CACzC,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,gCAAiC,EAAc,WAAW,EAC/E,OAAO,EACX,CAAC;CACL;CACA,IAAI;EACA,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAC5D,UAAU;EACN,EAAO,MAAM;CACjB;AACJ;AAEA,SAAS,EAAoB,GAAsC;CAI/D,OAHI,EAAI,YAAY,EAAI,eAAe,IAC5B,QAAQ,QAAQ,IAEpB,IAAI,SAAe,GAAS,MAAW;EAC1C,IAAM,UAAqB;GAEvB,AADA,EAAQ,GACR,EAAQ;EACZ,GACM,UAAsB;GAExB,AADA,EAAQ,GACR,EAAO,IAAI,EAAe,sDAAsD,CAAC;EACrF,GACM,UAAsB;GAExB,AADA,EAAI,oBAAoB,QAAQ,CAAM,GACtC,EAAI,oBAAoB,SAAS,CAAO;EAC5C;EAEA,AADA,EAAI,iBAAiB,QAAQ,GAAQ,EAAE,MAAM,GAAK,CAAC,GACnD,EAAI,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC;CACzD,CAAC;AACL;AAEA,SAAS,EAAc,GAA6B,GAAe,GAA0B;CACzF,IAAI,MAAU,KAAK,MAAW,GAC1B,MAAM,IAAI,EAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG;
|
|
1
|
+
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/io/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Image loading utilities — convert any supported source into the canonical\n * {@link RGBImage} format.\n *\n * Browser-only: uses `fetch`, `createImageBitmap`, and a Canvas 2D context to\n * decode arbitrary inputs into a tightly-packed `Uint8Array` of HWC RGB pixels.\n */\n\nimport { createCanvas, get2DContext, imageDataToRGB } from \"../core/canvas\";\nimport { ImageLoadError } from \"../core/exceptions\";\nimport { RGBImage } from \"../types\";\n\n/** Anything {@link loadImage} accepts as an image input. */\nexport type ImageInput =\n | string\n | Blob\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageBitmap\n | ImageData\n | RGBImage;\n\n/**\n * Load an image from any supported source into a HWC uint8 RGB array.\n *\n * @throws {@link ImageLoadError} if the source cannot be decoded or has an unsupported shape.\n */\nexport async function loadImage(source: ImageInput): Promise<RGBImage> {\n if (source instanceof RGBImage) {\n return source;\n }\n\n if (typeof ImageData !== \"undefined\" && source instanceof ImageData) {\n return imageDataToRGB(source);\n }\n\n if (typeof source === \"string\") {\n return loadFromUrl(source);\n }\n\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return loadFromBlob(source);\n }\n\n if (typeof HTMLImageElement !== \"undefined\" && source instanceof HTMLImageElement) {\n await waitForImageElement(source);\n return drawableToRGB(source, source.naturalWidth, source.naturalHeight);\n }\n\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n return drawableToRGB(source, source.width, source.height);\n }\n\n throw new ImageLoadError(\n `Unsupported image source type: ${Object.prototype.toString.call(source)}`,\n );\n}\n\nasync function loadFromUrl(url: string): Promise<RGBImage> {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw new ImageLoadError(`Failed to fetch image from ${url}: ${(err as Error).message}`, {\n cause: err,\n });\n }\n if (!response.ok) {\n throw new ImageLoadError(\n `Failed to fetch image from ${url}: HTTP ${response.status} ${response.statusText}`,\n );\n }\n const blob = await response.blob();\n return loadFromBlob(blob);\n}\n\nasync function loadFromBlob(blob: Blob): Promise<RGBImage> {\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(blob);\n } catch (err) {\n throw new ImageLoadError(`Failed to decode image blob: ${(err as Error).message}`, {\n cause: err,\n });\n }\n try {\n return drawableToRGB(bitmap, bitmap.width, bitmap.height);\n } finally {\n bitmap.close();\n }\n}\n\nfunction waitForImageElement(img: HTMLImageElement): Promise<void> {\n if (img.complete && img.naturalWidth > 0) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n const onLoad = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new ImageLoadError(\"Failed to load HTMLImageElement (load event errored)\"));\n };\n const cleanup = (): void => {\n img.removeEventListener(\"load\", onLoad);\n img.removeEventListener(\"error\", onError);\n };\n img.addEventListener(\"load\", onLoad, { once: true });\n img.addEventListener(\"error\", onError, { once: true });\n });\n}\n\nfunction drawableToRGB(drawable: CanvasImageSource, width: number, height: number): RGBImage {\n if (width === 0 || height === 0) {\n throw new ImageLoadError(`Cannot load image with zero dimension (${width}x${height}).`);\n }\n const canvas = createCanvas(width, height);\n const ctx = get2DContext(canvas);\n ctx.drawImage(drawable, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n return imageDataToRGB(imageData);\n}\n"],"mappings":";;;;AA6BA,eAAsB,EAAU,GAAuC;CACnE,IAAI,aAAkB,GAClB,OAAO;CAGX,IAAI,OAAO,YAAc,OAAe,aAAkB,WACtD,OAAO,EAAe,CAAM;CAGhC,IAAI,OAAO,KAAW,UAClB,OAAO,EAAY,CAAM;CAG7B,IAAI,OAAO,OAAS,OAAe,aAAkB,MACjD,OAAO,EAAa,CAAM;CAG9B,IAAI,OAAO,mBAAqB,OAAe,aAAkB,kBAE7D,OADA,MAAM,EAAoB,CAAM,GACzB,EAAc,GAAQ,EAAO,cAAc,EAAO,aAAa;CAW1E,IARI,OAAO,oBAAsB,OAAe,aAAkB,qBAI9D,OAAO,kBAAoB,OAAe,aAAkB,mBAI5D,OAAO,cAAgB,OAAe,aAAkB,aACxD,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAG5D,MAAM,IAAI,EACN,kCAAkC,OAAO,UAAU,SAAS,KAAK,CAAM,GAC3E;AACJ;AAEA,eAAe,EAAY,GAAgC;CACvD,IAAI;CACJ,IAAI;EACA,IAAW,MAAM,MAAM,CAAG;CAC9B,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,8BAA8B,EAAI,IAAK,EAAc,WAAW,EACrF,OAAO,EACX,CAAC;CACL;CACA,IAAI,CAAC,EAAS,IACV,MAAM,IAAI,EACN,8BAA8B,EAAI,SAAS,EAAS,OAAO,GAAG,EAAS,YAC3E;CAGJ,OAAO,EAAa,MADD,EAAS,KAAK,CACT;AAC5B;AAEA,eAAe,EAAa,GAA+B;CACvD,IAAI;CACJ,IAAI;EACA,IAAS,MAAM,kBAAkB,CAAI;CACzC,SAAS,GAAK;EACV,MAAM,IAAI,EAAe,gCAAiC,EAAc,WAAW,EAC/E,OAAO,EACX,CAAC;CACL;CACA,IAAI;EACA,OAAO,EAAc,GAAQ,EAAO,OAAO,EAAO,MAAM;CAC5D,UAAU;EACN,EAAO,MAAM;CACjB;AACJ;AAEA,SAAS,EAAoB,GAAsC;CAI/D,OAHI,EAAI,YAAY,EAAI,eAAe,IAC5B,QAAQ,QAAQ,IAEpB,IAAI,SAAe,GAAS,MAAW;EAC1C,IAAM,UAAqB;GAEvB,AADA,EAAQ,GACR,EAAQ;EACZ,GACM,UAAsB;GAExB,AADA,EAAQ,GACR,EAAO,IAAI,EAAe,sDAAsD,CAAC;EACrF,GACM,UAAsB;GAExB,AADA,EAAI,oBAAoB,QAAQ,CAAM,GACtC,EAAI,oBAAoB,SAAS,CAAO;EAC5C;EAEA,AADA,EAAI,iBAAiB,QAAQ,GAAQ,EAAE,MAAM,GAAK,CAAC,GACnD,EAAI,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC;CACzD,CAAC;AACL;AAEA,SAAS,EAAc,GAA6B,GAAe,GAA0B;CACzF,IAAI,MAAU,KAAK,MAAW,GAC1B,MAAM,IAAI,EAAe,0CAA0C,EAAM,GAAG,EAAO,GAAG;CAE1F,IAAM,IAAS,EAAa,GAAO,CAAM,GACnC,IAAM,EAAa,CAAM;CAC/B,EAAI,UAAU,GAAU,GAAG,CAAC;CAC5B,IAAM,IAAY,EAAI,aAAa,GAAG,GAAG,GAAO,CAAM;CACtD,OAAO,EAAe,CAAS;AACnC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");let r=require("onnxruntime-web");r=e.__toESM(r,1);function i(e,t,r){if(t<=0||r<=0)throw Error(`Invalid resize target ${t}x${r}.`);if(t===e.width&&r===e.height)return e;let i=n.createCanvas(e.width,e.height);n.get2DContext(i).putImageData(n.rgbToImageData(e),0,0);let a=n.
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");let r=require("onnxruntime-web");r=e.__toESM(r,1);function i(e,t,r){if(t<=0||r<=0)throw Error(`Invalid resize target ${t}x${r}.`);if(t===e.width&&r===e.height)return e;let i=n.createCanvas(e.width,e.height);n.get2DContext(i).putImageData(n.rgbToImageData(e),0,0);let a=n.createCanvas(t,r),o=n.get2DContext(a);o.imageSmoothingEnabled=!0,o.imageSmoothingQuality=`high`,o.drawImage(i,0,0,t,r);let s=o.getImageData(0,0,t,r);return n.imageDataToRGB(s)}function a(e,t,n,r=1/255){let i=new Float32Array(e.data.length),a=e.data,o=t[0],s=t[1],c=t[2],l=n[0],u=n[1],d=n[2];for(let e=0;e<a.length;e+=3)i[e]=(a[e]*r-o)/l,i[e+1]=(a[e+1]*r-s)/u,i[e+2]=(a[e+2]*r-c)/d;return i}function o(e,t=1/255){let n=new Float32Array(e.data.length),r=e.data;for(let e=0;e<r.length;e++)n[e]=r[e]*t;return n}function s(e,t,n,r=3){let i=t*n*r;if(e.length!==i)throw Error(`toCHW: expected length ${i} for ${t}x${n}x${r}, got ${e.length}.`);let a=new Float32Array(i),o=t*n;for(let i=0;i<n;i++)for(let n=0;n<t;n++){let s=(i*t+n)*r,c=i*t+n;for(let t=0;t<r;t++)a[t*o+c]=e[s+t]}return a}function c(e,t){return new r.Tensor(`float32`,e,t)}function l(e){return s(o(e),e.width,e.height,3)}function u(e,n,r){if(e.length!==n*r*3)throw Error(`fromCv2: data length ${e.length} does not match width * height * 3 = ${n*r*3}.`);let i=new Uint8Array(e.length);for(let t=0;t<e.length;t+=3)i[t]=e[t+2],i[t+1]=e[t+1],i[t+2]=e[t];return new t.RGBImage(i,n,r)}function d(e){let t=e.data,n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=3)n[e]=t[e+2],n[e+1]=t[e+1],n[e+2]=t[e];return n}function f(e,n,r,a=[114,114,114]){let o=Math.min(n/e.width,r/e.height),s=Math.round(e.width*o),c=Math.round(e.height*o),l=i(e,s,c),u=new Uint8Array(n*r*3),d=a[0],f=a[1],p=a[2];for(let e=0;e<u.length;e+=3)u[e]=d,u[e+1]=f,u[e+2]=p;let m=Math.floor((n-s)/2),h=Math.floor((r-c)/2),g=s*3;for(let e=0;e<c;e++){let t=e*g,r=((h+e)*n+m)*3;u.set(l.data.subarray(t,t+g),r)}return{image:new t.RGBImage(u,n,r),scale:o,padLeft:m,padTop:h}}exports.fromCv2=u,exports.letterbox=f,exports.normalize=a,exports.resize=i,exports.toCHW=s,exports.toCv2=d,exports.toFloat32=o,exports.toFloat32Tensor=c,exports.toTensor=l;
|
|
2
2
|
//# sourceMappingURL=image.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/preprocess/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Composable image preprocessing primitives (resize, normalize, letterbox, layout).\n *\n * Mirrors the Python `preprocess.image` module. Operates on the canonical\n * {@link RGBImage} (HWC RGB uint8) and produces uint8 or float32 buffers\n * depending on the operation.\n */\n\nimport * as ortRuntime from \"onnxruntime-web\";\nimport type * as ort from \"onnxruntime-web\";\n\nimport { createCanvas, get2DContext, imageDataToRGB, rgbToImageData } from \"../core/canvas\";\nimport { RGBImage } from \"../types\";\n\n/** Resize an image to `(targetWidth, targetHeight)` using high-quality canvas resampling. */\nexport function resize(image: RGBImage, targetWidth: number, targetHeight: number): RGBImage {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid resize target ${targetWidth}x${targetHeight}.`);\n }\n if (targetWidth === image.width && targetHeight === image.height) {\n return image;\n }\n\n const srcCanvas = createCanvas(image.width, image.height);\n const srcCtx = get2DContext(srcCanvas);\n srcCtx.putImageData(rgbToImageData(image), 0, 0);\n\n const dstCanvas = createCanvas(targetWidth, targetHeight);\n const dstCtx = get2DContext(dstCanvas);\n dstCtx.imageSmoothingEnabled = true;\n dstCtx.imageSmoothingQuality = \"high\";\n dstCtx.drawImage(srcCanvas as CanvasImageSource, 0, 0, targetWidth, targetHeight);\n\n const imageData = dstCtx.getImageData(0, 0, targetWidth, targetHeight);\n return imageDataToRGB(imageData);\n}\n\n/**\n * Convert a uint8 image to a normalized float32 array (HWC layout preserved).\n *\n * Applies `(pixel * scale - mean) / std` channel-wise.\n */\nexport function normalize(\n image: RGBImage,\n mean: readonly [number, number, number],\n std: readonly [number, number, number],\n scale: number = 1 / 255,\n): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n const m0 = mean[0];\n const m1 = mean[1];\n const m2 = mean[2];\n const s0 = std[0];\n const s1 = std[1];\n const s2 = std[2];\n for (let i = 0; i < data.length; i += 3) {\n out[i] = ((data[i] as number) * scale - m0) / s0;\n out[i + 1] = ((data[i + 1] as number) * scale - m1) / s1;\n out[i + 2] = ((data[i + 2] as number) * scale - m2) / s2;\n }\n return out;\n}\n\n/** Convert a uint8 image to a `Float32Array` in `[0, 1]` (HWC layout preserved). */\nexport function toFloat32(image: RGBImage, scale: number = 1 / 255): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n for (let i = 0; i < data.length; i++) {\n out[i] = (data[i] as number) * scale;\n }\n return out;\n}\n\n/**\n * Transpose interleaved HWC data to planar CHW layout.\n *\n * @param hwc Source array of length `width * height * channels`.\n */\nexport function toCHW(\n hwc: Float32Array,\n width: number,\n height: number,\n channels: number = 3,\n): Float32Array {\n const expected = width * height * channels;\n if (hwc.length !== expected) {\n throw new Error(\n `toCHW: expected length ${expected} for ${width}x${height}x${channels}, got ${hwc.length}.`,\n );\n }\n const chw = new Float32Array(expected);\n const plane = width * height;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const hwcBase = (y * width + x) * channels;\n const planeIdx = y * width + x;\n for (let c = 0; c < channels; c++) {\n chw[c * plane + planeIdx] = hwc[hwcBase + c] as number;\n }\n }\n }\n return chw;\n}\n\n/** Wrap a Float32 buffer into an `ort.Tensor`. */\nexport function toFloat32Tensor(data: Float32Array, dims: readonly number[]): ort.Tensor {\n return new ortRuntime.Tensor(\"float32\", data, dims as number[]);\n}\n\n/**\n * Convert an HWC uint8 image to a CHW `Float32Array` scaled to `[0, 1]`.\n *\n * Mirrors `torchvision.transforms.ToTensor()` semantics: HWC → CHW,\n * `uint8 → float32 / 255`. Useful as input to YOLO-style detectors that\n * don't require ImageNet normalization.\n *\n * @returns CHW `Float32Array` of length `width * height * 3`.\n */\nexport function toTensor(image: RGBImage): Float32Array {\n const f32 = toFloat32(image);\n return toCHW(f32, image.width, image.height, 3);\n}\n\n/**\n * Convert an HWC BGR uint8 buffer (OpenCV layout) to the SDK's HWC RGB.\n *\n * Use when you receive image bytes from `cv2.imencode` over the wire and\n * want to feed them to the SDK without going through a canvas decode.\n *\n * @param bgr Flat BGR Uint8Array of length `width * height * 3`.\n */\nexport function fromCv2(bgr: Uint8Array, width: number, height: number): RGBImage {\n if (bgr.length !== width * height * 3) {\n throw new Error(\n `fromCv2: data length ${bgr.length} does not match width * height * 3 = ${width * height * 3}.`,\n );\n }\n const rgb = new Uint8Array(bgr.length);\n for (let i = 0; i < bgr.length; i += 3) {\n rgb[i] = bgr[i + 2] as number;\n rgb[i + 1] = bgr[i + 1] as number;\n rgb[i + 2] = bgr[i] as number;\n }\n return new RGBImage(rgb, width, height);\n}\n\n/**\n * Convert the SDK's HWC RGB image to an HWC BGR `Uint8Array` (OpenCV layout).\n *\n * Useful for round-tripping data to a Python OpenCV consumer.\n */\nexport function toCv2(image: RGBImage): Uint8Array {\n const rgb = image.data;\n const bgr = new Uint8Array(rgb.length);\n for (let i = 0; i < rgb.length; i += 3) {\n bgr[i] = rgb[i + 2] as number;\n bgr[i + 1] = rgb[i + 1] as number;\n bgr[i + 2] = rgb[i] as number;\n }\n return bgr;\n}\n\nexport interface LetterboxResult {\n /** The padded image at the target size. */\n readonly image: RGBImage;\n /** The factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels (left side; right side has the same or +1). */\n readonly padLeft: number;\n /** Vertical padding in pixels (top side). */\n readonly padTop: number;\n}\n\n/**\n * Resize preserving aspect ratio, padding to `(targetWidth, targetHeight)`\n * with a constant fill color.\n *\n * Standard YOLO preprocessing — returning `scale` and `padLeft`/`padTop`\n * lets callers map detections back to the original image coordinates.\n */\nexport function letterbox(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): LetterboxResult {\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const newW = Math.round(image.width * scale);\n const newH = Math.round(image.height * scale);\n const resized = resize(image, newW, newH);\n\n const out = new Uint8Array(targetWidth * targetHeight * 3);\n const f0 = fill[0];\n const f1 = fill[1];\n const f2 = fill[2];\n for (let i = 0; i < out.length; i += 3) {\n out[i] = f0;\n out[i + 1] = f1;\n out[i + 2] = f2;\n }\n\n const padLeft = Math.floor((targetWidth - newW) / 2);\n const padTop = Math.floor((targetHeight - newH) / 2);\n const rowBytes = newW * 3;\n for (let y = 0; y < newH; y++) {\n const srcOffset = y * rowBytes;\n const dstOffset = ((padTop + y) * targetWidth + padLeft) * 3;\n out.set(resized.data.subarray(srcOffset, srcOffset + rowBytes), dstOffset);\n }\n\n return {\n image: new RGBImage(out, targetWidth, targetHeight),\n scale,\n padLeft,\n padTop,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"image.cjs","names":[],"sources":["../../../src/vision/preprocess/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Composable image preprocessing primitives (resize, normalize, letterbox, layout).\n *\n * Mirrors the Python `preprocess.image` module. Operates on the canonical\n * {@link RGBImage} (HWC RGB uint8) and produces uint8 or float32 buffers\n * depending on the operation.\n */\n\nimport * as ortRuntime from \"onnxruntime-web\";\nimport type * as ort from \"onnxruntime-web\";\n\nimport { createCanvas, get2DContext, imageDataToRGB, rgbToImageData } from \"../core/canvas\";\nimport { RGBImage } from \"../types\";\n\n/** Resize an image to `(targetWidth, targetHeight)` using high-quality canvas resampling. */\nexport function resize(image: RGBImage, targetWidth: number, targetHeight: number): RGBImage {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid resize target ${targetWidth}x${targetHeight}.`);\n }\n if (targetWidth === image.width && targetHeight === image.height) {\n return image;\n }\n\n const srcCanvas = createCanvas(image.width, image.height);\n const srcCtx = get2DContext(srcCanvas);\n srcCtx.putImageData(rgbToImageData(image), 0, 0);\n\n const dstCanvas = createCanvas(targetWidth, targetHeight);\n const dstCtx = get2DContext(dstCanvas);\n dstCtx.imageSmoothingEnabled = true;\n dstCtx.imageSmoothingQuality = \"high\";\n dstCtx.drawImage(srcCanvas as CanvasImageSource, 0, 0, targetWidth, targetHeight);\n\n const imageData = dstCtx.getImageData(0, 0, targetWidth, targetHeight);\n return imageDataToRGB(imageData);\n}\n\n/**\n * Convert a uint8 image to a normalized float32 array (HWC layout preserved).\n *\n * Applies `(pixel * scale - mean) / std` channel-wise.\n */\nexport function normalize(\n image: RGBImage,\n mean: readonly [number, number, number],\n std: readonly [number, number, number],\n scale: number = 1 / 255,\n): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n const m0 = mean[0];\n const m1 = mean[1];\n const m2 = mean[2];\n const s0 = std[0];\n const s1 = std[1];\n const s2 = std[2];\n for (let i = 0; i < data.length; i += 3) {\n out[i] = ((data[i] as number) * scale - m0) / s0;\n out[i + 1] = ((data[i + 1] as number) * scale - m1) / s1;\n out[i + 2] = ((data[i + 2] as number) * scale - m2) / s2;\n }\n return out;\n}\n\n/** Convert a uint8 image to a `Float32Array` in `[0, 1]` (HWC layout preserved). */\nexport function toFloat32(image: RGBImage, scale: number = 1 / 255): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n for (let i = 0; i < data.length; i++) {\n out[i] = (data[i] as number) * scale;\n }\n return out;\n}\n\n/**\n * Transpose interleaved HWC data to planar CHW layout.\n *\n * @param hwc Source array of length `width * height * channels`.\n */\nexport function toCHW(\n hwc: Float32Array,\n width: number,\n height: number,\n channels: number = 3,\n): Float32Array {\n const expected = width * height * channels;\n if (hwc.length !== expected) {\n throw new Error(\n `toCHW: expected length ${expected} for ${width}x${height}x${channels}, got ${hwc.length}.`,\n );\n }\n const chw = new Float32Array(expected);\n const plane = width * height;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const hwcBase = (y * width + x) * channels;\n const planeIdx = y * width + x;\n for (let c = 0; c < channels; c++) {\n chw[c * plane + planeIdx] = hwc[hwcBase + c] as number;\n }\n }\n }\n return chw;\n}\n\n/** Wrap a Float32 buffer into an `ort.Tensor`. */\nexport function toFloat32Tensor(data: Float32Array, dims: readonly number[]): ort.Tensor {\n return new ortRuntime.Tensor(\"float32\", data, dims as number[]);\n}\n\n/**\n * Convert an HWC uint8 image to a CHW `Float32Array` scaled to `[0, 1]`.\n *\n * Mirrors `torchvision.transforms.ToTensor()` semantics: HWC → CHW,\n * `uint8 → float32 / 255`. Useful as input to YOLO-style detectors that\n * don't require ImageNet normalization.\n *\n * @returns CHW `Float32Array` of length `width * height * 3`.\n */\nexport function toTensor(image: RGBImage): Float32Array {\n const f32 = toFloat32(image);\n return toCHW(f32, image.width, image.height, 3);\n}\n\n/**\n * Convert an HWC BGR uint8 buffer (OpenCV layout) to the SDK's HWC RGB.\n *\n * Use when you receive image bytes from `cv2.imencode` over the wire and\n * want to feed them to the SDK without going through a canvas decode.\n *\n * @param bgr Flat BGR Uint8Array of length `width * height * 3`.\n */\nexport function fromCv2(bgr: Uint8Array, width: number, height: number): RGBImage {\n if (bgr.length !== width * height * 3) {\n throw new Error(\n `fromCv2: data length ${bgr.length} does not match width * height * 3 = ${width * height * 3}.`,\n );\n }\n const rgb = new Uint8Array(bgr.length);\n for (let i = 0; i < bgr.length; i += 3) {\n rgb[i] = bgr[i + 2] as number;\n rgb[i + 1] = bgr[i + 1] as number;\n rgb[i + 2] = bgr[i] as number;\n }\n return new RGBImage(rgb, width, height);\n}\n\n/**\n * Convert the SDK's HWC RGB image to an HWC BGR `Uint8Array` (OpenCV layout).\n *\n * Useful for round-tripping data to a Python OpenCV consumer.\n */\nexport function toCv2(image: RGBImage): Uint8Array {\n const rgb = image.data;\n const bgr = new Uint8Array(rgb.length);\n for (let i = 0; i < rgb.length; i += 3) {\n bgr[i] = rgb[i + 2] as number;\n bgr[i + 1] = rgb[i + 1] as number;\n bgr[i + 2] = rgb[i] as number;\n }\n return bgr;\n}\n\nexport interface LetterboxResult {\n /** The padded image at the target size. */\n readonly image: RGBImage;\n /** The factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels (left side; right side has the same or +1). */\n readonly padLeft: number;\n /** Vertical padding in pixels (top side). */\n readonly padTop: number;\n}\n\n/**\n * Resize preserving aspect ratio, padding to `(targetWidth, targetHeight)`\n * with a constant fill color.\n *\n * Standard YOLO preprocessing — returning `scale` and `padLeft`/`padTop`\n * lets callers map detections back to the original image coordinates.\n */\nexport function letterbox(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): LetterboxResult {\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const newW = Math.round(image.width * scale);\n const newH = Math.round(image.height * scale);\n const resized = resize(image, newW, newH);\n\n const out = new Uint8Array(targetWidth * targetHeight * 3);\n const f0 = fill[0];\n const f1 = fill[1];\n const f2 = fill[2];\n for (let i = 0; i < out.length; i += 3) {\n out[i] = f0;\n out[i + 1] = f1;\n out[i + 2] = f2;\n }\n\n const padLeft = Math.floor((targetWidth - newW) / 2);\n const padTop = Math.floor((targetHeight - newH) / 2);\n const rowBytes = newW * 3;\n for (let y = 0; y < newH; y++) {\n const srcOffset = y * rowBytes;\n const dstOffset = ((padTop + y) * targetWidth + padLeft) * 3;\n out.set(resized.data.subarray(srcOffset, srcOffset + rowBytes), dstOffset);\n }\n\n return {\n image: new RGBImage(out, targetWidth, targetHeight),\n scale,\n padLeft,\n padTop,\n };\n}\n"],"mappings":"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"}
|
|
@@ -7,8 +7,10 @@ function o(e, a, o) {
|
|
|
7
7
|
if (a === e.width && o === e.height) return e;
|
|
8
8
|
let s = t(e.width, e.height);
|
|
9
9
|
n(s).putImageData(i(e), 0, 0);
|
|
10
|
-
let c =
|
|
11
|
-
|
|
10
|
+
let c = t(a, o), l = n(c);
|
|
11
|
+
l.imageSmoothingEnabled = !0, l.imageSmoothingQuality = "high", l.drawImage(s, 0, 0, a, o);
|
|
12
|
+
let u = l.getImageData(0, 0, a, o);
|
|
13
|
+
return r(u);
|
|
12
14
|
}
|
|
13
15
|
function s(e, t, n, r = 1 / 255) {
|
|
14
16
|
let i = new Float32Array(e.data.length), a = e.data, o = t[0], s = t[1], c = t[2], l = n[0], u = n[1], d = n[2];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/preprocess/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Composable image preprocessing primitives (resize, normalize, letterbox, layout).\n *\n * Mirrors the Python `preprocess.image` module. Operates on the canonical\n * {@link RGBImage} (HWC RGB uint8) and produces uint8 or float32 buffers\n * depending on the operation.\n */\n\nimport * as ortRuntime from \"onnxruntime-web\";\nimport type * as ort from \"onnxruntime-web\";\n\nimport { createCanvas, get2DContext, imageDataToRGB, rgbToImageData } from \"../core/canvas\";\nimport { RGBImage } from \"../types\";\n\n/** Resize an image to `(targetWidth, targetHeight)` using high-quality canvas resampling. */\nexport function resize(image: RGBImage, targetWidth: number, targetHeight: number): RGBImage {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid resize target ${targetWidth}x${targetHeight}.`);\n }\n if (targetWidth === image.width && targetHeight === image.height) {\n return image;\n }\n\n const srcCanvas = createCanvas(image.width, image.height);\n const srcCtx = get2DContext(srcCanvas);\n srcCtx.putImageData(rgbToImageData(image), 0, 0);\n\n const dstCanvas = createCanvas(targetWidth, targetHeight);\n const dstCtx = get2DContext(dstCanvas);\n dstCtx.imageSmoothingEnabled = true;\n dstCtx.imageSmoothingQuality = \"high\";\n dstCtx.drawImage(srcCanvas as CanvasImageSource, 0, 0, targetWidth, targetHeight);\n\n const imageData = dstCtx.getImageData(0, 0, targetWidth, targetHeight);\n return imageDataToRGB(imageData);\n}\n\n/**\n * Convert a uint8 image to a normalized float32 array (HWC layout preserved).\n *\n * Applies `(pixel * scale - mean) / std` channel-wise.\n */\nexport function normalize(\n image: RGBImage,\n mean: readonly [number, number, number],\n std: readonly [number, number, number],\n scale: number = 1 / 255,\n): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n const m0 = mean[0];\n const m1 = mean[1];\n const m2 = mean[2];\n const s0 = std[0];\n const s1 = std[1];\n const s2 = std[2];\n for (let i = 0; i < data.length; i += 3) {\n out[i] = ((data[i] as number) * scale - m0) / s0;\n out[i + 1] = ((data[i + 1] as number) * scale - m1) / s1;\n out[i + 2] = ((data[i + 2] as number) * scale - m2) / s2;\n }\n return out;\n}\n\n/** Convert a uint8 image to a `Float32Array` in `[0, 1]` (HWC layout preserved). */\nexport function toFloat32(image: RGBImage, scale: number = 1 / 255): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n for (let i = 0; i < data.length; i++) {\n out[i] = (data[i] as number) * scale;\n }\n return out;\n}\n\n/**\n * Transpose interleaved HWC data to planar CHW layout.\n *\n * @param hwc Source array of length `width * height * channels`.\n */\nexport function toCHW(\n hwc: Float32Array,\n width: number,\n height: number,\n channels: number = 3,\n): Float32Array {\n const expected = width * height * channels;\n if (hwc.length !== expected) {\n throw new Error(\n `toCHW: expected length ${expected} for ${width}x${height}x${channels}, got ${hwc.length}.`,\n );\n }\n const chw = new Float32Array(expected);\n const plane = width * height;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const hwcBase = (y * width + x) * channels;\n const planeIdx = y * width + x;\n for (let c = 0; c < channels; c++) {\n chw[c * plane + planeIdx] = hwc[hwcBase + c] as number;\n }\n }\n }\n return chw;\n}\n\n/** Wrap a Float32 buffer into an `ort.Tensor`. */\nexport function toFloat32Tensor(data: Float32Array, dims: readonly number[]): ort.Tensor {\n return new ortRuntime.Tensor(\"float32\", data, dims as number[]);\n}\n\n/**\n * Convert an HWC uint8 image to a CHW `Float32Array` scaled to `[0, 1]`.\n *\n * Mirrors `torchvision.transforms.ToTensor()` semantics: HWC → CHW,\n * `uint8 → float32 / 255`. Useful as input to YOLO-style detectors that\n * don't require ImageNet normalization.\n *\n * @returns CHW `Float32Array` of length `width * height * 3`.\n */\nexport function toTensor(image: RGBImage): Float32Array {\n const f32 = toFloat32(image);\n return toCHW(f32, image.width, image.height, 3);\n}\n\n/**\n * Convert an HWC BGR uint8 buffer (OpenCV layout) to the SDK's HWC RGB.\n *\n * Use when you receive image bytes from `cv2.imencode` over the wire and\n * want to feed them to the SDK without going through a canvas decode.\n *\n * @param bgr Flat BGR Uint8Array of length `width * height * 3`.\n */\nexport function fromCv2(bgr: Uint8Array, width: number, height: number): RGBImage {\n if (bgr.length !== width * height * 3) {\n throw new Error(\n `fromCv2: data length ${bgr.length} does not match width * height * 3 = ${width * height * 3}.`,\n );\n }\n const rgb = new Uint8Array(bgr.length);\n for (let i = 0; i < bgr.length; i += 3) {\n rgb[i] = bgr[i + 2] as number;\n rgb[i + 1] = bgr[i + 1] as number;\n rgb[i + 2] = bgr[i] as number;\n }\n return new RGBImage(rgb, width, height);\n}\n\n/**\n * Convert the SDK's HWC RGB image to an HWC BGR `Uint8Array` (OpenCV layout).\n *\n * Useful for round-tripping data to a Python OpenCV consumer.\n */\nexport function toCv2(image: RGBImage): Uint8Array {\n const rgb = image.data;\n const bgr = new Uint8Array(rgb.length);\n for (let i = 0; i < rgb.length; i += 3) {\n bgr[i] = rgb[i + 2] as number;\n bgr[i + 1] = rgb[i + 1] as number;\n bgr[i + 2] = rgb[i] as number;\n }\n return bgr;\n}\n\nexport interface LetterboxResult {\n /** The padded image at the target size. */\n readonly image: RGBImage;\n /** The factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels (left side; right side has the same or +1). */\n readonly padLeft: number;\n /** Vertical padding in pixels (top side). */\n readonly padTop: number;\n}\n\n/**\n * Resize preserving aspect ratio, padding to `(targetWidth, targetHeight)`\n * with a constant fill color.\n *\n * Standard YOLO preprocessing — returning `scale` and `padLeft`/`padTop`\n * lets callers map detections back to the original image coordinates.\n */\nexport function letterbox(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): LetterboxResult {\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const newW = Math.round(image.width * scale);\n const newH = Math.round(image.height * scale);\n const resized = resize(image, newW, newH);\n\n const out = new Uint8Array(targetWidth * targetHeight * 3);\n const f0 = fill[0];\n const f1 = fill[1];\n const f2 = fill[2];\n for (let i = 0; i < out.length; i += 3) {\n out[i] = f0;\n out[i + 1] = f1;\n out[i + 2] = f2;\n }\n\n const padLeft = Math.floor((targetWidth - newW) / 2);\n const padTop = Math.floor((targetHeight - newH) / 2);\n const rowBytes = newW * 3;\n for (let y = 0; y < newH; y++) {\n const srcOffset = y * rowBytes;\n const dstOffset = ((padTop + y) * targetWidth + padLeft) * 3;\n out.set(resized.data.subarray(srcOffset, srcOffset + rowBytes), dstOffset);\n }\n\n return {\n image: new RGBImage(out, targetWidth, targetHeight),\n scale,\n padLeft,\n padTop,\n };\n}\n"],"mappings":";;;;AAgBA,SAAgB,EAAO,GAAiB,GAAqB,GAAgC;CACzF,IAAI,KAAe,KAAK,KAAgB,GACpC,MAAU,MAAM,yBAAyB,EAAY,GAAG,EAAa,EAAE;CAE3E,IAAI,MAAgB,EAAM,SAAS,MAAiB,EAAM,QACtD,OAAO;CAGX,IAAM,IAAY,EAAa,EAAM,OAAO,EAAM,MAAM;CAExD,EAD4B,CAC5B,CAAA,CAAO,aAAa,EAAe,CAAK,GAAG,GAAG,CAAC;CAG/C,IAAM,IAAS,EADG,EAAa,GAAa,CAChB,CAAS;CAMrC,OALA,EAAO,wBAAwB,IAC/B,EAAO,wBAAwB,QAC/B,EAAO,UAAU,GAAgC,GAAG,GAAG,GAAa,CAAY,GAGzE,EADW,EAAO,aAAa,GAAG,GAAG,GAAa,CACnC,CAAS;AACnC;AAOA,SAAgB,EACZ,GACA,GACA,GACA,IAAgB,IAAI,KACR;CACZ,IAAM,IAAM,IAAI,aAAa,EAAM,KAAK,MAAM,GACxC,IAAO,EAAM,MACb,IAAK,EAAK,IACV,IAAK,EAAK,IACV,IAAK,EAAK,IACV,IAAK,EAAI,IACT,IAAK,EAAI,IACT,IAAK,EAAI;CACf,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,GAGlC,AAFA,EAAI,MAAO,EAAK,KAAgB,IAAQ,KAAM,GAC9C,EAAI,IAAI,MAAO,EAAK,IAAI,KAAgB,IAAQ,KAAM,GACtD,EAAI,IAAI,MAAO,EAAK,IAAI,KAAgB,IAAQ,KAAM;CAE1D,OAAO;AACX;AAGA,SAAgB,EAAU,GAAiB,IAAgB,IAAI,KAAmB;CAC9E,IAAM,IAAM,IAAI,aAAa,EAAM,KAAK,MAAM,GACxC,IAAO,EAAM;CACnB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAC7B,EAAI,KAAM,EAAK,KAAgB;CAEnC,OAAO;AACX;AAOA,SAAgB,EACZ,GACA,GACA,GACA,IAAmB,GACP;CACZ,IAAM,IAAW,IAAQ,IAAS;CAClC,IAAI,EAAI,WAAW,GACf,MAAU,MACN,0BAA0B,EAAS,OAAO,EAAM,GAAG,EAAO,GAAG,EAAS,QAAQ,EAAI,OAAO,EAC7F;CAEJ,IAAM,IAAM,IAAI,aAAa,CAAQ,GAC/B,IAAQ,IAAQ;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAQ,KACxB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK;EAC5B,IAAM,KAAW,IAAI,IAAQ,KAAK,GAC5B,IAAW,IAAI,IAAQ;EAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAU,KAC1B,EAAI,IAAI,IAAQ,KAAY,EAAI,IAAU;CAElD;CAEJ,OAAO;AACX;AAGA,SAAgB,EAAgB,GAAoB,GAAqC;CACrF,OAAO,IAAI,EAAW,OAAO,WAAW,GAAM,CAAgB;AAClE;AAWA,SAAgB,EAAS,GAA+B;CAEpD,OAAO,EADK,EAAU,CACT,GAAK,EAAM,OAAO,EAAM,QAAQ,CAAC;AAClD;AAUA,SAAgB,EAAQ,GAAiB,GAAe,GAA0B;CAC9E,IAAI,EAAI,WAAW,IAAQ,IAAS,GAChC,MAAU,MACN,wBAAwB,EAAI,OAAO,uCAAuC,IAAQ,IAAS,EAAE,EACjG;CAEJ,IAAM,IAAM,IAAI,WAAW,EAAI,MAAM;CACrC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK,GAGjC,AAFA,EAAI,KAAK,EAAI,IAAI,IACjB,EAAI,IAAI,KAAK,EAAI,IAAI,IACrB,EAAI,IAAI,KAAK,EAAI;CAErB,OAAO,IAAI,EAAS,GAAK,GAAO,CAAM;AAC1C;AAOA,SAAgB,EAAM,GAA6B;CAC/C,IAAM,IAAM,EAAM,MACZ,IAAM,IAAI,WAAW,EAAI,MAAM;CACrC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK,GAGjC,AAFA,EAAI,KAAK,EAAI,IAAI,IACjB,EAAI,IAAI,KAAK,EAAI,IAAI,IACrB,EAAI,IAAI,KAAK,EAAI;CAErB,OAAO;AACX;AAoBA,SAAgB,EACZ,GACA,GACA,GACA,IAA0C;CAAC;CAAK;CAAK;AAAG,GACzC;CACf,IAAM,IAAQ,KAAK,IAAI,IAAc,EAAM,OAAO,IAAe,EAAM,MAAM,GACvE,IAAO,KAAK,MAAM,EAAM,QAAQ,CAAK,GACrC,IAAO,KAAK,MAAM,EAAM,SAAS,CAAK,GACtC,IAAU,EAAO,GAAO,GAAM,CAAI,GAElC,IAAM,IAAI,WAAW,IAAc,IAAe,CAAC,GACnD,IAAK,EAAK,IACV,IAAK,EAAK,IACV,IAAK,EAAK;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK,GAGjC,AAFA,EAAI,KAAK,GACT,EAAI,IAAI,KAAK,GACb,EAAI,IAAI,KAAK;CAGjB,IAAM,IAAU,KAAK,OAAO,IAAc,KAAQ,CAAC,GAC7C,IAAS,KAAK,OAAO,IAAe,KAAQ,CAAC,GAC7C,IAAW,IAAO;CACxB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAM,KAAK;EAC3B,IAAM,IAAY,IAAI,GAChB,MAAc,IAAS,KAAK,IAAc,KAAW;EAC3D,EAAI,IAAI,EAAQ,KAAK,SAAS,GAAW,IAAY,CAAQ,GAAG,CAAS;CAC7E;CAEA,OAAO;EACH,OAAO,IAAI,EAAS,GAAK,GAAa,CAAY;EAClD;EACA;EACA;CACJ;AACJ"}
|
|
1
|
+
{"version":3,"file":"image.js","names":[],"sources":["../../../src/vision/preprocess/image.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Composable image preprocessing primitives (resize, normalize, letterbox, layout).\n *\n * Mirrors the Python `preprocess.image` module. Operates on the canonical\n * {@link RGBImage} (HWC RGB uint8) and produces uint8 or float32 buffers\n * depending on the operation.\n */\n\nimport * as ortRuntime from \"onnxruntime-web\";\nimport type * as ort from \"onnxruntime-web\";\n\nimport { createCanvas, get2DContext, imageDataToRGB, rgbToImageData } from \"../core/canvas\";\nimport { RGBImage } from \"../types\";\n\n/** Resize an image to `(targetWidth, targetHeight)` using high-quality canvas resampling. */\nexport function resize(image: RGBImage, targetWidth: number, targetHeight: number): RGBImage {\n if (targetWidth <= 0 || targetHeight <= 0) {\n throw new Error(`Invalid resize target ${targetWidth}x${targetHeight}.`);\n }\n if (targetWidth === image.width && targetHeight === image.height) {\n return image;\n }\n\n const srcCanvas = createCanvas(image.width, image.height);\n const srcCtx = get2DContext(srcCanvas);\n srcCtx.putImageData(rgbToImageData(image), 0, 0);\n\n const dstCanvas = createCanvas(targetWidth, targetHeight);\n const dstCtx = get2DContext(dstCanvas);\n dstCtx.imageSmoothingEnabled = true;\n dstCtx.imageSmoothingQuality = \"high\";\n dstCtx.drawImage(srcCanvas as CanvasImageSource, 0, 0, targetWidth, targetHeight);\n\n const imageData = dstCtx.getImageData(0, 0, targetWidth, targetHeight);\n return imageDataToRGB(imageData);\n}\n\n/**\n * Convert a uint8 image to a normalized float32 array (HWC layout preserved).\n *\n * Applies `(pixel * scale - mean) / std` channel-wise.\n */\nexport function normalize(\n image: RGBImage,\n mean: readonly [number, number, number],\n std: readonly [number, number, number],\n scale: number = 1 / 255,\n): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n const m0 = mean[0];\n const m1 = mean[1];\n const m2 = mean[2];\n const s0 = std[0];\n const s1 = std[1];\n const s2 = std[2];\n for (let i = 0; i < data.length; i += 3) {\n out[i] = ((data[i] as number) * scale - m0) / s0;\n out[i + 1] = ((data[i + 1] as number) * scale - m1) / s1;\n out[i + 2] = ((data[i + 2] as number) * scale - m2) / s2;\n }\n return out;\n}\n\n/** Convert a uint8 image to a `Float32Array` in `[0, 1]` (HWC layout preserved). */\nexport function toFloat32(image: RGBImage, scale: number = 1 / 255): Float32Array {\n const out = new Float32Array(image.data.length);\n const data = image.data;\n for (let i = 0; i < data.length; i++) {\n out[i] = (data[i] as number) * scale;\n }\n return out;\n}\n\n/**\n * Transpose interleaved HWC data to planar CHW layout.\n *\n * @param hwc Source array of length `width * height * channels`.\n */\nexport function toCHW(\n hwc: Float32Array,\n width: number,\n height: number,\n channels: number = 3,\n): Float32Array {\n const expected = width * height * channels;\n if (hwc.length !== expected) {\n throw new Error(\n `toCHW: expected length ${expected} for ${width}x${height}x${channels}, got ${hwc.length}.`,\n );\n }\n const chw = new Float32Array(expected);\n const plane = width * height;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const hwcBase = (y * width + x) * channels;\n const planeIdx = y * width + x;\n for (let c = 0; c < channels; c++) {\n chw[c * plane + planeIdx] = hwc[hwcBase + c] as number;\n }\n }\n }\n return chw;\n}\n\n/** Wrap a Float32 buffer into an `ort.Tensor`. */\nexport function toFloat32Tensor(data: Float32Array, dims: readonly number[]): ort.Tensor {\n return new ortRuntime.Tensor(\"float32\", data, dims as number[]);\n}\n\n/**\n * Convert an HWC uint8 image to a CHW `Float32Array` scaled to `[0, 1]`.\n *\n * Mirrors `torchvision.transforms.ToTensor()` semantics: HWC → CHW,\n * `uint8 → float32 / 255`. Useful as input to YOLO-style detectors that\n * don't require ImageNet normalization.\n *\n * @returns CHW `Float32Array` of length `width * height * 3`.\n */\nexport function toTensor(image: RGBImage): Float32Array {\n const f32 = toFloat32(image);\n return toCHW(f32, image.width, image.height, 3);\n}\n\n/**\n * Convert an HWC BGR uint8 buffer (OpenCV layout) to the SDK's HWC RGB.\n *\n * Use when you receive image bytes from `cv2.imencode` over the wire and\n * want to feed them to the SDK without going through a canvas decode.\n *\n * @param bgr Flat BGR Uint8Array of length `width * height * 3`.\n */\nexport function fromCv2(bgr: Uint8Array, width: number, height: number): RGBImage {\n if (bgr.length !== width * height * 3) {\n throw new Error(\n `fromCv2: data length ${bgr.length} does not match width * height * 3 = ${width * height * 3}.`,\n );\n }\n const rgb = new Uint8Array(bgr.length);\n for (let i = 0; i < bgr.length; i += 3) {\n rgb[i] = bgr[i + 2] as number;\n rgb[i + 1] = bgr[i + 1] as number;\n rgb[i + 2] = bgr[i] as number;\n }\n return new RGBImage(rgb, width, height);\n}\n\n/**\n * Convert the SDK's HWC RGB image to an HWC BGR `Uint8Array` (OpenCV layout).\n *\n * Useful for round-tripping data to a Python OpenCV consumer.\n */\nexport function toCv2(image: RGBImage): Uint8Array {\n const rgb = image.data;\n const bgr = new Uint8Array(rgb.length);\n for (let i = 0; i < rgb.length; i += 3) {\n bgr[i] = rgb[i + 2] as number;\n bgr[i + 1] = rgb[i + 1] as number;\n bgr[i + 2] = rgb[i] as number;\n }\n return bgr;\n}\n\nexport interface LetterboxResult {\n /** The padded image at the target size. */\n readonly image: RGBImage;\n /** The factor applied to the original image (`< 1` if downscaled). */\n readonly scale: number;\n /** Horizontal padding in pixels (left side; right side has the same or +1). */\n readonly padLeft: number;\n /** Vertical padding in pixels (top side). */\n readonly padTop: number;\n}\n\n/**\n * Resize preserving aspect ratio, padding to `(targetWidth, targetHeight)`\n * with a constant fill color.\n *\n * Standard YOLO preprocessing — returning `scale` and `padLeft`/`padTop`\n * lets callers map detections back to the original image coordinates.\n */\nexport function letterbox(\n image: RGBImage,\n targetWidth: number,\n targetHeight: number,\n fill: readonly [number, number, number] = [114, 114, 114],\n): LetterboxResult {\n const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n const newW = Math.round(image.width * scale);\n const newH = Math.round(image.height * scale);\n const resized = resize(image, newW, newH);\n\n const out = new Uint8Array(targetWidth * targetHeight * 3);\n const f0 = fill[0];\n const f1 = fill[1];\n const f2 = fill[2];\n for (let i = 0; i < out.length; i += 3) {\n out[i] = f0;\n out[i + 1] = f1;\n out[i + 2] = f2;\n }\n\n const padLeft = Math.floor((targetWidth - newW) / 2);\n const padTop = Math.floor((targetHeight - newH) / 2);\n const rowBytes = newW * 3;\n for (let y = 0; y < newH; y++) {\n const srcOffset = y * rowBytes;\n const dstOffset = ((padTop + y) * targetWidth + padLeft) * 3;\n out.set(resized.data.subarray(srcOffset, srcOffset + rowBytes), dstOffset);\n }\n\n return {\n image: new RGBImage(out, targetWidth, targetHeight),\n scale,\n padLeft,\n padTop,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
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(!
|
|
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)return;let i=r.path?` in ${r.path}`:``,a=r.classes===void 0?``:` among classes [${[...r.classes].sort((e,t)=>e-t).join(`, `)}]`;throw new e.NoDetectionsError(`No detections${i}${a}: 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":["/** @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,
|
|
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,CACJ,GAAI,CAAC,EAAQ,cAAgB,EAAQ,EAAG,OACxC,IAAM,EAAQ,EAAQ,KAAO,OAAO,EAAQ,OAAS,GAC/C,EACF,EAAQ,UAAY,IAAA,GACd,GACA,mBAAmB,CAAC,GAAG,EAAQ,OAAO,CAAC,CAAC,MAAM,EAAG,IAAM,EAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,GACnF,MAAM,IAAI,EAAA,kBACN,gBAAgB,IAAQ,EAAS,kCAAkC,EAAgB,EAAQ,aAAa,EAAE,EAC9G,CACJ"}
|
|
@@ -13,7 +13,9 @@ function n(e) {
|
|
|
13
13
|
return e.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
|
|
14
14
|
}
|
|
15
15
|
function r(t, r) {
|
|
16
|
-
if (!
|
|
16
|
+
if (!r.raiseOnEmpty || t > 0) return;
|
|
17
|
+
let i = r.path ? ` in ${r.path}` : "", a = r.classes === void 0 ? "" : ` among classes [${[...r.classes].sort((e, t) => e - t).join(", ")}]`;
|
|
18
|
+
throw new e(`No detections${i}${a}: nothing cleared confThreshold=${n(r.confThreshold)}.`);
|
|
17
19
|
}
|
|
18
20
|
//#endregion
|
|
19
21
|
export { t as VisionTask, r as requireDetections };
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;CACJ,IAAI,CAAC,EAAQ,gBAAgB,IAAQ,GAAG;CACxC,IAAM,IAAQ,EAAQ,OAAO,OAAO,EAAQ,SAAS,IAC/C,IACF,EAAQ,YAAY,KAAA,IACd,KACA,mBAAmB,CAAC,GAAG,EAAQ,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;CACnF,MAAM,IAAI,EACN,gBAAgB,IAAQ,EAAS,kCAAkC,EAAgB,EAAQ,aAAa,EAAE,EAC9G;AACJ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../core/timing.cjs"),t=require("../results.cjs"),n=require("../labels.cjs"),r=require("../core/graph.cjs"),i=require("../core/metadata.cjs"),a=require("../core/session.cjs"),o=require("../io/image.cjs"),s=require("../preprocess/image.cjs"),c=require("../postprocess/classification.cjs"),l=require("./base.cjs");var u=[.485,.456,.406],d=[.229,.224,.225],f=class f extends l.VisionTask{_labels;_names;_inputSize;_mean;_std;_applySoftmax;constructor(e,t,n,r,i,a,o){super(e),this._labels=t,this._names=n,this._inputSize=r,this._mean=i,this._std=a,this._applySoftmax=o}static async create(e,t={}){let o=await a.OrtSession.create(e,t),s=t.numClasses??r.classificationNumClasses(o.outputShape)??void 0,c=n.resolveLabels(t.labels??i.modelNames(o.metadata),{numClasses:s}),l={};for(let e=0;e<c.length;e++)l[e]=c[e];return new f(o,c,l,r.resolveInputSize({graphShape:o.inputShape,requested:t.inputSize,fallback:[224,224]}),t.mean??u,t.std??d,t.applySoftmax??!0)}get labels(){return this._labels}get names(){return this._names}get inputSize(){return this._inputSize}get numClasses(){return this._labels.length}async call(e,t={}){return this.predict(e,t)}async predict(n,r={}){let i=new e.SpeedTimer,a=typeof n==`string`?n:null,s=await o.loadImage(n);i.stage(`load`);let l=this._preprocess(s);i.stage(`preprocess`);let u=await this._session.run({[this._session.inputName]:l});i.stage(`inference`);let d=this._session.outputNames[0];if(d===void 0)throw Error(`Classifier model has no outputs.`);let f=u[d];if(f===void 0)throw Error(`Classifier model output ${d} missing from run() result.`);let p=this._postprocess(f.data),{indices:m,values:h}=c.topK(p,r.topK??null),g=[];for(let e=0;e<m.length;e++){let t=m[e],n=this._labels[t]??`class_${t}`;g.push({classId:t,className:n,probability:h[e],cls:t,name:n,conf:h[e]})}if(g.length===0)throw Error(`Classifier produced no probabilities (empty output).`);let _=g[0],v={classId:_.classId,className:_.className,confidence:_.probability,cls:_.classId,name:_.className,conf:_.probability,image:s,probabilities:g},y=[s.height,s.width],b=new t.Probs(p);return i.stage(`postprocess`),[new t.ClassificationResults(b,v,this._names,s,y,a,i.speed())]}_preprocess(e){let[t,n]=this._inputSize,r=s.resize(e,t,n)
|
|
1
|
+
const e=require("../core/timing.cjs"),t=require("../results.cjs"),n=require("../labels.cjs"),r=require("../core/graph.cjs"),i=require("../core/metadata.cjs"),a=require("../core/session.cjs"),o=require("../io/image.cjs"),s=require("../preprocess/image.cjs"),c=require("../postprocess/classification.cjs"),l=require("./base.cjs");var u=[.485,.456,.406],d=[.229,.224,.225],f=class f extends l.VisionTask{_labels;_names;_inputSize;_mean;_std;_applySoftmax;constructor(e,t,n,r,i,a,o){super(e),this._labels=t,this._names=n,this._inputSize=r,this._mean=i,this._std=a,this._applySoftmax=o}static async create(e,t={}){let o=await a.OrtSession.create(e,t),s=t.numClasses??r.classificationNumClasses(o.outputShape)??void 0,c=n.resolveLabels(t.labels??i.modelNames(o.metadata),{numClasses:s}),l={};for(let e=0;e<c.length;e++)l[e]=c[e];return new f(o,c,l,r.resolveInputSize({graphShape:o.inputShape,requested:t.inputSize,fallback:[224,224]}),t.mean??u,t.std??d,t.applySoftmax??!0)}get labels(){return this._labels}get names(){return this._names}get inputSize(){return this._inputSize}get numClasses(){return this._labels.length}async call(e,t={}){return this.predict(e,t)}async predict(n,r={}){let i=new e.SpeedTimer,a=typeof n==`string`?n:null,s=await o.loadImage(n);i.stage(`load`);let l=this._preprocess(s);i.stage(`preprocess`);let u=await this._session.run({[this._session.inputName]:l});i.stage(`inference`);let d=this._session.outputNames[0];if(d===void 0)throw Error(`Classifier model has no outputs.`);let f=u[d];if(f===void 0)throw Error(`Classifier model output ${d} missing from run() result.`);let p=this._postprocess(f.data),{indices:m,values:h}=c.topK(p,r.topK??null),g=[];for(let e=0;e<m.length;e++){let t=m[e],n=this._labels[t]??`class_${t}`;g.push({classId:t,className:n,probability:h[e],cls:t,name:n,conf:h[e]})}if(g.length===0)throw Error(`Classifier produced no probabilities (empty output).`);let _=g[0],v={classId:_.classId,className:_.className,confidence:_.probability,cls:_.classId,name:_.className,conf:_.probability,image:s,probabilities:g},y=[s.height,s.width],b=new t.Probs(p);return i.stage(`postprocess`),[new t.ClassificationResults(b,v,this._names,s,y,a,i.speed())]}_preprocess(e){let[t,n]=this._inputSize,r=s.resize(e,t,n),i=s.normalize(r,this._mean,this._std),a=s.toCHW(i,r.width,r.height,3);return s.toFloat32Tensor(a,[1,3,r.height,r.width])}_postprocess(e){return this._applySoftmax?c.softmax(e):new Float32Array(e)}};exports.Classifier=f;
|
|
2
2
|
//# sourceMappingURL=classifier.cjs.map
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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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"}
|
|
@@ -88,8 +88,8 @@ var g = [
|
|
|
88
88
|
return a.stage("postprocess"), [new t(x, y, this._names, s, b, o, a.speed())];
|
|
89
89
|
}
|
|
90
90
|
_preprocess(e) {
|
|
91
|
-
let [t, n] = this._inputSize, r = u(e, t, n);
|
|
92
|
-
return f(
|
|
91
|
+
let [t, n] = this._inputSize, r = u(e, t, n), i = l(r, this._mean, this._std), a = d(i, r.width, r.height, 3);
|
|
92
|
+
return f(a, [
|
|
93
93
|
1,
|
|
94
94
|
3,
|
|
95
95
|
r.height,
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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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"}
|
|
@@ -1,2 +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
|
|
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 r=this._spec.applySoftmax?u.softmax(e):e,{indices:i,values:a}=u.topK(r,n??null),o=[];for(let e=0;e<i.length;e++){let t=i[e]??0,n=a[e]??0,r=this._classifierLabels[t]??`class_${t}`;o.push({classId:t,className:r,probability:n,cls:t,name:r,conf:n})}let s=o[0]??{classId:0,className:`class_0`,probability:0,cls:0,name:`class_0`,conf:0};return{classId:s.classId,className:s.className,confidence:s.probability,cls:s.classId,name:s.className,conf:s.probability,image:t,probabilities:o}}};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){let t=c.toCHW(c.toFloat32(e),e.width,e.height,3);return c.toFloat32Tensor(t,[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
2
|
//# sourceMappingURL=detectClassify.cjs.map
|