def modify_config_for_default_image_exp(config):
    """
    Modifies a Config object with experiment, training, and observation settings that
    were used across all image experiments by default.

    Args:
        config (Config instance): config to modify
    """
    assert config.algo_name not in ["hbc", "iris"], "no image training for HBC and IRIS"

    with config.experiment.values_unlocked():
        # save model during every evaluation (every 20 epochs)
        config.experiment.save.enabled = True
        config.experiment.save.every_n_epochs = 20

        # every epoch is 500 gradient steps, and validation epoch is 50 gradient steps
        config.experiment.epoch_every_n_steps = 500
        config.experiment.validation_epoch_every_n_steps = 50

        # do 50 evaluation rollouts every 20 epochs
        # NOTE: horizon will generally get set depending on the task and dataset type
        config.experiment.rollout.enabled = True
        config.experiment.rollout.n = 50
        config.experiment.rollout.horizon = 400
        config.experiment.rollout.rate = 20
        config.experiment.rollout.warmstart = 0
        config.experiment.rollout.terminate_on_success = True

    with config.train.values_unlocked():
        # only cache low-dim info, and use 2 data workers to increase fetch speed for image obs
        config.train.num_data_workers = 2
        config.train.hdf5_cache_mode = "low_dim"

        # batch size 16 and 600 training epochs
        config.train.batch_size = 16
        config.train.num_epochs = 600


    with config.observation.values_unlocked():
        # default low-dim observation is eef pose, gripper finger position
        # default image observation is external camera and wrist camera
        config.observation.modalities.obs.low_dim = [
            "robot0_eef_pos", 
            "robot0_eef_quat", 
            "robot0_gripper_qpos", 
        ]
        config.observation.modalities.obs.rgb = [
            "agentview_image",
            "robot0_eye_in_hand_image",
        ]
        config.observation.modalities.goal.low_dim = []
        config.observation.modalities.goal.rgb = []

        # default image encoder architecture is ResNet with spatial softmax
        config.observation.encoder.rgb.core_class = "VisualCore"
        config.observation.encoder.rgb.core_kwargs.feature_dimension = 64
        config.observation.encoder.rgb.core_kwargs.backbone_class = 'ResNet18Conv'                         # ResNet backbone for image observations (unused if no image observations)
        config.observation.encoder.rgb.core_kwargs.backbone_kwargs.pretrained = False                # kwargs for visual core
        config.observation.encoder.rgb.core_kwargs.backbone_kwargs.input_coord_conv = False
        config.observation.encoder.rgb.core_kwargs.pool_class = "SpatialSoftmax"                # Alternate options are "SpatialMeanPool" or None (no pooling)
        config.observation.encoder.rgb.core_kwargs.pool_kwargs.num_kp = 32                      # Default arguments for "SpatialSoftmax"
        config.observation.encoder.rgb.core_kwargs.pool_kwargs.learnable_temperature = False    # Default arguments for "SpatialSoftmax"
        config.observation.encoder.rgb.core_kwargs.pool_kwargs.temperature = 1.0                # Default arguments for "SpatialSoftmax"
        config.observation.encoder.rgb.core_kwargs.pool_kwargs.noise_std = 0.0

        # observation randomizer class - set to None to use no randomization, or 'CropRandomizer' to use crop randomization
        config.observation.encoder.rgb.obs_randomizer_class = "CropRandomizer"

        # kwargs for observation randomizers (for the CropRandomizer, this is size and number of crops)
        config.observation.encoder.rgb.obs_randomizer_kwargs.crop_height = 76
        config.observation.encoder.rgb.obs_randomizer_kwargs.crop_width = 76
        config.observation.encoder.rgb.obs_randomizer_kwargs.num_crops = 1
        config.observation.encoder.rgb.obs_randomizer_kwargs.pos_enc = False

    return config