lazylabel-gui 1.3.0__py3-none-any.whl → 1.3.1__py3-none-any.whl

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.
@@ -1601,14 +1601,19 @@ class MainWindow(QMainWindow):
1601
1601
  if self.current_image_path:
1602
1602
  self._mark_sam_dirty()
1603
1603
 
1604
- # Handle multi view mode - mark models as dirty so they get updated with adjusted images
1604
+ # Handle multi view mode - use fast updates for adjusted images instead of marking dirty
1605
1605
  elif self.view_mode == "multi" and hasattr(self, "multi_view_models"):
1606
+ changed_indices = []
1606
1607
  for i in range(len(self.multi_view_models)):
1607
1608
  if (
1608
1609
  self.multi_view_images[i]
1609
1610
  and self.multi_view_models[i] is not None
1610
1611
  ):
1611
- self._mark_multi_view_sam_dirty(i)
1612
+ changed_indices.append(i)
1613
+
1614
+ # Use fast updates instead of marking all models dirty
1615
+ if changed_indices:
1616
+ self._fast_update_multi_view_images(changed_indices)
1612
1617
 
1613
1618
  # File management methods
1614
1619
  def _open_folder_dialog(self):
@@ -1805,17 +1810,28 @@ class MainWindow(QMainWindow):
1805
1810
  while len(self._last_multi_view_images) < num_viewers:
1806
1811
  self._last_multi_view_images.append(None)
1807
1812
 
1808
- # Check and update SAM models for all viewers
1813
+ # Check and update SAM models for all viewers - USE FAST UPDATES for existing models
1814
+ changed_indices = []
1809
1815
  for i in range(num_viewers):
1810
1816
  image_path = (
1811
1817
  self.multi_view_images[i] if i < len(self.multi_view_images) else None
1812
1818
  )
1813
- if (
1814
- i < len(self.multi_view_models)
1815
- and self._last_multi_view_images[i] != image_path
1816
- ):
1819
+ if self._last_multi_view_images[i] != image_path:
1817
1820
  self._last_multi_view_images[i] = image_path
1818
- self._mark_multi_view_sam_dirty(i)
1821
+
1822
+ # Only mark dirty if model doesn't exist yet (needs initialization)
1823
+ if (
1824
+ i >= len(self.multi_view_models)
1825
+ or self.multi_view_models[i] is None
1826
+ ):
1827
+ self._mark_multi_view_sam_dirty(i)
1828
+ else:
1829
+ # Model exists - use fast image update instead of recreation
1830
+ changed_indices.append(i)
1831
+
1832
+ # Perform fast batch updates for existing models
1833
+ if changed_indices:
1834
+ self._fast_update_multi_view_images(changed_indices)
1819
1835
 
1820
1836
  # Load existing segments for all loaded images
1821
1837
  valid_image_paths = [path for path in image_paths if path is not None]
@@ -4944,11 +4960,19 @@ class MainWindow(QMainWindow):
4944
4960
  if hasattr(self, "multi_view_images") and any(self.multi_view_images):
4945
4961
  self._apply_multi_view_image_processing_fast()
4946
4962
 
4947
- # Mark multi-view SAM models as dirty if needed
4963
+ # Use fast updates for multi-view SAM models instead of marking dirty
4948
4964
  if self.settings.operate_on_view:
4965
+ changed_indices = []
4949
4966
  for i in range(len(self.multi_view_images)):
4950
- if self.multi_view_images[i]:
4951
- self._mark_multi_view_sam_dirty(i)
4967
+ if (
4968
+ self.multi_view_images[i]
4969
+ and i < len(self.multi_view_models)
4970
+ and self.multi_view_models[i] is not None
4971
+ ):
4972
+ changed_indices.append(i)
4973
+
4974
+ if changed_indices:
4975
+ self._fast_update_multi_view_images(changed_indices)
4952
4976
  return
4953
4977
 
4954
4978
  # Handle single-view mode
@@ -4972,11 +4996,19 @@ class MainWindow(QMainWindow):
4972
4996
  if hasattr(self, "multi_view_images") and any(self.multi_view_images):
4973
4997
  self._apply_multi_view_image_processing_fast()
4974
4998
 
4975
- # Mark multi-view SAM models as dirty if needed
4999
+ # Use fast updates for multi-view SAM models instead of marking dirty
4976
5000
  if self.settings.operate_on_view:
5001
+ changed_indices = []
4977
5002
  for i in range(len(self.multi_view_images)):
4978
- if self.multi_view_images[i]:
4979
- self._mark_multi_view_sam_dirty(i)
5003
+ if (
5004
+ self.multi_view_images[i]
5005
+ and i < len(self.multi_view_models)
5006
+ and self.multi_view_models[i] is not None
5007
+ ):
5008
+ changed_indices.append(i)
5009
+
5010
+ if changed_indices:
5011
+ self._fast_update_multi_view_images(changed_indices)
4980
5012
  return
4981
5013
 
4982
5014
  # Handle single-view mode
@@ -6511,10 +6543,58 @@ class MainWindow(QMainWindow):
6511
6543
  )
6512
6544
 
6513
6545
  def _mark_multi_view_sam_dirty(self, viewer_index):
6514
- """Mark multi-view SAM model as dirty (needs image update)."""
6546
+ """Mark multi-view SAM model as dirty (needs model recreation)."""
6515
6547
  if 0 <= viewer_index < len(self.multi_view_models_dirty):
