Skip to content

v7.1.0rc1

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 12:37
f8422a3

Added

  • Expanded the Settings dialog with a scrollable page of workflow-oriented groups, an icon-labeled section index for quick navigation, and explanatory descriptions, so that auto-save, saving image data, keep-previous annotation/zoom/brightness-contrast, fill-drawing, label sorting/completion/text-field behavior, and the default AI model can all be changed in-app with immediate apply, instead of requiring hand-editing the config file (#2403)

Changed

  • Changed the Settings dialog to keep a stable, resizable window size, with scrolling when the available height cannot fit its content (#2403)
  • Grouped Shape coloring under one shape_color setting with explicit auto, uniform, and by_label modes, replacing the loosely coupled default_shape_color, shift_auto_shape_color, and label_colors keys. Existing Config Files and inline --config values are migrated in memory, preserving their behavior and override precedence (#2426)
  • Replaced the zoom control's "What's This" help with a plain hover tooltip naming the Ctrl+Wheel canvas zoom shortcut. The old text was reachable only by giving the toolbar zoom box keyboard focus and pressing Shift+F1 (no menu entry, no ? button), and the zoom key bindings it listed are already shown next to Zoom In/Zoom Out in the View menu (#2443)
  • Changed the release workflow to publish PEP 440 prerelease tags to PyPI with the current Unreleased notes and mark their GitHub releases as prereleases, while stable tags continue to use their exact version sections (#2469)

Removed

  • Removed the logger_level config key, which had no effect: log verbosity has always been controlled solely by the --logger-level CLI flag. A logger_level entry remaining in an existing ~/.labelmerc is dropped on load, so old config files keep working unchanged (#2402)

Fixed

  • Fixed clicking or hovering near a linestrip's unrendered "closing" line (the straight path from its last point back to its first) being treated as a hit on the shape; edge hover, add-point-to-edge, and body selection now ignore that phantom segment, since a linestrip is an open polyline and never draws it (#2307)
  • Fixed the --output guard rejecting only lowercase .json paths; an upper- or mixed-case file path such as --output notes.JSON slipped past the "expects a directory" check and was treated as an output directory. The guard now reuses the canonical case-insensitive is_label_file_path helper (#2317)
  • Fixed read_label_file accepting boolean values where a shape's group_id or point coordinates were expected in an annotation file; because bool is a subclass of int, a hand-edited or third-party "group_id": true (or a true/false inside points) slipped past the int/number checks and loaded as a group identifier or coordinate, so booleans are now rejected with the same clear read error as any other bad value (#2323)
  • Fixed the AI-model download progress dialog formatting sizes incorrectly: multi-GB models (e.g. SAM ~1.7 GB) showed as thousands of MB, and byte counts just under a unit boundary rolled up to 1024 KB/1024.0 MB instead of 1.0 MB/1.0 GB; sizes now use a GB tier and rounding-safe unit boundaries (#2324)
  • Fixed shapes_to_label mishandling a mask shape whose bounding box extends past the image edge; a negative corner silently wrapped the patch onto the opposite edge and a right/bottom overflow raised a ValueError broadcast error, so the destination rectangle (and matching sub-slice of the mask) is now clipped to the image canvas, as ADR 0004 requires for out-of-bounds points (#2327)
  • Fixed the application window/taskbar icon silently falling back to a blank icon; the startup call still requested icons/icon.png, which was removed when its PyInstaller-hostile symlink was deleted, so it now loads the real icons/icon-256.png (matching the documented PyInstaller build), and the new_icon tests now assert the icon is non-null so a missing icon file fails loudly (#2338)
  • Fixed a crash when opening a palette-mode (P/PA) image, such as a GIF, palette BMP/PNG, or palette TIFF whose bytes need re-encoding (any non-jpg/png extension, or an EXIF-oriented file); the re-encode path picked a format Pillow cannot write the palette mode in (OSError: cannot write mode P as JPEG / cannot write mode PA as PNG), so every such image crashed. A non-transparent palette image is now converted to RGB before the JPEG save, a P image carrying index-based transparency is routed to PNG so its transparency is preserved, and a PA image (palette + alpha) is converted to RGBA before the PNG save (#2340)
  • Fixed the outline of a Mask shape being drawn one pixel down-and-right of its filled pixels; the contour is traced on a 1-pixel-padded copy of the mask (so a region touching the border still closes), but that padding offset was never subtracted before positioning the stroke, unlike the polygon path that shares the same trick, so the outline now aligns with the fill it encloses (#2341)
  • Fixed a startup crash (OSError: [Errno 36] File name too long) when a --labels, --flags, --label-flags, or --config value is longer than the filesystem's filename limit (reachable with a few dozen inline comma-separated labels); these options probe whether the value names an existing file via Path(value).is_file(), which raised instead of returning False on an over-length value, so the value is now treated as inline data as intended (#2345)
  • Fixed the config labels key silently accepting a scalar string such as labels: cat instead of a list; the value was truthy and passed the duplicate check, so config["labels"] became the string "cat" and was later iterated character by character (c, a, t). A non-list labels value now surfaces as a clear configuration error instead (#2348)
  • Fixed a crash when a label_flags config entry contains a pattern that is not a usable regular expression, either an invalid one (e.g. person-() or a non-string one (e.g. the unquoted numeric key in 2024: [occluded], which YAML parses as an int); such a pattern raised an uncaught re.error or TypeError when loading a labeled shape or typing in the label dialog, and is now skipped instead, with a warning logged naming the offending pattern (#2350)
  • Fixed a non-string ai.default (e.g. ai:\n default: true) making the whole config unloadable: the old-model-name migration passed the value straight to re.match, raising TypeError: expected string or bytes-like object, so the config-error backstop discarded every other setting in the file and fell back to defaults. The migration now only runs on a string value, matching the shortcuts guard beside it, so the rest of the config is honored and an unusable ai.default degrades to the AI model widget's existing logged warning (#2358)
  • Fixed Delete File and the Delete-File action state ignoring where the annotation actually lives; current_label_file_path always recomputed an image-adjacent .json path, so with an output directory set (--output / Change Output Dir) the action could stay wrongly disabled or delete a stale image-adjacent file while leaving the saved annotation untouched. It now returns the loaded/saved label file, falling back to the output-dir-aware _resolve_label_path when none exists yet (#2360)
  • Fixed unsaved annotations being discarded when the user chose "Save" in the close/switch prompt but the save did not complete (a cancelled Save-As dialog, or a failed write); the app now only proceeds when the file is actually clean, so it keeps the window open instead of silently losing the annotations (#2361)
  • Fixed a shape vertex dragged out past an image corner staying frozen at the corner's x when the cursor kept moving sideways above or below the image; with out-of-bounds points disabled (the default) it now slides along the top or bottom edge under the cursor, because the out-of-bounds clip picks the edge from the axis the drag actually exits through rather than from the vertex's corner position (#2364)
  • Fixed the configured ai.default model not being applied at startup when it resolves to the first list entry, i.e. when it is set to EfficientSam (speed) or to an unrecognized value (which falls back to that entry): the AI-Assisted Annotation panel only pushed its selection to the canvas on currentIndexChanged, which never fires for the already-selected index 0, so the panel showed the chosen model while the canvas silently kept the hardcoded sam2:latest until the model was toggled by hand. The canvas is now initialized from the panel's resolved selection (model and output format) instead of waiting for a change signal (#2403) (#2370)
  • Fixed read_label_file accepting a non-integer top-level imageHeight or imageWidth in an annotation file; the dimension check compared with !=, so a boolean true/false (which subclasses int) or a float slipped through whenever it happened to equal the real dimension, and now these fields are validated as int and rejected with a clear read error (#2374)
  • Fixed a naturally-spaced --labels/--flags comma list such as --labels "cat, dog, person" registering labels with leading spaces (" dog", " person"); the inline comma-split branch now strips whitespace around each entry and drops blank entries, matching the file-reading branch's existing convention, so a later --validate-label exact no longer rejects "dog" because the registered label was actually " dog" (#2383)
  • Fixed a startup crash when loading the config raised anything other than ValueError, such as a malformed ~/.labelmerc or --config file with ungrammatical YAML (a yaml parser error); MainWindow._load_config caught only ValueError, so every other error crashed before the window opened. It now catches any such error, surfaces it in the configuration-error dialog (with an Ignore-and-use-defaults option), and falls back to defaults (#2384)
  • Fixed a pre-6.1.0 config file triggering the "Unexpected key in config" configuration-error dialog on startup because of the canvas.crosshair.ai_polygon / canvas.crosshair.ai_mask keys, which were consolidated into canvas.crosshair.ai_points_to_shape in v6.1.0; the legacy keys are now migrated during config loading (folded into ai_points_to_shape as the logical OR of the two old values, with an explicit ai_points_to_shape taking precedence) like the other renamed keys (#2391)
  • Fixed the app crashing when saving a label file failed on a raw filesystem error rather than a wrapped LabelFileError; save_labels created the output directory (Path.mkdir) and computed the image's relative path inside its try but caught only LabelFileError, so a read-only or full --output directory (PermissionError/OSError) or another raw ValueError escaped uncaught and took the whole app down through the global exception hook, including during auto-save. These are now caught like the existing write failures, surfacing the save-error dialog and returning False (#2393)
  • Fixed labelme --logger-level fatal crashing on startup with an unhandled ValueError: Level 'FATAL' does not exist; fatal was an advertised --logger-level choice but loguru has no such level, so the value was replaced with loguru's real critical level (matching the QtFatalMsg -> "CRITICAL" mapping already used for Qt logging) (#2399)
  • Fixed the Zoom In and Zoom Out toolbar/menu icons being swapped: Zoom In (which increases the zoom level) showed a magnifier with a minus glyph and Zoom Out (which decreases it) showed a magnifier with a plus glyph, backwards from convention and from what the actions do; the two icons are now assigned to match their actions (#2401)
  • Fixed the Brightness/Contrast dialog's Brightness: and Contrast: slider labels rendering in English under every one of the 20 bundled locales, even though the dialog's own title was translated; the two labels reached self.tr() through a loop variable instead of as string literals, and pyside6-lupdate only extracts literals, so neither string was ever written into a translation catalog. They are now literal self.tr(...) calls and are translated for all 20 locales, and the two slider rows moved to a grid layout so a longer translated label sizes the column instead of being clipped by the previous hardcoded 75px label width (#2405)
  • Fixed opening an image too large for Qt to decode reporting the misleading "Allowed formats" unsupported-format message; the dialog now states that the image is too large, shows its pixel dimensions and the ceiling that was actually hit (the decode allocation limit, or the raster engine's ~32767 pixel per-side limit, which no amount of raising the allocation limit can lift), and suggests tiling with gdal_retile.py or opening a smaller copy (#2417)
  • Fixed labelme refusing to start (exiting with status 1 and Config file does not exist) when ~/.labelmerc does not exist and could not be created, such as on a read-only or otherwise unwritable home directory; the auto-discovered config path was the default value of --config, so a missing one was treated like an explicitly requested file that is missing. A missing file is now fatal only when it was explicitly passed via --config, while a missing default path logs a warning and starts on the built-in default settings (#2421)
  • Fixed a config file that carries both an old polygon-named shortcut and its renamed replacement (such as edit_polygon alongside edit_shape) triggering the "Unexpected key in config" configuration-error dialog on startup; the polygon -> shape shortcut migration renamed an old key only when the new key was absent, so in the both-present case the stale key survived the migration and the whole config was then rejected in favor of the defaults, discarding every other setting in the file. The stale key is now always dropped, an existing new key still wins, and the discarded binding is logged so it is visible (#2423)
  • Fixed the label dialog silently discarding a shape flag's checked state when two label_flags patterns matching the same label both name that flag (for example a catch-all ".*": [occluded] alongside "^cat$": [occluded, urgent]); the dialog built one checkbox per pattern match rather than per flag, so the duplicate boxes overwrote each other on OK and the user's tick was lost. Each flag now gets exactly one checkbox, following the same keyed-by-flag-name dedup the annotation-loading path already applies to these patterns (#2424)
  • Fixed a startup crash (PermissionError) when the log file could not be set up, such as a read-only home directory in a container where ~/.cache cannot be created, or an existing but unwritable ~/.cache/labelme; the log file is now best-effort, so a failure to resolve the cache directory (including an unset LOCALAPPDATA on Windows, or a home directory that cannot be determined at all), create it, or register the file sink logs a warning and labelme keeps starting with the stderr logging that is already in place (#2425)
  • Fixed the label dialog silently clearing the ticked label flags whenever the label text is edited. The checked state lived only in the checkbox widgets, which are destroyed and rebuilt on every keystroke, so any intermediate text matching no label_flags pattern lost it for good. Because the dialog selects the existing label on open, the first keystroke replaces the whole text and drops it through such an intermediate: retyping the same label, or changing it to another label the same pattern covers, came back with every flag unticked. The checked state is now remembered per flag key for the lifetime of one popup and restored whenever that key reappears, while still resetting between popups (#2428)
  • Fixed the label dialog's whole flag area disappearing whenever the checkboxes were rebuilt while the dialog was open, such as picking another label in the dialog's label list or editing the label text; the flags stayed set but could neither be seen nor edited for the rest of the popup. The flag area was sized from its container's layout, which reports an empty size for the checkboxes added while the dialog is visible (they stay hidden until the event loop next activates the layout), so the area was pinned to zero height. The checkboxes are now shown as they are added, so the size is measured from the real content (#2428)
  • Fixed the label popup opening over a stale canvas after an AI-Box annotation, so the shape being labeled was invisible: the canvas still showed the drag bbox rubber band instead of the segmentation result, because the newly committed shape was only scheduled for repaint after the modal dialog had already taken over. The canvas now paints the committed shape before notifying, so the dialog opens on top of the annotation it is asking about (#2429)
  • Fixed the arrow keys navigating only a single file in the File List: loading an image always moved keyboard focus to the canvas, so the keypress after the first was delivered to the canvas and the selection stopped moving. A load now leaves the keyboard in the File List whenever the File List is what has it, so the arrow keys walk the list as expected; loading from anywhere else (opening a file or directory, or the A/D shortcuts while the canvas has focus) still hands the canvas the keyboard as before (#2434)
  • Fixed a selected label in the Annotation List rendering white-on-pale-gray, and so being unreadable, whenever the list did not hold keyboard focus (most commonly right after selecting a shape on the canvas, which leaves focus on the canvas). The custom HTML delegate bypassed Qt's text renderer and hardcoded the palette's Active group. Labels are now stored as plain text and painted through Qt's stock item-view style, and the delegate itself draws only the trailing label-color dot. This preserves the dot's position after the label and lets Qt handle focused, unfocused, disabled, light-theme, and dark-theme text colors (#2436)
  • Fixed AI-Points mode allowing SAM3 to start unsupported point-prompt inference, which wasted time extracting image features before failing and displayed the prompt draft as a prediction (#2437)
  • Fixed AI Assist interactions appearing to return nothing when every predicted Shape matched an existing Shape. Predictions now become new Shapes by default. The new disabled-by-default Existing Shape Suppression Setting can instead highlight matching existing Shapes while adding unmatched predictions normally. Point prompts choose the candidate that best satisfies their positive and negative points (#2444)
  • Fixed AI-Points Prompt Compatibility checks depending on mode navigation, which missed incompatible runtime states caused by startup, restored state, or Settings changes. AI-Points now keeps the selected model Setting and rejects an unsupported SAM3 point prompt before model download or inference (#2448)
  • Fixed Mask Shape construction for Model Session detections with fractional bounding boxes by using the same rounding for Shape points and Mask extents, preventing placement drift and Existing Shape Suppression errors (#2464)
  • Fixed AI Assist and AI Text Prompt passing images to vision models in BGR channel order, which swapped red and blue. Qt images are now converted to RGB before inference (#2466)
  • Fixed a failed Image load blanking the current session; the last good Image, Annotation, canvas, and File List selection now stay active, and an invalid adjacent Annotation File still blocks its Image from opening (#2454) (#2468)
  • Fixed failed auto-saves leaving an edited Annotation marked clean. The dirty title, Save action, and unsaved-changes prompt now remain active, while repeated failures for the same target show only one error until a save succeeds or the target changes (#2472)
  • Fixed malformed Annotation Files with unsupported Shape types, invalid geometry, or inconsistent Mask data reaching GUI Shape construction and causing an application failure. The reader now rejects the full Annotation before installing any Shapes and reports the file plus the indexed field that failed validation (#2473)
  • Fixed File List search rescanning the directory and changing the active Image when the search text changed. Search now filters the loaded Images in memory, so a dirty Annotation stays active without a save or discard prompt, and clearing the search restores the full File List and its active-Image selection (#2474)
  • Fixed enabling auto-save on an already modified Annotation leaving the window dirty after the next successful auto-save, which kept the Save action and modified title marker active and prompted to save again when closing (#2475)
  • Fixed whole-Shape dragging and keyboard nudging that used stale mouse and drag-anchor state. Clickless selections now move in every direction and stop at the Image bounds, oversized Shapes use symmetric bounds instead of reversing direction, and degenerate oriented-rectangle corner drags stay inside the Image when out-of-bounds points are disabled (#2398, #2375, #2365) (#2476)
  • Fixed failed Annotation File saves truncating the last good file. Saves now write and close a temporary file in the target directory before replacing the destination, and failed saves remove the temporary file (#2477)
  • Fixed a cancelled close still overwriting the Window State (window size, position, and dock layout); closeEvent ignored the close event but kept going, so cancelling the unsaved-changes prompt saved the current geometry anyway and the next session started from a layout the user never closed on. The Window State is now written only when the close goes through (#2478)
  • Fixed Keep Previous Zoom preserving the scale while resetting the viewport position on each newly opened image. It now carries the previous horizontal and vertical scroll positions forward, while still restoring an image's own saved viewport when revisiting it (#2484)
  • Fixed saving an annotation failing with an error dialog on Windows when the image and the label file live on different drives, because no relative imagePath exists between two drives. Such a save now stores an absolute imagePath, which reopens on the machine that wrote it but does not survive moving the files elsewhere; every other save keeps the relative imagePath (#1350) (#2496)
  • Fixed dropped image files entering the File List with forward slashes on Windows; QUrl reports a dropped path with forward slashes while every other path in the File List carries the separator of the platform, so the same image could be listed twice once its directory was also opened (#2497)
  • Fixed images opened through the file dialog on Windows neither selecting their File List row nor receiving the saved checkmark; Qt file dialogs report a chosen path with forward slashes while the File List carries the separator of the platform, and both lookups compare exact strings (#2499)
  • Fixed exported Mask Shapes with fractional bounds being shifted by integer truncation instead of matching their canvas position (#2504)
  • Fixed AI Assist and AI Text Prompt oriented-rectangle Shapes extending beyond the Image when out-of-bounds points are disabled. Edge-crossing fits now use an in-bounds axis-aligned rectangle, while enabling out-of-bounds points preserves the original vertices (#2512) (#2506)