@@ -492,15 +492,16 @@ def inference_segmentation(
492492
493493 from .v2 .util import DEFAULT_MODEL
494494 from .v1 .automatic_segmentation import _get_inputs_from_paths
495- from .v2 .automatic_segmentation import get_segmenter , automatic_instance_segmentation
495+ from .v2 .automatic_segmentation import get_predictor_and_segmenter , automatic_instance_segmentation
496496
497497 model_type = model_type or DEFAULT_MODEL
498498 tile_shape = _parse_shape (tile_shape )
499499 halo = _parse_shape (halo )
500500 generate_kwargs = _parse_extra (ctx .args )
501501
502- segmenter = get_segmenter (
503- model_type = model_type , checkpoint = checkpoint_path , device = device , is_tiled = tile_shape is not None ,
502+ predictor , segmenter = get_predictor_and_segmenter (
503+ model_type = model_type , checkpoint = checkpoint_path , device = device ,
504+ segmentation_mode = "ais" , is_tiled = tile_shape is not None ,
504505 )
505506
506507 input_paths = _get_inputs_from_paths (list (input_path ), pattern )
@@ -521,6 +522,7 @@ def inference_segmentation(
521522 embedding_fpath = os .path .join (embedding_folder , f"{ os .path .splitext (os .path .basename (path ))[0 ]} .zarr" )
522523
523524 segmentation = automatic_instance_segmentation (
525+ predictor = predictor ,
524526 segmenter = segmenter ,
525527 input_path = path ,
526528 output_path = output_fpath ,
@@ -580,17 +582,19 @@ def inference_tracking(
580582 for sparse or '--beta' for dense) can be passed through and are forwarded.
581583 """
582584 from .v2 .util import DEFAULT_MODEL
583- from .v2 .automatic_segmentation import get_segmenter , automatic_tracking
585+ from .v2 .automatic_segmentation import get_predictor_and_segmenter , automatic_tracking
584586
585587 model_type = model_type or DEFAULT_MODEL
586588 tile_shape = _parse_shape (tile_shape )
587589 halo = _parse_shape (halo )
588590 generate_kwargs = _parse_extra (ctx .args )
589591
590- segmenter = get_segmenter (
591- model_type = model_type , checkpoint = checkpoint_path , device = device , is_tiled = tile_shape is not None ,
592+ predictor , segmenter = get_predictor_and_segmenter (
593+ model_type = model_type , checkpoint = checkpoint_path , device = device ,
594+ segmentation_mode = "ais" , is_tiled = tile_shape is not None ,
592595 )
593596 automatic_tracking (
597+ predictor = predictor ,
594598 segmenter = segmenter ,
595599 input_path = input_path ,
596600 output_path = output_path ,
@@ -791,28 +795,48 @@ def precompute_embeddings(
791795
792796
793797@cli .command ("train" )
794- @click .option ("-c" , "--config" , required = True , help = "The filepath to the SAM2 training config file." )
795- @click .option ("--use_cluster" , type = int , default = None , help = "Whether to launch on a cluster: 0 local, 1 cluster." )
796- @click .option ("--partition" , default = None , help = "SLURM partition." )
797- @click .option ("--account" , default = None , help = "SLURM account." )
798- @click .option ("--qos" , default = None , help = "SLURM qos." )
799- @click .option ("--num_gpus" , type = int , default = None , help = "Number of GPUs per node." )
800- @click .option ("--num_nodes" , type = int , default = None , help = "Number of nodes." )
801- def train (config , use_cluster , partition , account , qos , num_gpus , num_nodes ):
802- """Training a custom `micro-sam2` model."""
803- from .v2 .train import train_sam2 , register_omegaconf_resolvers
804-
805- register_omegaconf_resolvers ()
806- train_sam2 (
807- config = config ,
808- use_cluster = bool (use_cluster ) if use_cluster is not None else None ,
809- partition = partition ,
810- account = account ,
811- qos = qos ,
812- num_gpus = num_gpus ,
813- num_nodes = num_nodes ,
798+ @click .option ("-i" , "--input_path" , required = True , help = "Root of the generalist training data (dataset subfolders)." )
799+ @click .option ("-m" , "--model_type" , default = "hvit_t" , help = "SAM2 variant: hvit_t, hvit_s, hvit_b, hvit_l." )
800+ @click .option ("-s" , "--save_root" , default = None , help = "Directory for checkpoints and logs. Default: current dir." )
801+ @click .option ("--name" , default = None , help = "Checkpoint/log folder name. Auto-generated if unset." )
802+ @click .option ("--dataset_choice" , default = "both" , help = "Data modality to train on: 'lm', 'em' or 'both'." )
803+ @click .option ("--n_epochs" , type = int , default = 100 , help = "Number of training epochs." )
804+ @click .option ("--n_iterations" , type = int , default = None , help = "Fixed iteration budget (overrides --n_epochs)." )
805+ @click .option ("--batch_size" , type = int , default = 1 , help = "Batch size per GPU for 3d groups." )
806+ @click .option ("--batch_size_2d" , type = int , default = 8 , help = "Batch size per GPU for 2d groups." )
807+ @click .option ("--z_slices" , type = int , multiple = True , default = (8 ,), help = "Z-slice counts for 3d groups." )
808+ @click .option ("-c" , "--checkpoint_path" , default = None , help = "SAM2 checkpoint to start from; default downloaded." )
809+ def train (
810+ input_path , model_type , save_root , name , dataset_choice , n_epochs , n_iterations ,
811+ batch_size , batch_size_2d , z_slices , checkpoint_path ,
812+ ):
813+ """Train a joint SAM2 + UniSAM2 `micro-sam2` model on the generalist datasets."""
814+ import torch
815+
816+ n_gpus = torch .cuda .device_count ()
817+ if name is None :
818+ name = f"joint_sam2_{ model_type } _{ 'multi' if n_gpus > 1 else 'single' } _gpu"
819+
820+ # Joint interactive + automatic recipe from finetuning/v2/generalist/train_joint.py.
821+ kwargs = dict (
822+ name = name , model_type = model_type , input_path = input_path , save_root = save_root ,
823+ dataset_choice = dataset_choice , n_epochs = n_epochs , n_iterations = n_iterations ,
824+ batch_size = batch_size , batch_size_2d = batch_size_2d , z_slices = list (z_slices ),
825+ n_workers = 8 , checkpoint_path = checkpoint_path , lr = 1e-5 , max_num_objects = 5 ,
826+ prob_to_use_pt_input = 1.0 , prob_to_use_box_input = 0.5 , num_frames_to_correct = 2 ,
827+ rand_frames_to_correct = True , prob_to_sample_from_gt = 0.1 , add_all_frames_to_correct_as_cond = True ,
828+ num_correction_pt_per_frame = 7 , num_init_cond_frames = 2 , clip_grad_norm = None , largest_first = True ,
829+ bidirectional = True , use_focal_loss = True , focal_weight = 1.0 , use_object_score_loss = True ,
830+ average_over_frames = False ,
814831 )
815832
833+ if n_gpus > 1 :
834+ from .v2 .training import train_joint_sam2_multi_gpu
835+ train_joint_sam2_multi_gpu (** kwargs )
836+ else :
837+ from .v2 .training import train_joint_sam2
838+ train_joint_sam2 (** kwargs )
839+
816840
817841@cli .command ("info" )
818842@click .option (
0 commit comments