6516
6548
  self.multi_view_models_dirty[viewer_index] = True
6517
6549
 
6550
+ def _update_multi_view_model_image(self, viewer_index, image_path):
6551
+ """Fast update: Set new image in existing model without recreating model."""
6552
+ if (
6553
+ viewer_index >= len(self.multi_view_models)
6554
+ or self.multi_view_models[viewer_index] is None
6555
+ or not image_path
6556
+ ):
6557
+ return False
6558
+
6559
+ model = self.multi_view_models[viewer_index]
6560
+
6561
+ try:
6562
+ # Get current modified image if operate_on_view is enabled
6563
+ if self.settings.operate_on_view:
6564
+ current_image = self._get_multi_view_modified_image(viewer_index)
6565
+ if current_image is not None:
6566
+ return model.set_image_from_array(current_image)
6567
+
6568
+ # Use original image path
6569
+ return model.set_image_from_path(image_path)
6570
+
6571
+ except Exception as e:
6572
+ logger.error(f"Failed to update image for model {viewer_index}: {e}")
6573
+ return False
6574
+
6575
+ def _fast_update_multi_view_images(self, changed_indices):
6576
+ """Fast batch update of images in existing models without recreation."""
6577
+ if not changed_indices:
6578
+ return
6579
+
6580
+ logger.debug(f"Fast updating images for viewers: {changed_indices}")
6581
+
6582
+ for viewer_index in changed_indices:
6583
+ if viewer_index >= len(self.multi_view_images):
6584
+ continue
6585
+
6586
+ image_path = self.multi_view_images[viewer_index]
6587
+ if image_path:
6588
+ success = self._update_multi_view_model_image(viewer_index, image_path)
6589
+ if success:
6590
+ logger.debug(f"Fast updated model {viewer_index} with new image")
6591
+ else:
6592
+ # Fall back to full model update if fast update fails
6593
+ logger.warning(
6594
+ f"Fast update failed for viewer {viewer_index}, marking dirty"
6595
+ )
6596
+ self._mark_multi_view_sam_dirty(viewer_index)
6597
+
6518
6598
  def _ensure_multi_view_sam_updated(self, viewer_index):
6519
6599
  """Ensure multi-view SAM model is updated for the given viewer."""
6520
6600
  config = self._get_multi_view_config()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lazylabel-gui
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: An image segmentation GUI for generating ML ready mask tensors and annotations.
5
5
  Author-email: "Deniz N. Cakan" <deniz.n.cakan@gmail.com>
6
6
  License: MIT License
@@ -18,7 +18,7 @@ lazylabel/ui/editable_vertex.py,sha256=ofo3r8ZZ3b8oYV40vgzZuS3QnXYBNzE92ArC2wggJ
18
18
  lazylabel/ui/hotkey_dialog.py,sha256=U_B76HLOxWdWkfA4d2XgRUaZTJPAAE_m5fmwf7Rh-5Y,14743
19
19
  lazylabel/ui/hoverable_pixelmap_item.py,sha256=UbWVxpmCTaeae_AeA8gMOHYGUmAw40fZBFTS3sZlw48,1821
20
20
  lazylabel/ui/hoverable_polygon_item.py,sha256=gZalImJ_PJYM7xON0iiSjQ335ZBREOfSscKLVs-MSh8,2314
21
- lazylabel/ui/main_window.py,sha256=tp2y41qwVtl0S7GHUD-KxQuFJek2ADA7JkyGs_GWU8o,378101
21
+ lazylabel/ui/main_window.py,sha256=r1Vk3aY346O3T1H8-4xmha0KpeWxANV27JthFQNX7ss,381615
22
22
  lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
23
23
  lazylabel/ui/photo_viewer.py,sha256=D_t2DS0AYckzlXjotTVC5ZxCsMYC-0xjBjeVQCrhqws,5631
24
24
  lazylabel/ui/reorderable_class_table.py,sha256=sxHhQre5O_MXLDFgKnw43QnvXXoqn5xRKMGitgO7muI,2371
@@ -41,9 +41,9 @@ lazylabel/utils/__init__.py,sha256=V6IR5Gim-39HgM2NyTVT-n8gy3mjilCSFW9y0owN5nc,1
41
41
  lazylabel/utils/custom_file_system_model.py,sha256=-3EimlybvevH6bvqBE0qdFnLADVtayylmkntxPXK0Bk,4869
42
42
  lazylabel/utils/logger.py,sha256=R7z6ifgA-NY-9ZbLlNH0i19zzwXndJ_gkG2J1zpVEhg,1306
43
43
  lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
44
- lazylabel_gui-1.3.0.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
45
- lazylabel_gui-1.3.0.dist-info/METADATA,sha256=XBCqdg0Ru-wM89Wp8EP-Rvb1jcUlkLDmWozCKi1SJJw,6898
46
- lazylabel_gui-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- lazylabel_gui-1.3.0.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
48
- lazylabel_gui-1.3.0.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
49
- lazylabel_gui-1.3.0.dist-info/RECORD,,
44
+ lazylabel_gui-1.3.1.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
45
+ lazylabel_gui-1.3.1.dist-info/METADATA,sha256=8Q4xKBHglQ2KIOuIzCM1W84pUQ4h_k-omx6uuzO_naw,6898
46
+ lazylabel_gui-1.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ lazylabel_gui-1.3.1.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
48
+ lazylabel_gui-1.3.1.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
49
+ lazylabel_gui-1.3.1.dist-info/RECORD,,