Buckets:
| { | |
| "cells": [ | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "5d0e0b69", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# Copyright (c) Meta Platforms, Inc. and affiliates." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "11912666", | |
| "metadata": {}, | |
| "source": [ | |
| "# <a target=\"_blank\" href=\"https://colab.research.google.com/github/facebookresearch/sam3/blob/main/notebooks/sam3_image_interactive.ipynb\">\n", | |
| "# <img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/>\n", | |
| "# </a>" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "8517f5f6", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "using_colab = False" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "2540e376", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "if using_colab:\n", | |
| " import torch\n", | |
| " import torchvision\n", | |
| " print(\"PyTorch version:\", torch.__version__)\n", | |
| " print(\"Torchvision version:\", torchvision.__version__)\n", | |
| " print(\"CUDA is available:\", torch.cuda.is_available())\n", | |
| " import sys\n", | |
| " !{sys.executable} -m pip install opencv-python matplotlib scikit-learn\n", | |
| " !{sys.executable} -m pip install 'git+https://github.com/facebookresearch/sam3.git'" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "id": "90073483-58f6-404e-90ac-c22efcd76216", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "%matplotlib widget" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "id": "13325376-658b-48d6-8528-2a006f223d44", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import torch\n", | |
| "# turn on tfloat32 for Ampere GPUs\n", | |
| "# https://pytorch.org/docs/stable/notes/cuda.html#tensorfloat-32-tf32-on-ampere-devices\n", | |
| "torch.backends.cuda.matmul.allow_tf32 = True\n", | |
| "torch.backends.cudnn.allow_tf32 = True\n", | |
| "\n", | |
| "# use bfloat16 for the entire notebook. If your card doesn't support it, try float16 instead\n", | |
| "torch.autocast(\"cuda\", dtype=torch.bfloat16).__enter__()\n", | |
| "\n", | |
| "# inference mode for the whole notebook. Disable if you need gradients\n", | |
| "torch.inference_mode().__enter__()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "fb863772-56a9-4ee2-be52-5d8933066519", | |
| "metadata": {}, | |
| "source": [ | |
| "# Load the model" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "id": "f84b4ccc-9db2-4d88-ac8f-4c272694d25a", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import sam3\n", | |
| "from sam3 import build_sam3_image_model\n", | |
| "import os\n", | |
| "sam3_root = os.path.join(os.path.dirname(sam3.__file__), \"..\")\n", | |
| "bpe_path = f\"{sam3_root}/assets/bpe_simple_vocab_16e6.txt.gz\"" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "id": "de01a36e-1221-4497-a5ab-e6c796689480", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "model = build_sam3_image_model(bpe_path=bpe_path)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "id": "b01ec8a9-d9f6-4baf-96ac-1e5d21fd90b8", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "from sam3.model.sam3_image_processor import Sam3Processor\n", | |
| "processor = Sam3Processor(model)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "e6172a69-35ca-487c-bd67-6f1f1ecb20d5", | |
| "metadata": {}, | |
| "source": [ | |
| "# Jupyter widget" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "id": "2a4ac22f-5d5c-4272-a5a1-dfe0c04253a7", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "import io\n", | |
| "\n", | |
| "import ipywidgets as widgets\n", | |
| "import matplotlib.pyplot as plt\n", | |
| "import numpy as np\n", | |
| "import PIL.Image\n", | |
| "import requests\n", | |
| "from IPython.display import clear_output, display, HTML\n", | |
| "from matplotlib.patches import Rectangle\n", | |
| "\n", | |
| "\n", | |
| "class Sam3SegmentationWidget:\n", | |
| " \"\"\"Interactive Jupyter widget for SAM3 segmentation with text and box prompts.\"\"\"\n", | |
| "\n", | |
| " def __init__(self, processor):\n", | |
| " \"\"\"\n", | |
| " Initialize the segmentation widget.\n", | |
| "\n", | |
| " Args:\n", | |
| " processor: Sam3Processor instance\n", | |
| " \"\"\"\n", | |
| " self.processor = processor\n", | |
| " self.state = None\n", | |
| " self.current_image = None\n", | |
| " self.current_image_array = None\n", | |
| " self.box_mode = \"positive\"\n", | |
| " self.drawing_box = False\n", | |
| " self.box_start = None\n", | |
| " self.current_rect = None\n", | |
| "\n", | |
| " self._setup_ui()\n", | |
| " self._setup_plot()\n", | |
| "\n", | |
| " def _setup_ui(self):\n", | |
| " \"\"\"Set up the UI components.\"\"\"\n", | |
| " self.upload_widget = widgets.FileUpload(\n", | |
| " accept=\"image/*\", multiple=False, description=\"Upload Image\"\n", | |
| " )\n", | |
| " self.upload_widget.observe(self._on_image_upload, names=\"value\")\n", | |
| "\n", | |
| " self.url_input = widgets.Text(\n", | |
| " placeholder=\"Or enter image URL\",\n", | |
| " )\n", | |
| " self.url_button = widgets.Button(description=\"Load URL\", button_style=\"info\")\n", | |
| " self.url_button.on_click(self._on_load_url)\n", | |
| " url_box = widgets.HBox(\n", | |
| " [self.url_input, self.url_button],\n", | |
| " layout=widgets.Layout(width=\"100%\", justify_content=\"space-between\"),\n", | |
| " )\n", | |
| "\n", | |
| " self.text_input = widgets.Text(\n", | |
| " placeholder='Enter segmentation prompt (e.g., \"person\", \"dog\")',\n", | |
| " continuous_update=False,\n", | |
| " )\n", | |
| " self.text_input.observe(self._on_text_submit, names=\"value\")\n", | |
| " self.text_button = widgets.Button(description=\"Segment\", button_style=\"success\")\n", | |
| " self.text_button.on_click(self._on_text_prompt)\n", | |
| " text_box = widgets.HBox(\n", | |
| " [self.text_input, self.text_button],\n", | |
| " layout=widgets.Layout(width=\"100%\", justify_content=\"space-between\"),\n", | |
| " )\n", | |
| "\n", | |
| " self.box_mode_buttons = widgets.ToggleButtons(\n", | |
| " options=[\"Positive Boxes\", \"Negative Boxes\"],\n", | |
| " description=\"Box Mode:\",\n", | |
| " button_style=\"\",\n", | |
| " tooltips=[\n", | |
| " \"Draw boxes around objects to include\",\n", | |
| " \"Draw boxes around objects to exclude\",\n", | |
| " ],\n", | |
| " )\n", | |
| " self.box_mode_buttons.observe(self._on_box_mode_change, names=\"value\")\n", | |
| "\n", | |
| " self.clear_button = widgets.Button(\n", | |
| " description=\"Clear All Prompts\", button_style=\"warning\"\n", | |
| " )\n", | |
| " self.clear_button.on_click(self._on_clear_prompts)\n", | |
| "\n", | |
| " self.confidence_slider = widgets.FloatSlider(\n", | |
| " value=0.5,\n", | |
| " min=0.0,\n", | |
| " max=1.0,\n", | |
| " step=0.01,\n", | |
| " description=\"Confidence:\",\n", | |
| " continuous_update=False,\n", | |
| " style={\"description_width\": \"initial\"},\n", | |
| " )\n", | |
| " self.confidence_slider.observe(self._on_confidence_change, names=\"value\")\n", | |
| "\n", | |
| " self.size_slider = widgets.IntSlider(\n", | |
| " value=960,\n", | |
| " min=300,\n", | |
| " max=2000,\n", | |
| " step=10,\n", | |
| " description=\"Image Size:\",\n", | |
| " continuous_update=False,\n", | |
| " style={\"description_width\": \"initial\"},\n", | |
| " )\n", | |
| " self.size_slider.observe(self._on_size_change, names=\"value\")\n", | |
| "\n", | |
| " slider_box = widgets.HBox(\n", | |
| " [self.confidence_slider, self.size_slider],\n", | |
| " layout=widgets.Layout(justify_content=\"space-between\"),\n", | |
| " )\n", | |
| "\n", | |
| " self.output = widgets.Output()\n", | |
| " self.status_label = widgets.Label(value=\"Upload an image to begin\")\n", | |
| "\n", | |
| " # This box will hold our matplotlib output and we can target it with CSS.\n", | |
| " self.plot_container = widgets.Box([self.output])\n", | |
| " self.plot_container.add_class(\"no-drag\")\n", | |
| "\n", | |
| " # CSS to make the cursor a crosshair over the matplotlib canvas\n", | |
| " css_style = widgets.HTML(\n", | |
| " \"\"\"\n", | |
| " <style>\n", | |
| " .jupyter-matplotlib-canvas, canvas {\n", | |
| " cursor: crosshair !important;\n", | |
| " }\n", | |
| " </style>\n", | |
| " \"\"\"\n", | |
| " )\n", | |
| " # Create VBoxes for each accordion pane\n", | |
| " source_pane = widgets.VBox([self.upload_widget, url_box])\n", | |
| " prompt_pane = widgets.VBox(\n", | |
| " [\n", | |
| " widgets.Label(\"Text Prompt:\"),\n", | |
| " text_box,\n", | |
| " self.box_mode_buttons,\n", | |
| " self.confidence_slider,\n", | |
| " self.clear_button,\n", | |
| " ]\n", | |
| " )\n", | |
| " display_pane = widgets.VBox([self.size_slider])\n", | |
| "\n", | |
| " # Create the Accordion to hold the control panes\n", | |
| " self.accordion = widgets.Accordion(\n", | |
| " children=[source_pane, prompt_pane, display_pane]\n", | |
| " )\n", | |
| " self.accordion.set_title(0, \"Image Source\")\n", | |
| " self.accordion.set_title(1, \"Segmentation Prompts\")\n", | |
| " self.accordion.set_title(2, \"Display Settings\")\n", | |
| " self.accordion.selected_index = 0 # Start with the first pane open\n", | |
| "\n", | |
| " # Create the left sidebar for controls\n", | |
| " sidebar = widgets.VBox(\n", | |
| " [self.status_label, widgets.HTML(\"<h4>Controls</h4>\"), self.accordion]\n", | |
| " )\n", | |
| " sidebar.layout = widgets.Layout(\n", | |
| " width=\"380px\",\n", | |
| " min_width=\"380px\",\n", | |
| " max_width=\"380px\",\n", | |
| " border=\"1px solid #e0e0e0\",\n", | |
| " padding=\"10px\",\n", | |
| " margin=\"0 15px 0 0\",\n", | |
| " flex=\"0 0 auto\",\n", | |
| " )\n", | |
| "\n", | |
| " # Create the main area for the image display\n", | |
| " main_area = widgets.VBox([self.plot_container])\n", | |
| " main_area.layout = widgets.Layout(flex=\"1\", min_width=\"500px\", overflow=\"auto\")\n", | |
| "\n", | |
| " # Combine sidebar and main area into the final app layout\n", | |
| " app_layout = widgets.HBox([sidebar, main_area])\n", | |
| " app_layout.layout = widgets.Layout(\n", | |
| " width=\"100%\",\n", | |
| " display=\"flex\",\n", | |
| " flex_flow=\"row\",\n", | |
| " align_items=\"stretch\",\n", | |
| " )\n", | |
| "\n", | |
| " # Set the main container\n", | |
| " self.container = widgets.VBox(\n", | |
| " [\n", | |
| " css_style,\n", | |
| " widgets.HTML(\"<h3>🖼️ SAM3 Interactive Segmentation</h3>\"),\n", | |
| " app_layout,\n", | |
| " ]\n", | |
| " )\n", | |
| "\n", | |
| " def _setup_plot(self):\n", | |
| " \"\"\"Set up the matplotlib figure.\"\"\"\n", | |
| " # plt.ioff()\n", | |
| " self.fig, self.ax = plt.subplots(figsize=(12, 8))\n", | |
| " # plt.ion()\n", | |
| " self.ax.axis(\"off\")\n", | |
| " self.fig.subplots_adjust(left=0, right=1, top=1, bottom=0)\n", | |
| " self.fig.canvas.toolbar_visible = False\n", | |
| " self.fig.canvas.header_visible = False\n", | |
| " self.fig.canvas.footer_visible = False\n", | |
| " self.fig.canvas.resizable = False\n", | |
| "\n", | |
| " # plt.close(self.fig)\n", | |
| "\n", | |
| " def _set_loading(self, is_loading, message=\"Processing...\"):\n", | |
| " \"\"\"Show/hide loading state and disable/enable controls.\"\"\"\n", | |
| " if is_loading:\n", | |
| " self.status_label.value = f\"⏳ {message}\"\n", | |
| " self.upload_widget.disabled = True\n", | |
| " self.url_button.disabled = True\n", | |
| " self.text_button.disabled = True\n", | |
| " self.clear_button.disabled = True\n", | |
| " self.box_mode_buttons.disabled = True\n", | |
| " self.confidence_slider.disabled = True\n", | |
| " else:\n", | |
| " self.upload_widget.disabled = False\n", | |
| " self.url_button.disabled = False\n", | |
| " self.text_button.disabled = False\n", | |
| " self.clear_button.disabled = False\n", | |
| " self.box_mode_buttons.disabled = False\n", | |
| " self.confidence_slider.disabled = False\n", | |
| "\n", | |
| " def _on_image_upload(self, change):\n", | |
| " \"\"\"Handle image upload.\"\"\"\n", | |
| " if change[\"new\"]:\n", | |
| " uploaded_file = change[\"new\"][0]\n", | |
| " image = PIL.Image.open(io.BytesIO(uploaded_file[\"content\"])).convert(\"RGB\")\n", | |
| " self._set_image(image)\n", | |
| "\n", | |
| " def _on_load_url(self, button):\n", | |
| " \"\"\"Handle loading image from URL.\"\"\"\n", | |
| " url = self.url_input.value.strip()\n", | |
| " if not url:\n", | |
| " self.status_label.value = \"Please enter a URL\"\n", | |
| " return\n", | |
| "\n", | |
| " self._set_loading(True, \"Downloading image from URL...\")\n", | |
| "\n", | |
| " try:\n", | |
| " response = requests.get(url, timeout=10)\n", | |
| " response.raise_for_status()\n", | |
| " image = PIL.Image.open(io.BytesIO(response.content)).convert(\"RGB\")\n", | |
| " self._set_image(image)\n", | |
| " except Exception as e:\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f\"Error loading image: {str(e)}\"\n", | |
| "\n", | |
| " def _set_image(self, image):\n", | |
| " \"\"\"Set the current image, adjust figure size, and initialize state.\"\"\"\n", | |
| " self._set_loading(True, \"Processing image through model...\")\n", | |
| "\n", | |
| " try:\n", | |
| "\n", | |
| " self.current_image = image\n", | |
| " self.current_image_array = np.array(image)\n", | |
| " self.state = self.processor.set_image(image)\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = (\n", | |
| " f\"Image loaded: {image.size[0]}x{image.size[1]} pixels\"\n", | |
| " )\n", | |
| " self._resize_figure()\n", | |
| " self._update_display()\n", | |
| " self._connect_plot_events()\n", | |
| " self.accordion.selected_index = 1\n", | |
| " except Exception as e:\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f\"Error processing image: {str(e)}\"\n", | |
| "\n", | |
| " def _on_text_submit(self, change):\n", | |
| " \"\"\"Handle text prompt submission via Enter key.\"\"\"\n", | |
| " # Call the same handler as the button click\n", | |
| " self._on_text_prompt(None)\n", | |
| "\n", | |
| " def _on_text_prompt(self, button):\n", | |
| " \"\"\"Handle text prompt submission.\"\"\"\n", | |
| " if self.state is None:\n", | |
| " self.status_label.value = \"Please load an image first\"\n", | |
| " return\n", | |
| "\n", | |
| " prompt = self.text_input.value.strip()\n", | |
| " if not prompt:\n", | |
| " self.status_label.value = \"Please enter a prompt\"\n", | |
| " return\n", | |
| "\n", | |
| " self._set_loading(True, f'Segmenting with prompt: \"{prompt}\"...')\n", | |
| "\n", | |
| " try:\n", | |
| " self.state = self.processor.set_text_prompt(prompt, self.state)\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f'Segmented with prompt: \"{prompt}\"'\n", | |
| " self._update_display()\n", | |
| " except Exception as e:\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f\"Error: {str(e)}\"\n", | |
| "\n", | |
| " def _on_box_mode_change(self, change):\n", | |
| " \"\"\"Handle box mode toggle.\"\"\"\n", | |
| " self.box_mode = \"positive\" if change[\"new\"] == \"Positive Boxes\" else \"negative\"\n", | |
| "\n", | |
| " def _on_clear_prompts(self, button):\n", | |
| " \"\"\"Clear all prompts and reset to image only.\"\"\"\n", | |
| " if self.current_image is not None:\n", | |
| " try:\n", | |
| " self._set_loading(True, \"Clearing prompts and resetting...\")\n", | |
| " self.state = self.processor.reset_all_prompts(self.state)\n", | |
| " if \"prompted_boxes\" in self.state:\n", | |
| " del self.state[\"prompted_boxes\"]\n", | |
| " self.text_input.value = \"\"\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = \"Cleared all prompts\"\n", | |
| " self._update_display()\n", | |
| " except Exception as e:\n", | |
| " self._set_loading(False)\n", | |
| " import traceback\n", | |
| "\n", | |
| " self.status_label.value = f\"Error: {str(e)} {traceback.format_exc()}\"\n", | |
| "\n", | |
| " def _on_confidence_change(self, change):\n", | |
| " \"\"\"Handle confidence threshold change.\"\"\"\n", | |
| " if self.state is not None:\n", | |
| " self.state = self.processor.set_confidence_threshold(\n", | |
| " change[\"new\"], self.state\n", | |
| " )\n", | |
| " self._update_display()\n", | |
| "\n", | |
| " def _connect_plot_events(self):\n", | |
| " \"\"\"Connect matplotlib event handlers for box drawing.\"\"\"\n", | |
| " # Disable matplotlib's toolbar navigation to allow custom box drawing\n", | |
| " if hasattr(self.fig.canvas, \"toolbar\") and self.fig.canvas.toolbar is not None:\n", | |
| " self.fig.canvas.toolbar.pan()\n", | |
| " self.fig.canvas.toolbar.pan()\n", | |
| "\n", | |
| " self.fig.canvas.mpl_connect(\"button_press_event\", self._on_press)\n", | |
| " self.fig.canvas.mpl_connect(\"button_release_event\", self._on_release)\n", | |
| " self.fig.canvas.mpl_connect(\"motion_notify_event\", self._on_motion)\n", | |
| "\n", | |
| " def _on_press(self, event):\n", | |
| " \"\"\"Handle mouse press for box drawing.\"\"\"\n", | |
| " if event.inaxes != self.ax:\n", | |
| " return\n", | |
| " self.drawing_box = True\n", | |
| " self.box_start = (event.xdata, event.ydata)\n", | |
| "\n", | |
| " def _on_motion(self, event):\n", | |
| " \"\"\"Handle mouse motion for box preview.\"\"\"\n", | |
| " if not self.drawing_box or event.inaxes != self.ax or self.box_start is None:\n", | |
| " return\n", | |
| "\n", | |
| " if self.current_rect is not None:\n", | |
| " self.current_rect.remove()\n", | |
| "\n", | |
| " x0, y0 = self.box_start\n", | |
| " x1, y1 = event.xdata, event.ydata\n", | |
| " width = x1 - x0\n", | |
| " height = y1 - y0\n", | |
| "\n", | |
| " color = \"green\" if self.box_mode == \"positive\" else \"red\"\n", | |
| " self.current_rect = Rectangle(\n", | |
| " (x0, y0),\n", | |
| " width,\n", | |
| " height,\n", | |
| " fill=False,\n", | |
| " edgecolor=color,\n", | |
| " linewidth=2,\n", | |
| " linestyle=\"--\",\n", | |
| " )\n", | |
| " self.ax.add_patch(self.current_rect)\n", | |
| " self.fig.canvas.draw_idle()\n", | |
| "\n", | |
| " def _on_release(self, event):\n", | |
| " \"\"\"Handle mouse release to finalize box.\"\"\"\n", | |
| " if not self.drawing_box or event.inaxes != self.ax or self.box_start is None:\n", | |
| " self.drawing_box = False\n", | |
| " return\n", | |
| "\n", | |
| " self.drawing_box = False\n", | |
| "\n", | |
| " if self.current_rect is not None:\n", | |
| " self.current_rect.remove()\n", | |
| " self.current_rect = None\n", | |
| "\n", | |
| " if self.state is None:\n", | |
| " return\n", | |
| "\n", | |
| " x0, y0 = self.box_start\n", | |
| " x1, y1 = event.xdata, event.ydata\n", | |
| "\n", | |
| " x_min = min(x0, x1)\n", | |
| " x_max = max(x0, x1)\n", | |
| " y_min = min(y0, y1)\n", | |
| " y_max = max(y0, y1)\n", | |
| "\n", | |
| " if abs(x_max - x_min) < 5 or abs(y_max - y_min) < 5:\n", | |
| " return\n", | |
| "\n", | |
| " # Get image dimensions\n", | |
| " img_h = self.state[\"original_height\"]\n", | |
| " img_w = self.state[\"original_width\"]\n", | |
| "\n", | |
| " # Convert from xyxy pixel coordinates to cxcywh normalized format\n", | |
| " center_x = (x_min + x_max) / 2.0 / img_w\n", | |
| " center_y = (y_min + y_max) / 2.0 / img_h\n", | |
| " width = (x_max - x_min) / img_w\n", | |
| " height = (y_max - y_min) / img_h\n", | |
| "\n", | |
| " box = [center_x, center_y, width, height]\n", | |
| " label = self.box_mode == \"positive\"\n", | |
| " mode_str = \"positive\" if label else \"negative\"\n", | |
| "\n", | |
| " # Store the prompted box in pixel coordinates for display\n", | |
| " if \"prompted_boxes\" not in self.state:\n", | |
| " self.state[\"prompted_boxes\"] = []\n", | |
| " self.state[\"prompted_boxes\"].append(\n", | |
| " {\"box\": [x_min, y_min, x_max, y_max], \"label\": label}\n", | |
| " )\n", | |
| "\n", | |
| " self._set_loading(True, f\"Adding {mode_str} box and re-segmenting...\")\n", | |
| "\n", | |
| " try:\n", | |
| " self.state = self.processor.add_geometric_prompt(box, label, self.state)\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f\"Added {mode_str} box\"\n", | |
| " self._update_display()\n", | |
| " except Exception as e:\n", | |
| " self._set_loading(False)\n", | |
| " self.status_label.value = f\"Error adding box: {str(e)}\"\n", | |
| "\n", | |
| " def _resize_figure(self):\n", | |
| " \"\"\"Calculate and apply new figure size based on image and slider value.\"\"\"\n", | |
| " if self.current_image is None:\n", | |
| " return\n", | |
| "\n", | |
| " # 1. Get original image dimensions\n", | |
| " img_w, img_h = self.current_image.size\n", | |
| "\n", | |
| " # 2. The slider's value is now the direct target width for the display\n", | |
| " display_w = float(self.size_slider.value)\n", | |
| "\n", | |
| " # 3. Calculate the corresponding height to maintain the original aspect ratio\n", | |
| " aspect_ratio = img_h / img_w\n", | |
| " display_h = int(display_w * aspect_ratio)\n", | |
| "\n", | |
| " # 4. Convert pixel dimensions to inches for Matplotlib and apply\n", | |
| " dpi = self.fig.dpi\n", | |
| " new_figsize = (display_w / dpi, display_h / dpi)\n", | |
| " self.fig.set_size_inches(new_figsize, forward=True)\n", | |
| "\n", | |
| " def _on_size_change(self, change):\n", | |
| " \"\"\"Handle a change from the image size slider.\"\"\"\n", | |
| " if self.current_image is not None:\n", | |
| " self._resize_figure()\n", | |
| " # After resizing the canvas, we must redraw the content\n", | |
| " self._update_display()\n", | |
| "\n", | |
| " def _update_display(self):\n", | |
| " \"\"\"Update the display with current results.\"\"\"\n", | |
| " if self.current_image_array is None:\n", | |
| " return\n", | |
| "\n", | |
| " with self.output:\n", | |
| " clear_output(wait=True)\n", | |
| "\n", | |
| " self.ax.clear()\n", | |
| " self.ax.axis(\"off\")\n", | |
| " self.ax.imshow(self.current_image_array)\n", | |
| "\n", | |
| " if self.state is not None and \"masks\" in self.state:\n", | |
| " masks = self.state.get(\"masks\", [])\n", | |
| " boxes = self.state.get(\"boxes\", [])\n", | |
| " scores = self.state.get(\"scores\", [])\n", | |
| "\n", | |
| " if len(masks) > 0:\n", | |
| " mask_overlay = np.zeros((*self.current_image_array.shape[:2], 4))\n", | |
| "\n", | |
| " for i, (mask, box, score) in enumerate(zip(masks, boxes, scores)):\n", | |
| " mask_np = mask[0].cpu().numpy()\n", | |
| "\n", | |
| " color = plt.cm.tab10(i % 10)[:3]\n", | |
| " mask_overlay[mask_np > 0.5] = (*color, 0.5)\n", | |
| "\n", | |
| " x0, y0, x1, y1 = box.cpu().numpy()\n", | |
| " rect = Rectangle(\n", | |
| " (x0, y0),\n", | |
| " x1 - x0,\n", | |
| " y1 - y0,\n", | |
| " fill=False,\n", | |
| " edgecolor=color,\n", | |
| " linewidth=2,\n", | |
| " )\n", | |
| " self.ax.add_patch(rect)\n", | |
| "\n", | |
| " self.ax.text(\n", | |
| " x0,\n", | |
| " y0 - 5,\n", | |
| " f\"{score:.2f}\",\n", | |
| " color=\"white\",\n", | |
| " fontsize=10,\n", | |
| " bbox=dict(\n", | |
| " facecolor=color, alpha=0.7, edgecolor=\"none\", pad=2\n", | |
| " ),\n", | |
| " )\n", | |
| "\n", | |
| " self.ax.imshow(mask_overlay)\n", | |
| " self.status_label.value = f\"Found {len(masks)} object(s)\"\n", | |
| " else:\n", | |
| " self.status_label.value = (\n", | |
| " \"No objects found above confidence threshold\"\n", | |
| " )\n", | |
| "\n", | |
| " # Display prompted boxes with dashed lines\n", | |
| " if self.state is not None and \"prompted_boxes\" in self.state:\n", | |
| " for prompted_box in self.state[\"prompted_boxes\"]:\n", | |
| " box_coords = prompted_box[\"box\"]\n", | |
| " is_positive = prompted_box[\"label\"]\n", | |
| "\n", | |
| " x0, y0, x1, y1 = box_coords\n", | |
| " color = \"green\" if is_positive else \"red\"\n", | |
| "\n", | |
| " rect = Rectangle(\n", | |
| " (x0, y0),\n", | |
| " x1 - x0,\n", | |
| " y1 - y0,\n", | |
| " fill=False,\n", | |
| " edgecolor=color,\n", | |
| " linewidth=2,\n", | |
| " linestyle=\"--\",\n", | |
| " )\n", | |
| " self.ax.add_patch(rect)\n", | |
| "\n", | |
| " # display(self.fig.canvas)\n", | |
| "\n", | |
| " def display(self):\n", | |
| " display(self.container)\n", | |
| "\n", | |
| " # Add this for more convenient display in notebooks\n", | |
| " def _ipython_display_(self):\n", | |
| " self.display()\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "1b9bda74-b455-4957-9767-2a46a041b50f", | |
| "metadata": {}, | |
| "source": [ | |
| "# Run!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "id": "ebfb9b85-2318-4328-bb0e-e93e4a57fefe", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "ea0e04a1bfd7486b93baae650d87e0b2", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "text/plain": [ | |
| "VBox(children=(HTML(value='\\n <style>\\n .jupyter-matplotlib-canvas, canvas {\\n …" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| }, | |
| { | |
| "data": { | |
| "application/vnd.jupyter.widget-view+json": { | |
| "model_id": "bbdcb3374c29461bb379d4bf9c319a49", | |
| "version_major": 2, | |
| "version_minor": 0 | |
| }, | |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAYAAAAz4JsCAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFf1JREFUeJzt2DEBACAMwDDAv+fhgJceiYLe3TMzCwAAAACizu8AAAAAAHgxsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEi710EKPFzQ9BwAAAAASUVORK5CYII=", | |
| "text/html": [ | |
| "\n", | |
| " <div style=\"display: inline-block;\">\n", | |
| " <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n", | |
| " Figure\n", | |
| " </div>\n", | |
| " <img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAYAAAAz4JsCAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFf1JREFUeJzt2DEBACAMwDDAv+fhgJceiYLe3TMzCwAAAACizu8AAAAAAHgxsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEgzsAAAAABIM7AAAAAASDOwAAAAAEi710EKPFzQ9BwAAAAASUVORK5CYII=' width=1200.0/>\n", | |
| " </div>\n", | |
| " " | |
| ], | |
| "text/plain": [ | |
| "Canvas(footer_visible=False, header_visible=False, resizable=False, toolbar=Toolbar(toolitems=[('Home', 'Reset…" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "widget = Sam3SegmentationWidget(processor)\n", | |
| "widget.display()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "50a14560-573a-4784-9f55-689fda9147be", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3 (ipykernel)", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.12.11" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } | |
Xet Storage Details
- Size:
- 45.4 kB
- Xet hash:
- a7971358c7b3ee344ba82a83f7a51e4c276416770d4db59889342265bea30a26
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.