v7.1.0rc1
Pre-release
Pre-release
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_colorsetting with explicitauto,uniform, andby_labelmodes, replacing the loosely coupleddefault_shape_color,shift_auto_shape_color, andlabel_colorskeys. Existing Config Files and inline--configvalues 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+Wheelcanvas 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_levelconfig key, which had no effect: log verbosity has always been controlled solely by the--logger-levelCLI flag. Alogger_levelentry remaining in an existing~/.labelmercis 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
--outputguard rejecting only lowercase.jsonpaths; an upper- or mixed-case file path such as--output notes.JSONslipped past the "expects a directory" check and was treated as an output directory. The guard now reuses the canonical case-insensitiveis_label_file_pathhelper (#2317) - Fixed
read_label_fileaccepting boolean values where a shape'sgroup_idor point coordinates were expected in an annotation file; becauseboolis a subclass ofint, a hand-edited or third-party"group_id": true(or atrue/falseinsidepoints) 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 MBinstead of1.0 MB/1.0 GB; sizes now use a GB tier and rounding-safe unit boundaries (#2324) - Fixed
shapes_to_labelmishandling amaskshape 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 aValueErrorbroadcast 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 realicons/icon-256.png(matching the documented PyInstaller build), and thenew_icontests 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 toRGBbefore the JPEG save, aPimage carrying index-based transparency is routed to PNG so its transparency is preserved, and aPAimage (palette + alpha) is converted toRGBAbefore 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--configvalue 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 viaPath(value).is_file(), which raised instead of returningFalseon an over-length value, so the value is now treated as inline data as intended (#2345) - Fixed the config
labelskey silently accepting a scalar string such aslabels: catinstead of a list; the value was truthy and passed the duplicate check, soconfig["labels"]became the string"cat"and was later iterated character by character (c,a,t). A non-listlabelsvalue now surfaces as a clear configuration error instead (#2348) - Fixed a crash when a
label_flagsconfig 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 in2024: [occluded], which YAML parses as an int); such a pattern raised an uncaughtre.errororTypeErrorwhen 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 tore.match, raisingTypeError: 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 theshortcutsguard beside it, so the rest of the config is honored and an unusableai.defaultdegrades 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_pathalways recomputed an image-adjacent.jsonpath, 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_pathwhen 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.defaultmodel not being applied at startup when it resolves to the first list entry, i.e. when it is set toEfficientSam (speed)or to an unrecognized value (which falls back to that entry): the AI-Assisted Annotation panel only pushed its selection to the canvas oncurrentIndexChanged, which never fires for the already-selected index 0, so the panel showed the chosen model while the canvas silently kept the hardcodedsam2:latestuntil 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_fileaccepting a non-integer top-levelimageHeightorimageWidthin an annotation file; the dimension check compared with!=, so a booleantrue/false(which subclassesint) or a float slipped through whenever it happened to equal the real dimension, and now these fields are validated asintand rejected with a clear read error (#2374) - Fixed a naturally-spaced
--labels/--flagscomma 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 exactno 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~/.labelmercor--configfile with ungrammatical YAML (ayamlparser error);MainWindow._load_configcaught onlyValueError, 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_maskkeys, which were consolidated intocanvas.crosshair.ai_points_to_shapein v6.1.0; the legacy keys are now migrated during config loading (folded intoai_points_to_shapeas the logical OR of the two old values, with an explicitai_points_to_shapetaking 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_labelscreated the output directory (Path.mkdir) and computed the image's relative path inside itstrybut caught onlyLabelFileError, so a read-only or full--outputdirectory (PermissionError/OSError) or another rawValueErrorescaped 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 returningFalse(#2393) - Fixed
labelme --logger-level fatalcrashing on startup with an unhandledValueError: Level 'FATAL' does not exist;fatalwas an advertised--logger-levelchoice but loguru has no such level, so the value was replaced with loguru's realcriticallevel (matching theQtFatalMsg -> "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:andContrast: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 reachedself.tr()through a loop variable instead of as string literals, andpyside6-lupdateonly extracts literals, so neither string was ever written into a translation catalog. They are now literalself.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.pyor opening a smaller copy (#2417) - Fixed labelme refusing to start (exiting with status 1 and
Config file does not exist) when~/.labelmercdoes 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_polygonalongsideedit_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_flagspatterns 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~/.cachecannot 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 unsetLOCALAPPDATAon 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_flagspattern 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/Dshortcuts 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
Activegroup. 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);
closeEventignored 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
imagePathexists between two drives. Such a save now stores an absoluteimagePath, which reopens on the machine that wrote it but does not survive moving the files elsewhere; every other save keeps the relativeimagePath(#1350) (#2496) - Fixed dropped image files entering the File List with forward slashes on Windows;
QUrlreports 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)