From af432f006e4c6dbe484a64e4fc28bb2cffdc0282 Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:27:51 +0200 Subject: [PATCH 1/7] remove segment_anyting dir add sam later in dep --- segment_anything/__init__.py | 15 - .../__pycache__/__init__.cpython-38.pyc | Bin 463 -> 0 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 471 -> 0 bytes .../automatic_mask_generator.cpython-38.pyc | Bin 11387 -> 0 bytes .../automatic_mask_generator.cpython-39.pyc | Bin 11355 -> 0 bytes .../__pycache__/build_sam.cpython-38.pyc | Bin 2249 -> 0 bytes .../__pycache__/build_sam.cpython-39.pyc | Bin 2271 -> 0 bytes .../__pycache__/predictor.cpython-38.pyc | Bin 9972 -> 0 bytes .../__pycache__/predictor.cpython-39.pyc | Bin 9949 -> 0 bytes segment_anything/automatic_mask_generator.py | 372 ----------------- segment_anything/build_sam.py | 107 ----- segment_anything/modeling/__init__.py | 11 - .../__pycache__/__init__.cpython-38.pyc | Bin 450 -> 0 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 458 -> 0 bytes .../__pycache__/common.cpython-38.pyc | Bin 1792 -> 0 bytes .../__pycache__/common.cpython-39.pyc | Bin 1800 -> 0 bytes .../__pycache__/image_encoder.cpython-38.pyc | Bin 12514 -> 0 bytes .../__pycache__/image_encoder.cpython-39.pyc | Bin 12488 -> 0 bytes .../__pycache__/mask_decoder.cpython-38.pyc | Bin 5471 -> 0 bytes .../__pycache__/mask_decoder.cpython-39.pyc | Bin 5471 -> 0 bytes .../__pycache__/prompt_encoder.cpython-38.pyc | Bin 7725 -> 0 bytes .../__pycache__/prompt_encoder.cpython-39.pyc | Bin 7721 -> 0 bytes .../modeling/__pycache__/sam.cpython-38.pyc | Bin 6698 -> 0 bytes .../modeling/__pycache__/sam.cpython-39.pyc | Bin 6702 -> 0 bytes .../__pycache__/transformer.cpython-38.pyc | Bin 6626 -> 0 bytes .../__pycache__/transformer.cpython-39.pyc | Bin 6600 -> 0 bytes segment_anything/modeling/common.py | 43 -- segment_anything/modeling/image_encoder.py | 395 ------------------ segment_anything/modeling/mask_decoder.py | 176 -------- segment_anything/modeling/prompt_encoder.py | 214 ---------- segment_anything/modeling/sam.py | 174 -------- segment_anything/modeling/transformer.py | 240 ----------- segment_anything/predictor.py | 269 ------------ segment_anything/utils/__init__.py | 5 - .../utils/__pycache__/__init__.cpython-38.pyc | Bin 210 -> 0 bytes .../utils/__pycache__/__init__.cpython-39.pyc | Bin 218 -> 0 bytes .../utils/__pycache__/amg.cpython-38.pyc | Bin 12265 -> 0 bytes .../utils/__pycache__/amg.cpython-39.pyc | Bin 12168 -> 0 bytes .../__pycache__/transforms.cpython-38.pyc | Bin 4032 -> 0 bytes .../__pycache__/transforms.cpython-39.pyc | Bin 4020 -> 0 bytes segment_anything/utils/amg.py | 346 --------------- segment_anything/utils/onnx.py | 144 ------- segment_anything/utils/transforms.py | 102 ----- 43 files changed, 2613 deletions(-) delete mode 100644 segment_anything/__init__.py delete mode 100644 segment_anything/__pycache__/__init__.cpython-38.pyc delete mode 100644 segment_anything/__pycache__/__init__.cpython-39.pyc delete mode 100644 segment_anything/__pycache__/automatic_mask_generator.cpython-38.pyc delete mode 100644 segment_anything/__pycache__/automatic_mask_generator.cpython-39.pyc delete mode 100644 segment_anything/__pycache__/build_sam.cpython-38.pyc delete mode 100644 segment_anything/__pycache__/build_sam.cpython-39.pyc delete mode 100644 segment_anything/__pycache__/predictor.cpython-38.pyc delete mode 100644 segment_anything/__pycache__/predictor.cpython-39.pyc delete mode 100644 segment_anything/automatic_mask_generator.py delete mode 100644 segment_anything/build_sam.py delete mode 100644 segment_anything/modeling/__init__.py delete mode 100644 segment_anything/modeling/__pycache__/__init__.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/__init__.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/common.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/common.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/image_encoder.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/image_encoder.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/mask_decoder.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/mask_decoder.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/prompt_encoder.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/prompt_encoder.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/sam.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/sam.cpython-39.pyc delete mode 100644 segment_anything/modeling/__pycache__/transformer.cpython-38.pyc delete mode 100644 segment_anything/modeling/__pycache__/transformer.cpython-39.pyc delete mode 100644 segment_anything/modeling/common.py delete mode 100644 segment_anything/modeling/image_encoder.py delete mode 100644 segment_anything/modeling/mask_decoder.py delete mode 100644 segment_anything/modeling/prompt_encoder.py delete mode 100644 segment_anything/modeling/sam.py delete mode 100644 segment_anything/modeling/transformer.py delete mode 100644 segment_anything/predictor.py delete mode 100644 segment_anything/utils/__init__.py delete mode 100644 segment_anything/utils/__pycache__/__init__.cpython-38.pyc delete mode 100644 segment_anything/utils/__pycache__/__init__.cpython-39.pyc delete mode 100644 segment_anything/utils/__pycache__/amg.cpython-38.pyc delete mode 100644 segment_anything/utils/__pycache__/amg.cpython-39.pyc delete mode 100644 segment_anything/utils/__pycache__/transforms.cpython-38.pyc delete mode 100644 segment_anything/utils/__pycache__/transforms.cpython-39.pyc delete mode 100644 segment_anything/utils/amg.py delete mode 100644 segment_anything/utils/onnx.py delete mode 100644 segment_anything/utils/transforms.py diff --git a/segment_anything/__init__.py b/segment_anything/__init__.py deleted file mode 100644 index 34383d8..0000000 --- a/segment_anything/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -from .build_sam import ( - build_sam, - build_sam_vit_h, - build_sam_vit_l, - build_sam_vit_b, - sam_model_registry, -) -from .predictor import SamPredictor -from .automatic_mask_generator import SamAutomaticMaskGenerator diff --git a/segment_anything/__pycache__/__init__.cpython-38.pyc b/segment_anything/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index a156dcb30bb5bfc03dbe15866fa707f99aa68782..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmZ8dO-lnY5Y2wH-IW%>lY$4Yy);)3A{K>u=!&%Tl1s?$hHWs}tVvecOaG7f3;Zj4 z_2gghH# zmt0cAD`B1Kra?bmGxcbADGH|z@H61^)@j9@C^BZB7QE($f%q^@jbF$_9%2sz4?_Tw zHhT{<^8A$TJ*WZ`TJ2p-0`eO&sc-f0{fsx38;f6AUD++KE4&oBVWz{G&V}R`ce-d5 zubst(Ry)=-lJ9P%Zc7j>&bozg_ieu7jkXx3r%Sz>W6LYwLs{LqtpHO>MGcptv!?5l SE4V`|`L&3u^s9NjQ)q~g>u-5u^q`X)VH?h9&P$h#wWN44QX zQ7cO6ylp4A8!ecAvVzOP8w>md_)X)DW?mL^=3Zx_5|)AaI2qc|kc|T*0eS)Y0Nt?O zX4nC6a?G|FR6__Yw<$ISdyQ-u+y;Ky?8OP|vUgUMZYioVdyu(hw$0`ymr9)7nWE96 z@-8ckUa`7XVs)!b!@+Rbyq!sZ-{jAtHZF6b3|G%t)%vA`tUrP71WIKE6Qk3*?b1t_ QN2A15__GTwoeoC$7uy|-lmGw# diff --git a/segment_anything/__pycache__/automatic_mask_generator.cpython-38.pyc b/segment_anything/__pycache__/automatic_mask_generator.cpython-38.pyc deleted file mode 100644 index ee94d699351358afba6b7057b07ebb6c3d07f0cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11387 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 diff --git a/segment_anything/__pycache__/automatic_mask_generator.cpython-39.pyc b/segment_anything/__pycache__/automatic_mask_generator.cpython-39.pyc deleted file mode 100644 index 16faf5c53dd17c06903d6fcb1756c3ac7619a428..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11355 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 E0kzvl>;M1& diff --git a/segment_anything/__pycache__/build_sam.cpython-38.pyc b/segment_anything/__pycache__/build_sam.cpython-38.pyc deleted file mode 100644 index baf2a50142de4cbaecda9883ab5553e905d50f4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2249 zcmbtVOOM<{5N>&4HUwG$%QM~Uan`T2dv-I( zlM8Sh?H}Nf9COPB39doPkMIEraT-P3ct|7%s_dEBCCUMW?XIrsuI{d?uKIkX(Xa_T zKg8$RjT#}ppm6ljL0E&9MnD*0N4#d+N{M4W`a~>3(R6RaCL6OTjOv`+L(DnFxQ7>j(eBy8CwGB7jy~GPSZ+s-;Fp<;gymHwM^TqA`_^LbH z7H*X8#3JOPhkMN)wZ_bV%XV; zyMDk|FU7q<$Rn9{dU1HmO_G4$x){U*1`}y#WB9%=KNxhkcoL@_h@P_^Z@t?|xrb{U zHyX;m51Y=9Kc5Wq)?9M-eChO?U`UFDDC+dJ74?z8;Qo)$PlyH)MlS^>?gaC50*Ol| zi#XOmf;SafW~1tOkB z4pU5=Me?6)?7j#~o@V1Y7;kI2!T63l2qe{u(3f417gD!}A(}mC4<23Q`2%2>GSZnk zs?Ea$*N3~s;pesuIpF@V>MGV1B%$lD$LAuW{vBzn(3LDnL8@1 zuI^wg?6D>dR+A>HgH8iLpf%Qjt3gFAjCCmTCAREU*a|zwjzfQ9tdFeBx^3Md3duA^ zb}eyV+Q6OsNsjrN0xK-2$y1vXSWE<7W|6`rYk6AKbgpR%nGM>GlK@vR%*hvi_`jWm3}*Jty_QTj%oUZStv^Ge&BY5CI(a`0mlrOFALm|ie(_`X+bb5V&qqZhq z0kiTIA3?1|3kLO7>Mi(D0-EJqVPGQ!tOHCaS5F|#ho&h6XMID_ULzhCx8`vCn1cTrta6}%0ByAlLa4l{6@u0ver-&h4p38loF&?3k z_a;6MzgY9OzCZiT!^O|1%+H^#c|ZRC(zSy(HrBj@`^c@Yd0-47_tw_{*BjFil)y=w zNde@}6ccH^u#=TA57*$|gm8!4ji^=fsbo|Y-F8DDBn!*|fz_AmG8Vmlu127`j`z6< zH!G?*kL4k-FmsLXxk0YQ36F9uh+RfoNS#!=l7nA8*{%x&d{JP{5^~E(5PRvu%-9*) zQ~SuJHL)@e^G3V|OY#apcdqPE`|yM(&`KN!y|1oux%exaYF&M%V%r)tyEb+0akW7n{SCLyLO=ij diff --git a/segment_anything/__pycache__/build_sam.cpython-39.pyc b/segment_anything/__pycache__/build_sam.cpython-39.pyc deleted file mode 100644 index bf43b8aa5d1a7bae4634e232a14f1aac17c33b25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2271 zcmbVNOOG5i5OzPOAM@Bp!XtsOf*@r;$q+bjLD5PH0;Js)N*1D6fmYAhJJU(O;`U@S zQBN*`<0yZC!zQ=fazTO%2axyy960m=32|yg+;~VN2da7=yF@tv?RL3bF5BgD)n~ua za0q-~C#TpomylnubMP~uvkoEEkDuiiF54A|AdSp-|GN~EWXf3j+ z1!GNSF!M8o+T5lNYq1)$py#qBW-|x4I(MMByw2P&blPCctj-!BZ!+ZqX|I&9C)sK% zMJ@G(4E(TEK+rad)(4T_=kLb7gmLk4uwA&Des=X7ulhyfLy<(OoDCP+1wSg5w|A3^ z{%BkHaki6)h>ISsHUE&WK|KpKdj^PvqcW9geZus6N=}$DF~B5qD zbcHWQoz0{hgnaE>(i=uRmRYBlM7R7j4f(CJVKQVekaadk?*;PxVfQ>wldO~RKB}Jd z&06?yE56X%-#_d0Q`PjPLlvP*S6E`?LwCO}B>*ntx~!Ze2zC zkH9cxY%q0fGHqPT&AfJmj4er|l0($zCex)VwJZ7+15 zBe!yEM}^tu4&)4TCc3OKS6ZwNIt_q<)UzKn1kgK&b9aIxqDYZ z4l?!dRtZ8P@M^0-DIsh~fAZ^>dw+ia;7nVg8c(zB5`(i{FN|qU+KX(ZRuJ{QEV#+3 z9fheUd>JIvi2*yj&>wM8*o(ZSPU_3vV5)6hyL#R027X4}Va7edLk|*(u0AcL-CaoT zWOuerGL&9#007n2#cN}KdP-!!*;N6>HC9PMsvMKn(RRlM{>KwSZCT8n??1+;%MFU7LlpX5q@9+eE34Ed6hMHXl zLTb8##acitLT&ROJ@q%eiBc1a`dByTU|hBH{vUcB#(y%8Td-DLIiWa8wNqPxH+cTH z#A(>Fuy=-WPbNv2Rj#B~1W$1YF*h27RWpg9cr8C*HTMJ=_izMwgd4%KmIM|*5G$fLgj0Rcvw diff --git a/segment_anything/__pycache__/predictor.cpython-38.pyc b/segment_anything/__pycache__/predictor.cpython-38.pyc deleted file mode 100644 index 8fac8b702fd93e2ff4159f2a58b3956ecd3a7361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9972 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 UHTgD8R?sVMVBN5dWy3aq38fVyyZ`_I diff --git a/segment_anything/__pycache__/predictor.cpython-39.pyc b/segment_anything/__pycache__/predictor.cpython-39.pyc deleted file mode 100644 index 200e61d1291920e91411daa684ec973415610b3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9949 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 uadcO)nH None: - """ - Using a SAM model, generates masks for the entire image. - Generates a grid of point prompts over the image, then filters - low quality and duplicate masks. The default settings are chosen - for SAM with a ViT-H backbone. - - Arguments: - model (Sam): The SAM model to use for mask prediction. - points_per_side (int or None): The number of points to be sampled - along one side of the image. The total number of points is - points_per_side**2. If None, 'point_grids' must provide explicit - point sampling. - points_per_batch (int): Sets the number of points run simultaneously - by the model. Higher numbers may be faster but use more GPU memory. - pred_iou_thresh (float): A filtering threshold in [0,1], using the - model's predicted mask quality. - stability_score_thresh (float): A filtering threshold in [0,1], using - the stability of the mask under changes to the cutoff used to binarize - the model's mask predictions. - stability_score_offset (float): The amount to shift the cutoff when - calculated the stability score. - box_nms_thresh (float): The box IoU cutoff used by non-maximal - suppression to filter duplicate masks. - crops_n_layers (int): If >0, mask prediction will be run again on - crops of the image. Sets the number of layers to run, where each - layer has 2**i_layer number of image crops. - crops_nms_thresh (float): The box IoU cutoff used by non-maximal - suppression to filter duplicate masks between different crops. - crop_overlap_ratio (float): Sets the degree to which crops overlap. - In the first crop layer, crops will overlap by this fraction of - the image length. Later layers with more crops scale down this overlap. - crop_n_points_downscale_factor (int): The number of points-per-side - sampled in layer n is scaled down by crop_n_points_downscale_factor**n. - point_grids (list(np.ndarray) or None): A list over explicit grids - of points used for sampling, normalized to [0,1]. The nth grid in the - list is used in the nth crop layer. Exclusive with points_per_side. - min_mask_region_area (int): If >0, postprocessing will be applied - to remove disconnected regions and holes in masks with area smaller - than min_mask_region_area. Requires opencv. - output_mode (str): The form masks are returned in. Can be 'binary_mask', - 'uncompressed_rle', or 'coco_rle'. 'coco_rle' requires pycocotools. - For large resolutions, 'binary_mask' may consume large amounts of - memory. - """ - - assert (points_per_side is None) != ( - point_grids is None - ), "Exactly one of points_per_side or point_grid must be provided." - if points_per_side is not None: - self.point_grids = build_all_layer_point_grids( - points_per_side, - crop_n_layers, - crop_n_points_downscale_factor, - ) - elif point_grids is not None: - self.point_grids = point_grids - else: - raise ValueError("Can't have both points_per_side and point_grid be None.") - - assert output_mode in [ - "binary_mask", - "uncompressed_rle", - "coco_rle", - ], f"Unknown output_mode {output_mode}." - if output_mode == "coco_rle": - from pycocotools import mask as mask_utils # type: ignore # noqa: F401 - - if min_mask_region_area > 0: - import cv2 # type: ignore # noqa: F401 - - self.predictor = SamPredictor(model) - self.points_per_batch = points_per_batch - self.pred_iou_thresh = pred_iou_thresh - self.stability_score_thresh = stability_score_thresh - self.stability_score_offset = stability_score_offset - self.box_nms_thresh = box_nms_thresh - self.crop_n_layers = crop_n_layers - self.crop_nms_thresh = crop_nms_thresh - self.crop_overlap_ratio = crop_overlap_ratio - self.crop_n_points_downscale_factor = crop_n_points_downscale_factor - self.min_mask_region_area = min_mask_region_area - self.output_mode = output_mode - - @torch.no_grad() - def generate(self, image: np.ndarray) -> List[Dict[str, Any]]: - """ - Generates masks for the given image. - - Arguments: - image (np.ndarray): The image to generate masks for, in HWC uint8 format. - - Returns: - list(dict(str, any)): A list over records for masks. Each record is - a dict containing the following keys: - segmentation (dict(str, any) or np.ndarray): The mask. If - output_mode='binary_mask', is an array of shape HW. Otherwise, - is a dictionary containing the RLE. - bbox (list(float)): The box around the mask, in XYWH format. - area (int): The area in pixels of the mask. - predicted_iou (float): The model's own prediction of the mask's - quality. This is filtered by the pred_iou_thresh parameter. - point_coords (list(list(float))): The point coordinates input - to the model to generate this mask. - stability_score (float): A measure of the mask's quality. This - is filtered on using the stability_score_thresh parameter. - crop_box (list(float)): The crop of the image used to generate - the mask, given in XYWH format. - """ - - # Generate masks - mask_data = self._generate_masks(image) - - # Filter small disconnected regions and holes in masks - if self.min_mask_region_area > 0: - mask_data = self.postprocess_small_regions( - mask_data, - self.min_mask_region_area, - max(self.box_nms_thresh, self.crop_nms_thresh), - ) - - # Encode masks - if self.output_mode == "coco_rle": - mask_data["segmentations"] = [coco_encode_rle(rle) for rle in mask_data["rles"]] - elif self.output_mode == "binary_mask": - mask_data["segmentations"] = [rle_to_mask(rle) for rle in mask_data["rles"]] - else: - mask_data["segmentations"] = mask_data["rles"] - - # Write mask records - curr_anns = [] - for idx in range(len(mask_data["segmentations"])): - ann = { - "segmentation": mask_data["segmentations"][idx], - "area": area_from_rle(mask_data["rles"][idx]), - "bbox": box_xyxy_to_xywh(mask_data["boxes"][idx]).tolist(), - "predicted_iou": mask_data["iou_preds"][idx].item(), - "point_coords": [mask_data["points"][idx].tolist()], - "stability_score": mask_data["stability_score"][idx].item(), - "crop_box": box_xyxy_to_xywh(mask_data["crop_boxes"][idx]).tolist(), - } - curr_anns.append(ann) - - return curr_anns - - def _generate_masks(self, image: np.ndarray) -> MaskData: - orig_size = image.shape[:2] - crop_boxes, layer_idxs = generate_crop_boxes( - orig_size, self.crop_n_layers, self.crop_overlap_ratio - ) - - # Iterate over image crops - data = MaskData() - for crop_box, layer_idx in zip(crop_boxes, layer_idxs): - crop_data = self._process_crop(image, crop_box, layer_idx, orig_size) - data.cat(crop_data) - - # Remove duplicate masks between crops - if len(crop_boxes) > 1: - # Prefer masks from smaller crops - scores = 1 / box_area(data["crop_boxes"]) - scores = scores.to(data["boxes"].device) - keep_by_nms = batched_nms( - data["boxes"].float(), - scores, - torch.zeros(len(data["boxes"])), # categories - iou_threshold=self.crop_nms_thresh, - ) - data.filter(keep_by_nms) - - data.to_numpy() - return data - - def _process_crop( - self, - image: np.ndarray, - crop_box: List[int], - crop_layer_idx: int, - orig_size: Tuple[int, ...], - ) -> MaskData: - # Crop the image and calculate embeddings - x0, y0, x1, y1 = crop_box - cropped_im = image[y0:y1, x0:x1, :] - cropped_im_size = cropped_im.shape[:2] - self.predictor.set_image(cropped_im) - - # Get points for this crop - points_scale = np.array(cropped_im_size)[None, ::-1] - points_for_image = self.point_grids[crop_layer_idx] * points_scale - - # Generate masks for this crop in batches - data = MaskData() - for (points,) in batch_iterator(self.points_per_batch, points_for_image): - batch_data = self._process_batch(points, cropped_im_size, crop_box, orig_size) - data.cat(batch_data) - del batch_data - self.predictor.reset_image() - - # Remove duplicates within this crop. - keep_by_nms = batched_nms( - data["boxes"].float(), - data["iou_preds"], - torch.zeros(len(data["boxes"])), # categories - iou_threshold=self.box_nms_thresh, - ) - data.filter(keep_by_nms) - - # Return to the original image frame - data["boxes"] = uncrop_boxes_xyxy(data["boxes"], crop_box) - data["points"] = uncrop_points(data["points"], crop_box) - data["crop_boxes"] = torch.tensor([crop_box for _ in range(len(data["rles"]))]) - - return data - - def _process_batch( - self, - points: np.ndarray, - im_size: Tuple[int, ...], - crop_box: List[int], - orig_size: Tuple[int, ...], - ) -> MaskData: - orig_h, orig_w = orig_size - - # Run model on this batch - transformed_points = self.predictor.transform.apply_coords(points, im_size) - in_points = torch.as_tensor(transformed_points, device=self.predictor.device) - in_labels = torch.ones(in_points.shape[0], dtype=torch.int, device=in_points.device) - masks, iou_preds, _ = self.predictor.predict_torch( - in_points[:, None, :], - in_labels[:, None], - multimask_output=True, - return_logits=True, - ) - - # Serialize predictions and store in MaskData - data = MaskData( - masks=masks.flatten(0, 1), - iou_preds=iou_preds.flatten(0, 1), - points=torch.as_tensor(points.repeat(masks.shape[1], axis=0)), - ) - del masks - - # Filter by predicted IoU - if self.pred_iou_thresh > 0.0: - keep_mask = data["iou_preds"] > self.pred_iou_thresh - data.filter(keep_mask) - - # Calculate stability score - data["stability_score"] = calculate_stability_score( - data["masks"], self.predictor.model.mask_threshold, self.stability_score_offset - ) - if self.stability_score_thresh > 0.0: - keep_mask = data["stability_score"] >= self.stability_score_thresh - data.filter(keep_mask) - - # Threshold masks and calculate boxes - data["masks"] = data["masks"] > self.predictor.model.mask_threshold - data["boxes"] = batched_mask_to_box(data["masks"]) - - # Filter boxes that touch crop boundaries - keep_mask = ~is_box_near_crop_edge(data["boxes"], crop_box, [0, 0, orig_w, orig_h]) - if not torch.all(keep_mask): - data.filter(keep_mask) - - # Compress to RLE - data["masks"] = uncrop_masks(data["masks"], crop_box, orig_h, orig_w) - data["rles"] = mask_to_rle_pytorch(data["masks"]) - del data["masks"] - - return data - - @staticmethod - def postprocess_small_regions( - mask_data: MaskData, min_area: int, nms_thresh: float - ) -> MaskData: - """ - Removes small disconnected regions and holes in masks, then reruns - box NMS to remove any new duplicates. - - Edits mask_data in place. - - Requires open-cv as a dependency. - """ - if len(mask_data["rles"]) == 0: - return mask_data - - # Filter small disconnected regions and holes - new_masks = [] - scores = [] - for rle in mask_data["rles"]: - mask = rle_to_mask(rle) - - mask, changed = remove_small_regions(mask, min_area, mode="holes") - unchanged = not changed - mask, changed = remove_small_regions(mask, min_area, mode="islands") - unchanged = unchanged and not changed - - new_masks.append(torch.as_tensor(mask).unsqueeze(0)) - # Give score=0 to changed masks and score=1 to unchanged masks - # so NMS will prefer ones that didn't need postprocessing - scores.append(float(unchanged)) - - # Recalculate boxes and remove any new duplicates - masks = torch.cat(new_masks, dim=0) - boxes = batched_mask_to_box(masks) - keep_by_nms = batched_nms( - boxes.float(), - torch.as_tensor(scores), - torch.zeros(len(boxes)), # categories - iou_threshold=nms_thresh, - ) - - # Only recalculate RLEs for masks that have changed - for i_mask in keep_by_nms: - if scores[i_mask] == 0.0: - mask_torch = masks[i_mask].unsqueeze(0) - mask_data["rles"][i_mask] = mask_to_rle_pytorch(mask_torch)[0] - mask_data["boxes"][i_mask] = boxes[i_mask] # update res directly - mask_data.filter(keep_by_nms) - - return mask_data diff --git a/segment_anything/build_sam.py b/segment_anything/build_sam.py deleted file mode 100644 index 07abfca..0000000 --- a/segment_anything/build_sam.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch - -from functools import partial - -from .modeling import ImageEncoderViT, MaskDecoder, PromptEncoder, Sam, TwoWayTransformer - - -def build_sam_vit_h(checkpoint=None): - return _build_sam( - encoder_embed_dim=1280, - encoder_depth=32, - encoder_num_heads=16, - encoder_global_attn_indexes=[7, 15, 23, 31], - checkpoint=checkpoint, - ) - - -build_sam = build_sam_vit_h - - -def build_sam_vit_l(checkpoint=None): - return _build_sam( - encoder_embed_dim=1024, - encoder_depth=24, - encoder_num_heads=16, - encoder_global_attn_indexes=[5, 11, 17, 23], - checkpoint=checkpoint, - ) - - -def build_sam_vit_b(checkpoint=None): - return _build_sam( - encoder_embed_dim=768, - encoder_depth=12, - encoder_num_heads=12, - encoder_global_attn_indexes=[2, 5, 8, 11], - checkpoint=checkpoint, - ) - - -sam_model_registry = { - "default": build_sam, - "vit_h": build_sam, - "vit_l": build_sam_vit_l, - "vit_b": build_sam_vit_b, -} - - -def _build_sam( - encoder_embed_dim, - encoder_depth, - encoder_num_heads, - encoder_global_attn_indexes, - checkpoint=None, -): - prompt_embed_dim = 256 - image_size = 1024 - vit_patch_size = 16 - image_embedding_size = image_size // vit_patch_size - sam = Sam( - image_encoder=ImageEncoderViT( - depth=encoder_depth, - embed_dim=encoder_embed_dim, - img_size=image_size, - mlp_ratio=4, - norm_layer=partial(torch.nn.LayerNorm, eps=1e-6), - num_heads=encoder_num_heads, - patch_size=vit_patch_size, - qkv_bias=True, - use_rel_pos=True, - global_attn_indexes=encoder_global_attn_indexes, - window_size=14, - out_chans=prompt_embed_dim, - ), - prompt_encoder=PromptEncoder( - embed_dim=prompt_embed_dim, - image_embedding_size=(image_embedding_size, image_embedding_size), - input_image_size=(image_size, image_size), - mask_in_chans=16, - ), - mask_decoder=MaskDecoder( - num_multimask_outputs=3, - transformer=TwoWayTransformer( - depth=2, - embedding_dim=prompt_embed_dim, - mlp_dim=2048, - num_heads=8, - ), - transformer_dim=prompt_embed_dim, - iou_head_depth=3, - iou_head_hidden_dim=256, - ), - pixel_mean=[123.675, 116.28, 103.53], - pixel_std=[58.395, 57.12, 57.375], - ) - sam.eval() - if checkpoint is not None: - with open(checkpoint, "rb") as f: - state_dict = torch.load(f) - sam.load_state_dict(state_dict) - return sam diff --git a/segment_anything/modeling/__init__.py b/segment_anything/modeling/__init__.py deleted file mode 100644 index 38e9062..0000000 --- a/segment_anything/modeling/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -from .sam import Sam -from .image_encoder import ImageEncoderViT -from .mask_decoder import MaskDecoder -from .prompt_encoder import PromptEncoder -from .transformer import TwoWayTransformer diff --git a/segment_anything/modeling/__pycache__/__init__.cpython-38.pyc b/segment_anything/modeling/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 28aed9c6aab2055aaa94843e4e0c152fcb421002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450 zcmYk2NlwEs6o&1lX*vbO4cK;5UjQKxMS#>I)B&VyEVnVKg@?#agu6*9mV3 zl<~baDlc{|0FLHs^USKbW!k+MtGK-z_3OYfW&NymEW9P4=(u%c&2;8gTxaA~EG)AXnVN-={CHxPrQ*79WNFlf z<+2^1l#cVN?w$fJ PB|nQ`EZ2oJ#M|`?v3Z20 diff --git a/segment_anything/modeling/__pycache__/common.cpython-38.pyc b/segment_anything/modeling/__pycache__/common.cpython-38.pyc deleted file mode 100644 index 53c866cb05bed3007f49ae4e4ecdb512a484946f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1792 zcmZWqy>25n5GJ|YAIa9m@j0=L%a4-)K?DRA;wr`Aki-dmg)AJ-cB5vo7AbjkyIdW) zf=`C-8aue^-oS-jx=WKHFOa+g+Z2I|)B%zdnc-Tt4k0nKO4wG*{%wtf32%3>@^`$xMGKyoCc{%TLN_L3w1V1B!OE&aRy>0*&Uj$$Y zZY-god!!j&gE!J?Qp@)zBiX~*d<$+S?o>&-RFE!{-jMgH^q~hZ4%gu}f}Qi%q)*+s zjcz1s!#axa&zT5Bc*eU6uL&pJML0FG(Qf<6cUjSU)@gFvkoln$B2|M}q`3|AY~%)B z(kpGCWjWTWhwq;?9HV$3W(!nFPRRwmB$Slw!kf}5yJS-mb2npC>Sq4bJ0)NZ1lc23 zw9^c&Z^k33Z4}3;O3OI5Oeq_*Qza8^d6ufLoZiwH2e>IWGV5zRT0@SAGhb0#i{oCF z7!$`=J|B`WHid;tL>~9 z3s^9%-N{Z`J{})Fm7~J6_L4kq7f-)!89Bh;#EF`eM-Zu2UI+;n9H5iDP@AKPMgZLd zF%c*d)agCwC-2Tey*Yd36|?k(4q;D^;m(_eV>E7qnD;?V$ps1p!5F%}M>KkGdKyo1 z0niOJF#Qf1-b1x~tM0?dhW$bxCt9q-#JCgb$r*h>KFl&t}11;3oPyP~jGl?QK1hJ2M= z(g)-vfP3ge=_Efg)O~Lq{H*}&hfpTwt*f{fOQzqsrf}*$)Xeailp`ov*N8$WCp?#l zvfijTzKN50uFEO{pTiFQ1#aVaM6q;ishNYLiw+_dw;T6|02E$>{v|!RKOdhNYpDJN zo!0d#eDoSBq?vvI%KH7RNXjaam^l3rD)g^EMs>&2J05Jn0xlYib41qyjh1Fqy(n_z t+El6nMo>;hP=g!`^#`!e5ykyt&iQTPZS=6B^&_k^F8dK(WQ*SN@_$P!hV%dc diff --git a/segment_anything/modeling/__pycache__/common.cpython-39.pyc b/segment_anything/modeling/__pycache__/common.cpython-39.pyc deleted file mode 100644 index 862d9ff2c73fabf0e08ab04dcb1e5e29ff74e2d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1800 zcmZWqPj6#25V!sO{v>Ud(k-;r@~41=hy;!3iNk7zD5!gAqZQq~XG6E} zl5S}OEz6NsU3~v+;2OyTGCROZaz-xc6``bLm)?X<*cF?Qn7bXDP`C3Z-WdUDAjl!P zrtM~EeKQ(LZKF6&Ra(ZeWlGs#KUFf(mS?H@((xUQae$k0BeR~yqc!A+IPo>LwK(o( zi7|0}P5$|@^~6YRS|^F>n`5c^t^M>!CwkmED2~!hZhc#HN4Zp`X?2VIMKT;_^2Kge zj07l5>tMW>mJdfq-^*cPT1NKK^ovA|%VP-8Oc2inc_AcRw2#j6LTwMn8Vl(Tkcohi zpib|=Jbil>^6lAcubHJk=n!nW3@xVv*C^ZtGVcPLkV_;Agt2thP^_cBwB33#<&yd>B{_8Q)RP(=}<{7AszKNhWCv!TrbD*vr&>& z8oh)L`QCT?Ppp@!QlmQ?95`ba0PB~9?jGCVu~eqe8XsaC(?oS;mc{YH{Z>G$@sb*A z3Lj!n6#4u=#u#NZqU_(5C8vD@Bv=YK%za=pkcgV}Bo|D07oGzK7yfyp1CSYnNFo4W zgdzf9L=G4=07l&|?I&ZY+l9_|#GkMJ`sMQP-+q43ZhCfEjq^841Ud5z+T5i$uIpXe~1Fa21vrWB$^;*YKV?1w{=|uA1<0zylamV4T&kG*6)MH z@^T(bgl$043VyXHcg^qW8#i zDDHs|EtLGkkoUYz@V5qKKY(_zC|yTeY@L4lhQg_jp?8K)r5r-*y1^=hw!(9nDC-T2 zlWCmHGhJ2@_!KPkXK2Q6fnw>%QnOHwE;?ATXl~pe13-8K=I8YE?qYmqsG<5JbXwQz z@X;H{5N7%wFzffSA}OmxV&e1%$k4z35ZNtGZ*i~%3RD`5b3``+jgn?my(n_v+E%J6 pjG!D3p$9n>>i59T0mc1d!TCJ#Ho9NI`T_PCm;Hz?vt@5}^?w-&io5^- diff --git a/segment_anything/modeling/__pycache__/image_encoder.cpython-38.pyc b/segment_anything/modeling/__pycache__/image_encoder.cpython-38.pyc deleted file mode 100644 index 1192f25138a62bdba9bc5a08b077ac2d5ab82f1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12514 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 Q4Bn^1?jnB1hvnz~1292CSO5S3 diff --git a/segment_anything/modeling/__pycache__/image_encoder.cpython-39.pyc b/segment_anything/modeling/__pycache__/image_encoder.cpython-39.pyc deleted file mode 100644 index a05ad9027e56a8d72753b0c940a33be58668ac4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12488 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 O04hs*!&v;KR{sxl#+fMq diff --git a/segment_anything/modeling/__pycache__/prompt_encoder.cpython-38.pyc b/segment_anything/modeling/__pycache__/prompt_encoder.cpython-38.pyc deleted file mode 100644 index c90cee7bde119fafb028c997df5c163868098541..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7725 zcma)BO>i5>m7aeLKmdd&>eq5I*<@oOVMyDlY_eLdY+2UIsgh`yB(D=B&eRayAVC5% zaQ8qGQDD}!@>X)uAvx?`bRdteTyo8Ik9)~AHK$aiYPWRTYwRj}zt@c!3`l8{VNIi_ z`}OPB@BcO5Z!~HKp5GIeafi8s>afKO4^6(iNzNQ0U8 zjCSoAb~85HW@g24+sW+f@qXsNJ4*XW91Sw}{&+OtnR9=C#Gjdf1mM!`XrGJCL=0bN zU0Pj!{Mm;*3uvxR(6O+i(=)ltJ-lwux?q%gE+-oO3pg>eo_fD9dM2}(^GTyq<+a@< z<~}vmS)5LtzSY}MGyYSDRaxy5r_;=5*wRyr)mZ~$%f(m|W6P|Cu@*mtoo85x4p4H6 zzDvI@I|aNe>@?t4Fn3x}u*%Nhd-bnazkpxiI?K*s?U`Q~j?p;_o}bSe?}=nMN^i#9 zgn^Z9FRSw57H1*r53|+&Fxuv!8esi+JCywi&szO>G)_Z3r$!pXNbZIGIPC63vCL{w zH|;-&NN|}acsdqw*DHypf_?+9jaU9Rn$&n~9GXXlY5dZd8lg3{(b`iBt&_UHggh=9 zk4=1ejK(U3Wc<{h8oQOp=G&M*@Y3pGZR#Bnx&|dUh>h)-* z3Ap97y4zyz)M3^|lD)|)Pn`6W{>HxUV}l^{H`)?Jc@}iK%zt7ZRe*P8VgJ*tN*W%$ zX&FW>m_3^3G8icd$e@>qK(RJRli=R4KV; zcZ|o-c|oVy>0|FWAVrS(Kn7z8N+6kqEjjH%ywu_%w6c7-x&8;2<9Pi}!o~wWV_#_w zlmmV6a0eUaC>Qp5F8XKCA>$eO=q|az{Gm}YveS6wc{JNFr4L&NW(w0{Fsvi%SJp=k z)X)@UfNe|AlB{}@%$-itwlZt|)y(XFY6=PvpBkTiyz#!|LT)^a;%x~sw>NJ0w?riN zH|```{Q(c&PP$qXH@eC2=g|lX^Ya^nWXv!jH}34;>Zk9Fx9;*$A~)_u!|--;_xgt9 z+oZi=6z``y*mz?I-!q_&Hib|zgNyaiepb6W=*twyN7vRtlcaNdhGk5?wcxncL%5%Q z8iwmv2T3;?$ZP223)OjriWye6w8sS`t6iBVQ_*J}EV%%@o9)%imE#c?nV;iRoDg-) ziX}AJx%U#;C(l-}?QRsaWSIFQ9u6oRbylHG;V6O0%sr>fTmc?(&GVYph}$4AYaNFa zE40t4I01voXgbR?^(E)4+-~h2|7Z+G!WuL0MiM`Goe7G1SxZ5((f>t@rsXgcPqSyQctw)tnTIyw7%d4cuIz_OsqBq@pwH}Fd0#?&~(yK5eqhZaK% zCAOmT04uEJu8J~Jc>?H~k`R1UZdKZhVQ*Tq0>$&(Ij$90NPqjVcK}9kyD^MY@|4_y zTA!e~vhWFqb-zNxXN!iUn$@>?8mcpgBYq7dlH7w) zom^ZLTp0{mnx{FFd4p&R{xY*i5z`VSOU)m0I4)i#(LbOwMGQS>9GFvE?4*$F)ZDcg zvLMR0dN#gn=033w9LzaWE1yHew)D)Bao}Rkotjf;+rlaj&~SAav8HY@f(XCs9aaEk z?D|L60W#64hxqUBSyzp`=OXvQe08_>eW=}R+}g8d<4Z)>!kk^2v&(bP%j)Ee@(c*; zDANOc6v|{CBE5q$*hlsOi5~8PlE_^fqPM3|E#~|il0W_1 zvu6T!7zxpx2|tJOPC!-4P!P30IXx3K2rUFHUIj(s@2Da9ZqDWXjC>jr?26!8h{`&z z5~PYRRd059ru_cUk=Gdt8G-8u!ohB#AZ}U6?_C{yw>F9W7fC0>O?>; z_@^}h{4l{exNY#l(zHU>g$^qZCBBVak4t$;(Wiah0nw&x+nii@4m}#GOY+Mf%2p_x zC|Uj&I$9fH=VbLx3W}&iBdbRsF%F$0$P&Q;p@P|v?$4&?PZ0a`q9RcMKmj!6Ev#dU`YI1MU8kDP-VcC7V?kACzYU`C-+qZ=}Uo1%JyHlOwSg}igkZ6 zEt_$0&M#G#li|)7L#I(htpzVg*WP-xSx(phw*&D7n?YYfDk&GkevBk@YhU?;dFeUx z1C%zLWT4uz%(gPWuFR6v=TNN}LG`=Z>|}2FR+-ei|4yD)h94ZuDaC8BINZ^xbU|k^ z-^GZEckQP5C+dG6P3CgkD(&k6;}(rlN-6$<8nRq*lbUZ*LlIA0N0WK{(Fp8S32S?) zl%N!@J+roCc1p`=9tou&pRUswazLFXxK*0YS~{Q1C4R6X*nqEGaC{Yl+g$(;4@EGhpNuf%=C28Al7Kw*-DauX6KxfP8PP7k8}{?(bIV zWtFGM)NxbnbZUGF@Q%8#rI{LLmRKD#bp^dR+jwfTCR@gAL)~;X;aX3LmqEhh4dn@* zS9^^mc~KPUDCWtJsynWpP!)E!&u8~L&)x)<&9;q#S{3;+?C~h2v>b&t*O`Y6ko=)O zmE`m*Db<@_bt1ADd%nDgUvtkCUtt#ItSE4C@tN9($W^Ci4-sb-H#cUhC>h6PzL3j>b~uCm#{?XRJJVmHm)9!Om2-Sw9G7) z&K~Fa+K&kO$J8iAQF>EU|G&k!PAQ-zE$9YmN9&78QPked@09fANO3!ZODAQjs^nL3 zADHN&J}Ju$ypli=!EthCou?v^qB&Ib09hNw_f_O?tN2QBnGa4OvLB&;=+Un#{hTKh zP2I^4=7JvVFVy~&u0?4O!7s=7_W>?RCc5tb$*XIxeYmc8rrn#$JwB@)Mb1t9v2b5qmxHOlHjM!y4;B)u@~I#}4WCf~?OJ;A!tG9>8^ zC6_02bh18j9*TctY%0s4st26gHIWygaHbpyB{cPsAtB#!r|zyx71I-wIp8#MAAGyT zw)!Xa>83xC@{T|)D(D~NENLAswj8Yz5La8{TimM9FH?OeTRV5dla8m3MSI}gY z-XMw6@4k)#YCM$Vp@?YIm1)%7%PK%R9H$&>mB6-W&fLk&hqKC>XzNt=br9)PX3+$4 z=Oq`a?18-Of8v#NQAO33Z=Qusw8%$V=grAiUnJN(T-aG%mw33rM5&O~=KokZ=}*Yd z7j`ni$J9JDjto`Z!a7jh>elL^riEug`;vjm_t+dRITpu|D=T=^K_}ob2YB2fPwhi^ zrd{VqU%@$(tNGcY!T)Dp>2qzYT;I5v+Z`a6)Ize5+mIkLSIIChdj=R1Lu$xD9G3$* z*WcsSX65+itN5FIJE!otS diff --git a/segment_anything/modeling/__pycache__/prompt_encoder.cpython-39.pyc b/segment_anything/modeling/__pycache__/prompt_encoder.cpython-39.pyc deleted file mode 100644 index 9ba25808f7b3f9962f0a7cd337cb8ad6c678632c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7721 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 diff --git a/segment_anything/modeling/__pycache__/sam.cpython-39.pyc b/segment_anything/modeling/__pycache__/sam.cpython-39.pyc deleted file mode 100644 index c2088cabcc1c70ff68d2f09b1f29a98fc889f178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6702 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 P07L@phI96Vvzz|`f4_3K diff --git a/segment_anything/modeling/__pycache__/transformer.cpython-39.pyc b/segment_anything/modeling/__pycache__/transformer.cpython-39.pyc deleted file mode 100644 index 4636e8a4193d3ee7c434b01f8625f4645206bd7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6600 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 diff --git a/segment_anything/modeling/common.py b/segment_anything/modeling/common.py deleted file mode 100644 index 2bf1523..0000000 --- a/segment_anything/modeling/common.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -import torch.nn as nn - -from typing import Type - - -class MLPBlock(nn.Module): - def __init__( - self, - embedding_dim: int, - mlp_dim: int, - act: Type[nn.Module] = nn.GELU, - ) -> None: - super().__init__() - self.lin1 = nn.Linear(embedding_dim, mlp_dim) - self.lin2 = nn.Linear(mlp_dim, embedding_dim) - self.act = act() - - def forward(self, x: torch.Tensor) -> torch.Tensor: - return self.lin2(self.act(self.lin1(x))) - - -# From https://github.com/facebookresearch/detectron2/blob/main/detectron2/layers/batch_norm.py # noqa -# Itself from https://github.com/facebookresearch/ConvNeXt/blob/d1fa8f6fef0a165b27399986cc2bdacc92777e40/models/convnext.py#L119 # noqa -class LayerNorm2d(nn.Module): - def __init__(self, num_channels: int, eps: float = 1e-6) -> None: - super().__init__() - self.weight = nn.Parameter(torch.ones(num_channels)) - self.bias = nn.Parameter(torch.zeros(num_channels)) - self.eps = eps - - def forward(self, x: torch.Tensor) -> torch.Tensor: - u = x.mean(1, keepdim=True) - s = (x - u).pow(2).mean(1, keepdim=True) - x = (x - u) / torch.sqrt(s + self.eps) - x = self.weight[:, None, None] * x + self.bias[:, None, None] - return x diff --git a/segment_anything/modeling/image_encoder.py b/segment_anything/modeling/image_encoder.py deleted file mode 100644 index a6ad9ad..0000000 --- a/segment_anything/modeling/image_encoder.py +++ /dev/null @@ -1,395 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -import torch.nn as nn -import torch.nn.functional as F - -from typing import Optional, Tuple, Type - -from .common import LayerNorm2d, MLPBlock - - -# This class and its supporting functions below lightly adapted from the ViTDet backbone available at: https://github.com/facebookresearch/detectron2/blob/main/detectron2/modeling/backbone/vit.py # noqa -class ImageEncoderViT(nn.Module): - def __init__( - self, - img_size: int = 1024, - patch_size: int = 16, - in_chans: int = 3, - embed_dim: int = 768, - depth: int = 12, - num_heads: int = 12, - mlp_ratio: float = 4.0, - out_chans: int = 256, - qkv_bias: bool = True, - norm_layer: Type[nn.Module] = nn.LayerNorm, - act_layer: Type[nn.Module] = nn.GELU, - use_abs_pos: bool = True, - use_rel_pos: bool = False, - rel_pos_zero_init: bool = True, - window_size: int = 0, - global_attn_indexes: Tuple[int, ...] = (), - ) -> None: - """ - Args: - img_size (int): Input image size. - patch_size (int): Patch size. - in_chans (int): Number of input image channels. - embed_dim (int): Patch embedding dimension. - depth (int): Depth of ViT. - num_heads (int): Number of attention heads in each ViT block. - mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. - qkv_bias (bool): If True, add a learnable bias to query, key, value. - norm_layer (nn.Module): Normalization layer. - act_layer (nn.Module): Activation layer. - use_abs_pos (bool): If True, use absolute positional embeddings. - use_rel_pos (bool): If True, add relative positional embeddings to the attention map. - rel_pos_zero_init (bool): If True, zero initialize relative positional parameters. - window_size (int): Window size for window attention blocks. - global_attn_indexes (list): Indexes for blocks using global attention. - """ - super().__init__() - self.img_size = img_size - - self.patch_embed = PatchEmbed( - kernel_size=(patch_size, patch_size), - stride=(patch_size, patch_size), - in_chans=in_chans, - embed_dim=embed_dim, - ) - - self.pos_embed: Optional[nn.Parameter] = None - if use_abs_pos: - # Initialize absolute positional embedding with pretrain image size. - self.pos_embed = nn.Parameter( - torch.zeros(1, img_size // patch_size, img_size // patch_size, embed_dim) - ) - - self.blocks = nn.ModuleList() - for i in range(depth): - block = Block( - dim=embed_dim, - num_heads=num_heads, - mlp_ratio=mlp_ratio, - qkv_bias=qkv_bias, - norm_layer=norm_layer, - act_layer=act_layer, - use_rel_pos=use_rel_pos, - rel_pos_zero_init=rel_pos_zero_init, - window_size=window_size if i not in global_attn_indexes else 0, - input_size=(img_size // patch_size, img_size // patch_size), - ) - self.blocks.append(block) - - self.neck = nn.Sequential( - nn.Conv2d( - embed_dim, - out_chans, - kernel_size=1, - bias=False, - ), - LayerNorm2d(out_chans), - nn.Conv2d( - out_chans, - out_chans, - kernel_size=3, - padding=1, - bias=False, - ), - LayerNorm2d(out_chans), - ) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - x = self.patch_embed(x) - if self.pos_embed is not None: - x = x + self.pos_embed - - for blk in self.blocks: - x = blk(x) - - x = self.neck(x.permute(0, 3, 1, 2)) - - return x - - -class Block(nn.Module): - """Transformer blocks with support of window attention and residual propagation blocks""" - - def __init__( - self, - dim: int, - num_heads: int, - mlp_ratio: float = 4.0, - qkv_bias: bool = True, - norm_layer: Type[nn.Module] = nn.LayerNorm, - act_layer: Type[nn.Module] = nn.GELU, - use_rel_pos: bool = False, - rel_pos_zero_init: bool = True, - window_size: int = 0, - input_size: Optional[Tuple[int, int]] = None, - ) -> None: - """ - Args: - dim (int): Number of input channels. - num_heads (int): Number of attention heads in each ViT block. - mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. - qkv_bias (bool): If True, add a learnable bias to query, key, value. - norm_layer (nn.Module): Normalization layer. - act_layer (nn.Module): Activation layer. - use_rel_pos (bool): If True, add relative positional embeddings to the attention map. - rel_pos_zero_init (bool): If True, zero initialize relative positional parameters. - window_size (int): Window size for window attention blocks. If it equals 0, then - use global attention. - input_size (int or None): Input resolution for calculating the relative positional - parameter size. - """ - super().__init__() - self.norm1 = norm_layer(dim) - self.attn = Attention( - dim, - num_heads=num_heads, - qkv_bias=qkv_bias, - use_rel_pos=use_rel_pos, - rel_pos_zero_init=rel_pos_zero_init, - input_size=input_size if window_size == 0 else (window_size, window_size), - ) - - self.norm2 = norm_layer(dim) - self.mlp = MLPBlock(embedding_dim=dim, mlp_dim=int(dim * mlp_ratio), act=act_layer) - - self.window_size = window_size - - def forward(self, x: torch.Tensor) -> torch.Tensor: - shortcut = x - x = self.norm1(x) - # Window partition - if self.window_size > 0: - H, W = x.shape[1], x.shape[2] - x, pad_hw = window_partition(x, self.window_size) - - x = self.attn(x) - # Reverse window partition - if self.window_size > 0: - x = window_unpartition(x, self.window_size, pad_hw, (H, W)) - - x = shortcut + x - x = x + self.mlp(self.norm2(x)) - - return x - - -class Attention(nn.Module): - """Multi-head Attention block with relative position embeddings.""" - - def __init__( - self, - dim: int, - num_heads: int = 8, - qkv_bias: bool = True, - use_rel_pos: bool = False, - rel_pos_zero_init: bool = True, - input_size: Optional[Tuple[int, int]] = None, - ) -> None: - """ - Args: - dim (int): Number of input channels. - num_heads (int): Number of attention heads. - qkv_bias (bool: If True, add a learnable bias to query, key, value. - rel_pos (bool): If True, add relative positional embeddings to the attention map. - rel_pos_zero_init (bool): If True, zero initialize relative positional parameters. - input_size (int or None): Input resolution for calculating the relative positional - parameter size. - """ - super().__init__() - self.num_heads = num_heads - head_dim = dim // num_heads - self.scale = head_dim**-0.5 - - self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) - self.proj = nn.Linear(dim, dim) - - self.use_rel_pos = use_rel_pos - if self.use_rel_pos: - assert ( - input_size is not None - ), "Input size must be provided if using relative positional encoding." - # initialize relative positional embeddings - self.rel_pos_h = nn.Parameter(torch.zeros(2 * input_size[0] - 1, head_dim)) - self.rel_pos_w = nn.Parameter(torch.zeros(2 * input_size[1] - 1, head_dim)) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - B, H, W, _ = x.shape - # qkv with shape (3, B, nHead, H * W, C) - qkv = self.qkv(x).reshape(B, H * W, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4) - # q, k, v with shape (B * nHead, H * W, C) - q, k, v = qkv.reshape(3, B * self.num_heads, H * W, -1).unbind(0) - - attn = (q * self.scale) @ k.transpose(-2, -1) - - if self.use_rel_pos: - attn = add_decomposed_rel_pos(attn, q, self.rel_pos_h, self.rel_pos_w, (H, W), (H, W)) - - attn = attn.softmax(dim=-1) - x = (attn @ v).view(B, self.num_heads, H, W, -1).permute(0, 2, 3, 1, 4).reshape(B, H, W, -1) - x = self.proj(x) - - return x - - -def window_partition(x: torch.Tensor, window_size: int) -> Tuple[torch.Tensor, Tuple[int, int]]: - """ - Partition into non-overlapping windows with padding if needed. - Args: - x (tensor): input tokens with [B, H, W, C]. - window_size (int): window size. - - Returns: - windows: windows after partition with [B * num_windows, window_size, window_size, C]. - (Hp, Wp): padded height and width before partition - """ - B, H, W, C = x.shape - - pad_h = (window_size - H % window_size) % window_size - pad_w = (window_size - W % window_size) % window_size - if pad_h > 0 or pad_w > 0: - x = F.pad(x, (0, 0, 0, pad_w, 0, pad_h)) - Hp, Wp = H + pad_h, W + pad_w - - x = x.view(B, Hp // window_size, window_size, Wp // window_size, window_size, C) - windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C) - return windows, (Hp, Wp) - - -def window_unpartition( - windows: torch.Tensor, window_size: int, pad_hw: Tuple[int, int], hw: Tuple[int, int] -) -> torch.Tensor: - """ - Window unpartition into original sequences and removing padding. - Args: - x (tensor): input tokens with [B * num_windows, window_size, window_size, C]. - window_size (int): window size. - pad_hw (Tuple): padded height and width (Hp, Wp). - hw (Tuple): original height and width (H, W) before padding. - - Returns: - x: unpartitioned sequences with [B, H, W, C]. - """ - Hp, Wp = pad_hw - H, W = hw - B = windows.shape[0] // (Hp * Wp // window_size // window_size) - x = windows.view(B, Hp // window_size, Wp // window_size, window_size, window_size, -1) - x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, Hp, Wp, -1) - - if Hp > H or Wp > W: - x = x[:, :H, :W, :].contiguous() - return x - - -def get_rel_pos(q_size: int, k_size: int, rel_pos: torch.Tensor) -> torch.Tensor: - """ - Get relative positional embeddings according to the relative positions of - query and key sizes. - Args: - q_size (int): size of query q. - k_size (int): size of key k. - rel_pos (Tensor): relative position embeddings (L, C). - - Returns: - Extracted positional embeddings according to relative positions. - """ - max_rel_dist = int(2 * max(q_size, k_size) - 1) - # Interpolate rel pos if needed. - if rel_pos.shape[0] != max_rel_dist: - # Interpolate rel pos. - rel_pos_resized = F.interpolate( - rel_pos.reshape(1, rel_pos.shape[0], -1).permute(0, 2, 1), - size=max_rel_dist, - mode="linear", - ) - rel_pos_resized = rel_pos_resized.reshape(-1, max_rel_dist).permute(1, 0) - else: - rel_pos_resized = rel_pos - - # Scale the coords with short length if shapes for q and k are different. - q_coords = torch.arange(q_size)[:, None] * max(k_size / q_size, 1.0) - k_coords = torch.arange(k_size)[None, :] * max(q_size / k_size, 1.0) - relative_coords = (q_coords - k_coords) + (k_size - 1) * max(q_size / k_size, 1.0) - - return rel_pos_resized[relative_coords.long()] - - -def add_decomposed_rel_pos( - attn: torch.Tensor, - q: torch.Tensor, - rel_pos_h: torch.Tensor, - rel_pos_w: torch.Tensor, - q_size: Tuple[int, int], - k_size: Tuple[int, int], -) -> torch.Tensor: - """ - Calculate decomposed Relative Positional Embeddings from :paper:`mvitv2`. - https://github.com/facebookresearch/mvit/blob/19786631e330df9f3622e5402b4a419a263a2c80/mvit/models/attention.py # noqa B950 - Args: - attn (Tensor): attention map. - q (Tensor): query q in the attention layer with shape (B, q_h * q_w, C). - rel_pos_h (Tensor): relative position embeddings (Lh, C) for height axis. - rel_pos_w (Tensor): relative position embeddings (Lw, C) for width axis. - q_size (Tuple): spatial sequence size of query q with (q_h, q_w). - k_size (Tuple): spatial sequence size of key k with (k_h, k_w). - - Returns: - attn (Tensor): attention map with added relative positional embeddings. - """ - q_h, q_w = q_size - k_h, k_w = k_size - Rh = get_rel_pos(q_h, k_h, rel_pos_h) - Rw = get_rel_pos(q_w, k_w, rel_pos_w) - - B, _, dim = q.shape - r_q = q.reshape(B, q_h, q_w, dim) - rel_h = torch.einsum("bhwc,hkc->bhwk", r_q, Rh) - rel_w = torch.einsum("bhwc,wkc->bhwk", r_q, Rw) - - attn = ( - attn.view(B, q_h, q_w, k_h, k_w) + rel_h[:, :, :, :, None] + rel_w[:, :, :, None, :] - ).view(B, q_h * q_w, k_h * k_w) - - return attn - - -class PatchEmbed(nn.Module): - """ - Image to Patch Embedding. - """ - - def __init__( - self, - kernel_size: Tuple[int, int] = (16, 16), - stride: Tuple[int, int] = (16, 16), - padding: Tuple[int, int] = (0, 0), - in_chans: int = 3, - embed_dim: int = 768, - ) -> None: - """ - Args: - kernel_size (Tuple): kernel size of the projection layer. - stride (Tuple): stride of the projection layer. - padding (Tuple): padding size of the projection layer. - in_chans (int): Number of input image channels. - embed_dim (int): embed_dim (int): Patch embedding dimension. - """ - super().__init__() - - self.proj = nn.Conv2d( - in_chans, embed_dim, kernel_size=kernel_size, stride=stride, padding=padding - ) - - def forward(self, x: torch.Tensor) -> torch.Tensor: - x = self.proj(x) - # B C H W -> B H W C - x = x.permute(0, 2, 3, 1) - return x diff --git a/segment_anything/modeling/mask_decoder.py b/segment_anything/modeling/mask_decoder.py deleted file mode 100644 index 3e86f7c..0000000 --- a/segment_anything/modeling/mask_decoder.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -from torch import nn -from torch.nn import functional as F - -from typing import List, Tuple, Type - -from .common import LayerNorm2d - - -class MaskDecoder(nn.Module): - def __init__( - self, - *, - transformer_dim: int, - transformer: nn.Module, - num_multimask_outputs: int = 3, - activation: Type[nn.Module] = nn.GELU, - iou_head_depth: int = 3, - iou_head_hidden_dim: int = 256, - ) -> None: - """ - Predicts masks given an image and prompt embeddings, using a - tranformer architecture. - - Arguments: - transformer_dim (int): the channel dimension of the transformer - transformer (nn.Module): the transformer used to predict masks - num_multimask_outputs (int): the number of masks to predict - when disambiguating masks - activation (nn.Module): the type of activation to use when - upscaling masks - iou_head_depth (int): the depth of the MLP used to predict - mask quality - iou_head_hidden_dim (int): the hidden dimension of the MLP - used to predict mask quality - """ - super().__init__() - self.transformer_dim = transformer_dim - self.transformer = transformer - - self.num_multimask_outputs = num_multimask_outputs - - self.iou_token = nn.Embedding(1, transformer_dim) - self.num_mask_tokens = num_multimask_outputs + 1 - self.mask_tokens = nn.Embedding(self.num_mask_tokens, transformer_dim) - - self.output_upscaling = nn.Sequential( - nn.ConvTranspose2d(transformer_dim, transformer_dim // 4, kernel_size=2, stride=2), - LayerNorm2d(transformer_dim // 4), - activation(), - nn.ConvTranspose2d(transformer_dim // 4, transformer_dim // 8, kernel_size=2, stride=2), - activation(), - ) - self.output_hypernetworks_mlps = nn.ModuleList( - [ - MLP(transformer_dim, transformer_dim, transformer_dim // 8, 3) - for i in range(self.num_mask_tokens) - ] - ) - - self.iou_prediction_head = MLP( - transformer_dim, iou_head_hidden_dim, self.num_mask_tokens, iou_head_depth - ) - - def forward( - self, - image_embeddings: torch.Tensor, - image_pe: torch.Tensor, - sparse_prompt_embeddings: torch.Tensor, - dense_prompt_embeddings: torch.Tensor, - multimask_output: bool, - ) -> Tuple[torch.Tensor, torch.Tensor]: - """ - Predict masks given image and prompt embeddings. - - Arguments: - image_embeddings (torch.Tensor): the embeddings from the image encoder - image_pe (torch.Tensor): positional encoding with the shape of image_embeddings - sparse_prompt_embeddings (torch.Tensor): the embeddings of the points and boxes - dense_prompt_embeddings (torch.Tensor): the embeddings of the mask inputs - multimask_output (bool): Whether to return multiple masks or a single - mask. - - Returns: - torch.Tensor: batched predicted masks - torch.Tensor: batched predictions of mask quality - """ - masks, iou_pred = self.predict_masks( - image_embeddings=image_embeddings, - image_pe=image_pe, - sparse_prompt_embeddings=sparse_prompt_embeddings, - dense_prompt_embeddings=dense_prompt_embeddings, - ) - - # Select the correct mask or masks for outptu - if multimask_output: - mask_slice = slice(1, None) - else: - mask_slice = slice(0, 1) - masks = masks[:, mask_slice, :, :] - iou_pred = iou_pred[:, mask_slice] - - # Prepare output - return masks, iou_pred - - def predict_masks( - self, - image_embeddings: torch.Tensor, - image_pe: torch.Tensor, - sparse_prompt_embeddings: torch.Tensor, - dense_prompt_embeddings: torch.Tensor, - ) -> Tuple[torch.Tensor, torch.Tensor]: - """Predicts masks. See 'forward' for more details.""" - # Concatenate output tokens - output_tokens = torch.cat([self.iou_token.weight, self.mask_tokens.weight], dim=0) - output_tokens = output_tokens.unsqueeze(0).expand(sparse_prompt_embeddings.size(0), -1, -1) - tokens = torch.cat((output_tokens, sparse_prompt_embeddings), dim=1) - - # Expand per-image data in batch direction to be per-mask - src = torch.repeat_interleave(image_embeddings, tokens.shape[0], dim=0) - src = src + dense_prompt_embeddings - pos_src = torch.repeat_interleave(image_pe, tokens.shape[0], dim=0) - b, c, h, w = src.shape - - # Run the transformer - hs, src = self.transformer(src, pos_src, tokens) - iou_token_out = hs[:, 0, :] - mask_tokens_out = hs[:, 1 : (1 + self.num_mask_tokens), :] - - # Upscale mask embeddings and predict masks using the mask tokens - src = src.transpose(1, 2).view(b, c, h, w) - upscaled_embedding = self.output_upscaling(src) - hyper_in_list: List[torch.Tensor] = [] - for i in range(self.num_mask_tokens): - hyper_in_list.append(self.output_hypernetworks_mlps[i](mask_tokens_out[:, i, :])) - hyper_in = torch.stack(hyper_in_list, dim=1) - b, c, h, w = upscaled_embedding.shape - masks = (hyper_in @ upscaled_embedding.view(b, c, h * w)).view(b, -1, h, w) - - # Generate mask quality predictions - iou_pred = self.iou_prediction_head(iou_token_out) - - return masks, iou_pred - - -# Lightly adapted from -# https://github.com/facebookresearch/MaskFormer/blob/main/mask_former/modeling/transformer/transformer_predictor.py # noqa -class MLP(nn.Module): - def __init__( - self, - input_dim: int, - hidden_dim: int, - output_dim: int, - num_layers: int, - sigmoid_output: bool = False, - ) -> None: - super().__init__() - self.num_layers = num_layers - h = [hidden_dim] * (num_layers - 1) - self.layers = nn.ModuleList( - nn.Linear(n, k) for n, k in zip([input_dim] + h, h + [output_dim]) - ) - self.sigmoid_output = sigmoid_output - - def forward(self, x): - for i, layer in enumerate(self.layers): - x = F.relu(layer(x)) if i < self.num_layers - 1 else layer(x) - if self.sigmoid_output: - x = F.sigmoid(x) - return x diff --git a/segment_anything/modeling/prompt_encoder.py b/segment_anything/modeling/prompt_encoder.py deleted file mode 100644 index c3143f4..0000000 --- a/segment_anything/modeling/prompt_encoder.py +++ /dev/null @@ -1,214 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import numpy as np -import torch -from torch import nn - -from typing import Any, Optional, Tuple, Type - -from .common import LayerNorm2d - - -class PromptEncoder(nn.Module): - def __init__( - self, - embed_dim: int, - image_embedding_size: Tuple[int, int], - input_image_size: Tuple[int, int], - mask_in_chans: int, - activation: Type[nn.Module] = nn.GELU, - ) -> None: - """ - Encodes prompts for input to SAM's mask decoder. - - Arguments: - embed_dim (int): The prompts' embedding dimension - image_embedding_size (tuple(int, int)): The spatial size of the - image embedding, as (H, W). - input_image_size (int): The padded size of the image as input - to the image encoder, as (H, W). - mask_in_chans (int): The number of hidden channels used for - encoding input masks. - activation (nn.Module): The activation to use when encoding - input masks. - """ - super().__init__() - self.embed_dim = embed_dim - self.input_image_size = input_image_size - self.image_embedding_size = image_embedding_size - self.pe_layer = PositionEmbeddingRandom(embed_dim // 2) - - self.num_point_embeddings: int = 4 # pos/neg point + 2 box corners - point_embeddings = [nn.Embedding(1, embed_dim) for i in range(self.num_point_embeddings)] - self.point_embeddings = nn.ModuleList(point_embeddings) - self.not_a_point_embed = nn.Embedding(1, embed_dim) - - self.mask_input_size = (4 * image_embedding_size[0], 4 * image_embedding_size[1]) - self.mask_downscaling = nn.Sequential( - nn.Conv2d(1, mask_in_chans // 4, kernel_size=2, stride=2), - LayerNorm2d(mask_in_chans // 4), - activation(), - nn.Conv2d(mask_in_chans // 4, mask_in_chans, kernel_size=2, stride=2), - LayerNorm2d(mask_in_chans), - activation(), - nn.Conv2d(mask_in_chans, embed_dim, kernel_size=1), - ) - self.no_mask_embed = nn.Embedding(1, embed_dim) - - def get_dense_pe(self) -> torch.Tensor: - """ - Returns the positional encoding used to encode point prompts, - applied to a dense set of points the shape of the image encoding. - - Returns: - torch.Tensor: Positional encoding with shape - 1x(embed_dim)x(embedding_h)x(embedding_w) - """ - return self.pe_layer(self.image_embedding_size).unsqueeze(0) - - def _embed_points( - self, - points: torch.Tensor, - labels: torch.Tensor, - pad: bool, - ) -> torch.Tensor: - """Embeds point prompts.""" - points = points + 0.5 # Shift to center of pixel - if pad: - padding_point = torch.zeros((points.shape[0], 1, 2), device=points.device) - padding_label = -torch.ones((labels.shape[0], 1), device=labels.device) - points = torch.cat([points, padding_point], dim=1) - labels = torch.cat([labels, padding_label], dim=1) - point_embedding = self.pe_layer.forward_with_coords(points, self.input_image_size) - point_embedding[labels == -1] = 0.0 - point_embedding[labels == -1] += self.not_a_point_embed.weight - point_embedding[labels == 0] += self.point_embeddings[0].weight - point_embedding[labels == 1] += self.point_embeddings[1].weight - return point_embedding - - def _embed_boxes(self, boxes: torch.Tensor) -> torch.Tensor: - """Embeds box prompts.""" - boxes = boxes + 0.5 # Shift to center of pixel - coords = boxes.reshape(-1, 2, 2) - corner_embedding = self.pe_layer.forward_with_coords(coords, self.input_image_size) - corner_embedding[:, 0, :] += self.point_embeddings[2].weight - corner_embedding[:, 1, :] += self.point_embeddings[3].weight - return corner_embedding - - def _embed_masks(self, masks: torch.Tensor) -> torch.Tensor: - """Embeds mask inputs.""" - mask_embedding = self.mask_downscaling(masks) - return mask_embedding - - def _get_batch_size( - self, - points: Optional[Tuple[torch.Tensor, torch.Tensor]], - boxes: Optional[torch.Tensor], - masks: Optional[torch.Tensor], - ) -> int: - """ - Gets the batch size of the output given the batch size of the input prompts. - """ - if points is not None: - return points[0].shape[0] - elif boxes is not None: - return boxes.shape[0] - elif masks is not None: - return masks.shape[0] - else: - return 1 - - def _get_device(self) -> torch.device: - return self.point_embeddings[0].weight.device - - def forward( - self, - points: Optional[Tuple[torch.Tensor, torch.Tensor]], - boxes: Optional[torch.Tensor], - masks: Optional[torch.Tensor], - ) -> Tuple[torch.Tensor, torch.Tensor]: - """ - Embeds different types of prompts, returning both sparse and dense - embeddings. - - Arguments: - points (tuple(torch.Tensor, torch.Tensor) or none): point coordinates - and labels to embed. - boxes (torch.Tensor or none): boxes to embed - masks (torch.Tensor or none): masks to embed - - Returns: - torch.Tensor: sparse embeddings for the points and boxes, with shape - BxNx(embed_dim), where N is determined by the number of input points - and boxes. - torch.Tensor: dense embeddings for the masks, in the shape - Bx(embed_dim)x(embed_H)x(embed_W) - """ - bs = self._get_batch_size(points, boxes, masks) - sparse_embeddings = torch.empty((bs, 0, self.embed_dim), device=self._get_device()) - if points is not None: - coords, labels = points - point_embeddings = self._embed_points(coords, labels, pad=(boxes is None)) - sparse_embeddings = torch.cat([sparse_embeddings, point_embeddings], dim=1) - if boxes is not None: - box_embeddings = self._embed_boxes(boxes) - sparse_embeddings = torch.cat([sparse_embeddings, box_embeddings], dim=1) - - if masks is not None: - dense_embeddings = self._embed_masks(masks) - else: - dense_embeddings = self.no_mask_embed.weight.reshape(1, -1, 1, 1).expand( - bs, -1, self.image_embedding_size[0], self.image_embedding_size[1] - ) - - return sparse_embeddings, dense_embeddings - - -class PositionEmbeddingRandom(nn.Module): - """ - Positional encoding using random spatial frequencies. - """ - - def __init__(self, num_pos_feats: int = 64, scale: Optional[float] = None) -> None: - super().__init__() - if scale is None or scale <= 0.0: - scale = 1.0 - self.register_buffer( - "positional_encoding_gaussian_matrix", - scale * torch.randn((2, num_pos_feats)), - ) - - def _pe_encoding(self, coords: torch.Tensor) -> torch.Tensor: - """Positionally encode points that are normalized to [0,1].""" - # assuming coords are in [0, 1]^2 square and have d_1 x ... x d_n x 2 shape - coords = 2 * coords - 1 - coords = coords @ self.positional_encoding_gaussian_matrix - coords = 2 * np.pi * coords - # outputs d_1 x ... x d_n x C shape - return torch.cat([torch.sin(coords), torch.cos(coords)], dim=-1) - - def forward(self, size: Tuple[int, int]) -> torch.Tensor: - """Generate positional encoding for a grid of the specified size.""" - h, w = size - device: Any = self.positional_encoding_gaussian_matrix.device - grid = torch.ones((h, w), device=device, dtype=torch.float32) - y_embed = grid.cumsum(dim=0) - 0.5 - x_embed = grid.cumsum(dim=1) - 0.5 - y_embed = y_embed / h - x_embed = x_embed / w - - pe = self._pe_encoding(torch.stack([x_embed, y_embed], dim=-1)) - return pe.permute(2, 0, 1) # C x H x W - - def forward_with_coords( - self, coords_input: torch.Tensor, image_size: Tuple[int, int] - ) -> torch.Tensor: - """Positionally encode points that are not normalized to [0,1].""" - coords = coords_input.clone() - coords[:, :, 0] = coords[:, :, 0] / image_size[1] - coords[:, :, 1] = coords[:, :, 1] / image_size[0] - return self._pe_encoding(coords.to(torch.float)) # B x N x C diff --git a/segment_anything/modeling/sam.py b/segment_anything/modeling/sam.py deleted file mode 100644 index 303bc2f..0000000 --- a/segment_anything/modeling/sam.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -from torch import nn -from torch.nn import functional as F - -from typing import Any, Dict, List, Tuple - -from .image_encoder import ImageEncoderViT -from .mask_decoder import MaskDecoder -from .prompt_encoder import PromptEncoder - - -class Sam(nn.Module): - mask_threshold: float = 0.0 - image_format: str = "RGB" - - def __init__( - self, - image_encoder: ImageEncoderViT, - prompt_encoder: PromptEncoder, - mask_decoder: MaskDecoder, - pixel_mean: List[float] = [123.675, 116.28, 103.53], - pixel_std: List[float] = [58.395, 57.12, 57.375], - ) -> None: - """ - SAM predicts object masks from an image and input prompts. - - Arguments: - image_encoder (ImageEncoderViT): The backbone used to encode the - image into image embeddings that allow for efficient mask prediction. - prompt_encoder (PromptEncoder): Encodes various types of input prompts. - mask_decoder (MaskDecoder): Predicts masks from the image embeddings - and encoded prompts. - pixel_mean (list(float)): Mean values for normalizing pixels in the input image. - pixel_std (list(float)): Std values for normalizing pixels in the input image. - """ - super().__init__() - self.image_encoder = image_encoder - self.prompt_encoder = prompt_encoder - self.mask_decoder = mask_decoder - self.register_buffer("pixel_mean", torch.Tensor(pixel_mean).view(-1, 1, 1), False) - self.register_buffer("pixel_std", torch.Tensor(pixel_std).view(-1, 1, 1), False) - - @property - def device(self) -> Any: - return self.pixel_mean.device - - @torch.no_grad() - def forward( - self, - batched_input: List[Dict[str, Any]], - multimask_output: bool, - ) -> List[Dict[str, torch.Tensor]]: - """ - Predicts masks end-to-end from provided images and prompts. - If prompts are not known in advance, using SamPredictor is - recommended over calling the model directly. - - Arguments: - batched_input (list(dict)): A list over input images, each a - dictionary with the following keys. A prompt key can be - excluded if it is not present. - 'image': The image as a torch tensor in 3xHxW format, - already transformed for input to the model. - 'original_size': (tuple(int, int)) The original size of - the image before transformation, as (H, W). - 'point_coords': (torch.Tensor) Batched point prompts for - this image, with shape BxNx2. Already transformed to the - input frame of the model. - 'point_labels': (torch.Tensor) Batched labels for point prompts, - with shape BxN. - 'boxes': (torch.Tensor) Batched box inputs, with shape Bx4. - Already transformed to the input frame of the model. - 'mask_inputs': (torch.Tensor) Batched mask inputs to the model, - in the form Bx1xHxW. - multimask_output (bool): Whether the model should predict multiple - disambiguating masks, or return a single mask. - - Returns: - (list(dict)): A list over input images, where each element is - as dictionary with the following keys. - 'masks': (torch.Tensor) Batched binary mask predictions, - with shape BxCxHxW, where B is the number of input promts, - C is determiend by multimask_output, and (H, W) is the - original size of the image. - 'iou_predictions': (torch.Tensor) The model's predictions - of mask quality, in shape BxC. - 'low_res_logits': (torch.Tensor) Low resolution logits with - shape BxCxHxW, where H=W=256. Can be passed as mask input - to subsequent iterations of prediction. - """ - input_images = torch.stack([self.preprocess(x["image"]) for x in batched_input], dim=0) - image_embeddings = self.image_encoder(input_images) - - outputs = [] - for image_record, curr_embedding in zip(batched_input, image_embeddings): - if "point_coords" in image_record: - points = (image_record["point_coords"], image_record["point_labels"]) - else: - points = None - sparse_embeddings, dense_embeddings = self.prompt_encoder( - points=points, - boxes=image_record.get("boxes", None), - masks=image_record.get("mask_inputs", None), - ) - low_res_masks, iou_predictions = self.mask_decoder( - image_embeddings=curr_embedding.unsqueeze(0), - image_pe=self.prompt_encoder.get_dense_pe(), - sparse_prompt_embeddings=sparse_embeddings, - dense_prompt_embeddings=dense_embeddings, - multimask_output=multimask_output, - ) - masks = self.postprocess_masks( - low_res_masks, - input_size=image_record["image"].shape[-2:], - original_size=image_record["original_size"], - ) - masks = masks > self.mask_threshold - outputs.append( - { - "masks": masks, - "iou_predictions": iou_predictions, - "low_res_logits": low_res_masks, - } - ) - return outputs - - def postprocess_masks( - self, - masks: torch.Tensor, - input_size: Tuple[int, ...], - original_size: Tuple[int, ...], - ) -> torch.Tensor: - """ - Remove padding and upscale masks to the original image size. - - Arguments: - masks (torch.Tensor): Batched masks from the mask_decoder, - in BxCxHxW format. - input_size (tuple(int, int)): The size of the image input to the - model, in (H, W) format. Used to remove padding. - original_size (tuple(int, int)): The original size of the image - before resizing for input to the model, in (H, W) format. - - Returns: - (torch.Tensor): Batched masks in BxCxHxW format, where (H, W) - is given by original_size. - """ - masks = F.interpolate( - masks, - (self.image_encoder.img_size, self.image_encoder.img_size), - mode="bilinear", - align_corners=False, - ) - masks = masks[..., : input_size[0], : input_size[1]] - masks = F.interpolate(masks, original_size, mode="bilinear", align_corners=False) - return masks - - def preprocess(self, x: torch.Tensor) -> torch.Tensor: - """Normalize pixel values and pad to a square input.""" - # Normalize colors - x = (x - self.pixel_mean) / self.pixel_std - - # Pad - h, w = x.shape[-2:] - padh = self.image_encoder.img_size - h - padw = self.image_encoder.img_size - w - x = F.pad(x, (0, padw, 0, padh)) - return x diff --git a/segment_anything/modeling/transformer.py b/segment_anything/modeling/transformer.py deleted file mode 100644 index f1a2812..0000000 --- a/segment_anything/modeling/transformer.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -from torch import Tensor, nn - -import math -from typing import Tuple, Type - -from .common import MLPBlock - - -class TwoWayTransformer(nn.Module): - def __init__( - self, - depth: int, - embedding_dim: int, - num_heads: int, - mlp_dim: int, - activation: Type[nn.Module] = nn.ReLU, - attention_downsample_rate: int = 2, - ) -> None: - """ - A transformer decoder that attends to an input image using - queries whose positional embedding is supplied. - - Args: - depth (int): number of layers in the transformer - embedding_dim (int): the channel dimension for the input embeddings - num_heads (int): the number of heads for multihead attention. Must - divide embedding_dim - mlp_dim (int): the channel dimension internal to the MLP block - activation (nn.Module): the activation to use in the MLP block - """ - super().__init__() - self.depth = depth - self.embedding_dim = embedding_dim - self.num_heads = num_heads - self.mlp_dim = mlp_dim - self.layers = nn.ModuleList() - - for i in range(depth): - self.layers.append( - TwoWayAttentionBlock( - embedding_dim=embedding_dim, - num_heads=num_heads, - mlp_dim=mlp_dim, - activation=activation, - attention_downsample_rate=attention_downsample_rate, - skip_first_layer_pe=(i == 0), - ) - ) - - self.final_attn_token_to_image = Attention( - embedding_dim, num_heads, downsample_rate=attention_downsample_rate - ) - self.norm_final_attn = nn.LayerNorm(embedding_dim) - - def forward( - self, - image_embedding: Tensor, - image_pe: Tensor, - point_embedding: Tensor, - ) -> Tuple[Tensor, Tensor]: - """ - Args: - image_embedding (torch.Tensor): image to attend to. Should be shape - B x embedding_dim x h x w for any h and w. - image_pe (torch.Tensor): the positional encoding to add to the image. Must - have the same shape as image_embedding. - point_embedding (torch.Tensor): the embedding to add to the query points. - Must have shape B x N_points x embedding_dim for any N_points. - - Returns: - torch.Tensor: the processed point_embedding - torch.Tensor: the processed image_embedding - """ - # BxCxHxW -> BxHWxC == B x N_image_tokens x C - bs, c, h, w = image_embedding.shape - image_embedding = image_embedding.flatten(2).permute(0, 2, 1) - image_pe = image_pe.flatten(2).permute(0, 2, 1) - - # Prepare queries - queries = point_embedding - keys = image_embedding - - # Apply transformer blocks and final layernorm - for layer in self.layers: - queries, keys = layer( - queries=queries, - keys=keys, - query_pe=point_embedding, - key_pe=image_pe, - ) - - # Apply the final attenion layer from the points to the image - q = queries + point_embedding - k = keys + image_pe - attn_out = self.final_attn_token_to_image(q=q, k=k, v=keys) - queries = queries + attn_out - queries = self.norm_final_attn(queries) - - return queries, keys - - -class TwoWayAttentionBlock(nn.Module): - def __init__( - self, - embedding_dim: int, - num_heads: int, - mlp_dim: int = 2048, - activation: Type[nn.Module] = nn.ReLU, - attention_downsample_rate: int = 2, - skip_first_layer_pe: bool = False, - ) -> None: - """ - A transformer block with four layers: (1) self-attention of sparse - inputs, (2) cross attention of sparse inputs to dense inputs, (3) mlp - block on sparse inputs, and (4) cross attention of dense inputs to sparse - inputs. - - Arguments: - embedding_dim (int): the channel dimension of the embeddings - num_heads (int): the number of heads in the attention layers - mlp_dim (int): the hidden dimension of the mlp block - activation (nn.Module): the activation of the mlp block - skip_first_layer_pe (bool): skip the PE on the first layer - """ - super().__init__() - self.self_attn = Attention(embedding_dim, num_heads) - self.norm1 = nn.LayerNorm(embedding_dim) - - self.cross_attn_token_to_image = Attention( - embedding_dim, num_heads, downsample_rate=attention_downsample_rate - ) - self.norm2 = nn.LayerNorm(embedding_dim) - - self.mlp = MLPBlock(embedding_dim, mlp_dim, activation) - self.norm3 = nn.LayerNorm(embedding_dim) - - self.norm4 = nn.LayerNorm(embedding_dim) - self.cross_attn_image_to_token = Attention( - embedding_dim, num_heads, downsample_rate=attention_downsample_rate - ) - - self.skip_first_layer_pe = skip_first_layer_pe - - def forward( - self, queries: Tensor, keys: Tensor, query_pe: Tensor, key_pe: Tensor - ) -> Tuple[Tensor, Tensor]: - # Self attention block - if self.skip_first_layer_pe: - queries = self.self_attn(q=queries, k=queries, v=queries) - else: - q = queries + query_pe - attn_out = self.self_attn(q=q, k=q, v=queries) - queries = queries + attn_out - queries = self.norm1(queries) - - # Cross attention block, tokens attending to image embedding - q = queries + query_pe - k = keys + key_pe - attn_out = self.cross_attn_token_to_image(q=q, k=k, v=keys) - queries = queries + attn_out - queries = self.norm2(queries) - - # MLP block - mlp_out = self.mlp(queries) - queries = queries + mlp_out - queries = self.norm3(queries) - - # Cross attention block, image embedding attending to tokens - q = queries + query_pe - k = keys + key_pe - attn_out = self.cross_attn_image_to_token(q=k, k=q, v=queries) - keys = keys + attn_out - keys = self.norm4(keys) - - return queries, keys - - -class Attention(nn.Module): - """ - An attention layer that allows for downscaling the size of the embedding - after projection to queries, keys, and values. - """ - - def __init__( - self, - embedding_dim: int, - num_heads: int, - downsample_rate: int = 1, - ) -> None: - super().__init__() - self.embedding_dim = embedding_dim - self.internal_dim = embedding_dim // downsample_rate - self.num_heads = num_heads - assert self.internal_dim % num_heads == 0, "num_heads must divide embedding_dim." - - self.q_proj = nn.Linear(embedding_dim, self.internal_dim) - self.k_proj = nn.Linear(embedding_dim, self.internal_dim) - self.v_proj = nn.Linear(embedding_dim, self.internal_dim) - self.out_proj = nn.Linear(self.internal_dim, embedding_dim) - - def _separate_heads(self, x: Tensor, num_heads: int) -> Tensor: - b, n, c = x.shape - x = x.reshape(b, n, num_heads, c // num_heads) - return x.transpose(1, 2) # B x N_heads x N_tokens x C_per_head - - def _recombine_heads(self, x: Tensor) -> Tensor: - b, n_heads, n_tokens, c_per_head = x.shape - x = x.transpose(1, 2) - return x.reshape(b, n_tokens, n_heads * c_per_head) # B x N_tokens x C - - def forward(self, q: Tensor, k: Tensor, v: Tensor) -> Tensor: - # Input projections - q = self.q_proj(q) - k = self.k_proj(k) - v = self.v_proj(v) - - # Separate into heads - q = self._separate_heads(q, self.num_heads) - k = self._separate_heads(k, self.num_heads) - v = self._separate_heads(v, self.num_heads) - - # Attention - _, _, _, c_per_head = q.shape - attn = q @ k.permute(0, 1, 3, 2) # B x N_heads x N_tokens x N_tokens - attn = attn / math.sqrt(c_per_head) - attn = torch.softmax(attn, dim=-1) - - # Get output - out = attn @ v - out = self._recombine_heads(out) - out = self.out_proj(out) - - return out diff --git a/segment_anything/predictor.py b/segment_anything/predictor.py deleted file mode 100644 index 57c089d..0000000 --- a/segment_anything/predictor.py +++ /dev/null @@ -1,269 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import numpy as np -import torch - -from segment_anything.modeling import Sam - -from typing import Optional, Tuple - -from .utils.transforms import ResizeLongestSide - - -class SamPredictor: - def __init__( - self, - sam_model: Sam, - ) -> None: - """ - Uses SAM to calculate the image embedding for an image, and then - allow repeated, efficient mask prediction given prompts. - - Arguments: - sam_model (Sam): The model to use for mask prediction. - """ - super().__init__() - self.model = sam_model - self.transform = ResizeLongestSide(sam_model.image_encoder.img_size) - self.reset_image() - - def set_image( - self, - image: np.ndarray, - image_format: str = "RGB", - ) -> None: - """ - Calculates the image embeddings for the provided image, allowing - masks to be predicted with the 'predict' method. - - Arguments: - image (np.ndarray): The image for calculating masks. Expects an - image in HWC uint8 format, with pixel values in [0, 255]. - image_format (str): The color format of the image, in ['RGB', 'BGR']. - """ - assert image_format in [ - "RGB", - "BGR", - ], f"image_format must be in ['RGB', 'BGR'], is {image_format}." - if image_format != self.model.image_format: - image = image[..., ::-1] - - # Transform the image to the form expected by the model - input_image = self.transform.apply_image(image) - input_image_torch = torch.as_tensor(input_image, device=self.device) - input_image_torch = input_image_torch.permute(2, 0, 1).contiguous()[None, :, :, :] - - self.set_torch_image(input_image_torch, image.shape[:2]) - - @torch.no_grad() - def set_torch_image( - self, - transformed_image: torch.Tensor, - original_image_size: Tuple[int, ...], - ) -> None: - """ - Calculates the image embeddings for the provided image, allowing - masks to be predicted with the 'predict' method. Expects the input - image to be already transformed to the format expected by the model. - - Arguments: - transformed_image (torch.Tensor): The input image, with shape - 1x3xHxW, which has been transformed with ResizeLongestSide. - original_image_size (tuple(int, int)): The size of the image - before transformation, in (H, W) format. - """ - assert ( - len(transformed_image.shape) == 4 - and transformed_image.shape[1] == 3 - and max(*transformed_image.shape[2:]) == self.model.image_encoder.img_size - ), f"set_torch_image input must be BCHW with long side {self.model.image_encoder.img_size}." - self.reset_image() - - self.original_size = original_image_size - self.input_size = tuple(transformed_image.shape[-2:]) - input_image = self.model.preprocess(transformed_image) - self.features = self.model.image_encoder(input_image) - self.is_image_set = True - - def predict( - self, - point_coords: Optional[np.ndarray] = None, - point_labels: Optional[np.ndarray] = None, - box: Optional[np.ndarray] = None, - mask_input: Optional[np.ndarray] = None, - multimask_output: bool = True, - return_logits: bool = False, - ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: - """ - Predict masks for the given input prompts, using the currently set image. - - Arguments: - point_coords (np.ndarray or None): A Nx2 array of point prompts to the - model. Each point is in (X,Y) in pixels. - point_labels (np.ndarray or None): A length N array of labels for the - point prompts. 1 indicates a foreground point and 0 indicates a - background point. - box (np.ndarray or None): A length 4 array given a box prompt to the - model, in XYXY format. - mask_input (np.ndarray): A low resolution mask input to the model, typically - coming from a previous prediction iteration. Has form 1xHxW, where - for SAM, H=W=256. - multimask_output (bool): If true, the model will return three masks. - For ambiguous input prompts (such as a single click), this will often - produce better masks than a single prediction. If only a single - mask is needed, the model's predicted quality score can be used - to select the best mask. For non-ambiguous prompts, such as multiple - input prompts, multimask_output=False can give better results. - return_logits (bool): If true, returns un-thresholded masks logits - instead of a binary mask. - - Returns: - (np.ndarray): The output masks in CxHxW format, where C is the - number of masks, and (H, W) is the original image size. - (np.ndarray): An array of length C containing the model's - predictions for the quality of each mask. - (np.ndarray): An array of shape CxHxW, where C is the number - of masks and H=W=256. These low resolution logits can be passed to - a subsequent iteration as mask input. - """ - if not self.is_image_set: - raise RuntimeError("An image must be set with .set_image(...) before mask prediction.") - - # Transform input prompts - coords_torch, labels_torch, box_torch, mask_input_torch = None, None, None, None - if point_coords is not None: - assert ( - point_labels is not None - ), "point_labels must be supplied if point_coords is supplied." - point_coords = self.transform.apply_coords(point_coords, self.original_size) - coords_torch = torch.as_tensor(point_coords, dtype=torch.float, device=self.device) - labels_torch = torch.as_tensor(point_labels, dtype=torch.int, device=self.device) - coords_torch, labels_torch = coords_torch[None, :, :], labels_torch[None, :] - if box is not None: - box = self.transform.apply_boxes(box, self.original_size) - box_torch = torch.as_tensor(box, dtype=torch.float, device=self.device) - box_torch = box_torch[None, :] - if mask_input is not None: - mask_input_torch = torch.as_tensor(mask_input, dtype=torch.float, device=self.device) - mask_input_torch = mask_input_torch[None, :, :, :] - - masks, iou_predictions, low_res_masks = self.predict_torch( - coords_torch, - labels_torch, - box_torch, - mask_input_torch, - multimask_output, - return_logits=return_logits, - ) - - masks = masks[0].detach().cpu().numpy() - iou_predictions = iou_predictions[0].detach().cpu().numpy() - low_res_masks = low_res_masks[0].detach().cpu().numpy() - return masks, iou_predictions, low_res_masks - - @torch.no_grad() - def predict_torch( - self, - point_coords: Optional[torch.Tensor], - point_labels: Optional[torch.Tensor], - boxes: Optional[torch.Tensor] = None, - mask_input: Optional[torch.Tensor] = None, - multimask_output: bool = True, - return_logits: bool = False, - ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: - """ - Predict masks for the given input prompts, using the currently set image. - Input prompts are batched torch tensors and are expected to already be - transformed to the input frame using ResizeLongestSide. - - Arguments: - point_coords (torch.Tensor or None): A BxNx2 array of point prompts to the - model. Each point is in (X,Y) in pixels. - point_labels (torch.Tensor or None): A BxN array of labels for the - point prompts. 1 indicates a foreground point and 0 indicates a - background point. - box (np.ndarray or None): A Bx4 array given a box prompt to the - model, in XYXY format. - mask_input (np.ndarray): A low resolution mask input to the model, typically - coming from a previous prediction iteration. Has form Bx1xHxW, where - for SAM, H=W=256. Masks returned by a previous iteration of the - predict method do not need further transformation. - multimask_output (bool): If true, the model will return three masks. - For ambiguous input prompts (such as a single click), this will often - produce better masks than a single prediction. If only a single - mask is needed, the model's predicted quality score can be used - to select the best mask. For non-ambiguous prompts, such as multiple - input prompts, multimask_output=False can give better results. - return_logits (bool): If true, returns un-thresholded masks logits - instead of a binary mask. - - Returns: - (torch.Tensor): The output masks in BxCxHxW format, where C is the - number of masks, and (H, W) is the original image size. - (torch.Tensor): An array of shape BxC containing the model's - predictions for the quality of each mask. - (torch.Tensor): An array of shape BxCxHxW, where C is the number - of masks and H=W=256. These low res logits can be passed to - a subsequent iteration as mask input. - """ - if not self.is_image_set: - raise RuntimeError("An image must be set with .set_image(...) before mask prediction.") - - if point_coords is not None: - points = (point_coords, point_labels) - else: - points = None - - # Embed prompts - sparse_embeddings, dense_embeddings = self.model.prompt_encoder( - points=points, - boxes=boxes, - masks=mask_input, - ) - - # Predict masks - low_res_masks, iou_predictions = self.model.mask_decoder( - image_embeddings=self.features, - image_pe=self.model.prompt_encoder.get_dense_pe(), - sparse_prompt_embeddings=sparse_embeddings, - dense_prompt_embeddings=dense_embeddings, - multimask_output=multimask_output, - ) - - # Upscale the masks to the original image resolution - masks = self.model.postprocess_masks(low_res_masks, self.input_size, self.original_size) - - if not return_logits: - masks = masks > self.model.mask_threshold - - return masks, iou_predictions, low_res_masks - - def get_image_embedding(self) -> torch.Tensor: - """ - Returns the image embeddings for the currently set image, with - shape 1xCxHxW, where C is the embedding dimension and (H,W) are - the embedding spatial dimension of SAM (typically C=256, H=W=64). - """ - if not self.is_image_set: - raise RuntimeError( - "An image must be set with .set_image(...) to generate an embedding." - ) - assert self.features is not None, "Features must exist if an image has been set." - return self.features - - @property - def device(self) -> torch.device: - return self.model.device - - def reset_image(self) -> None: - """Resets the currently set image.""" - self.is_image_set = False - self.features = None - self.orig_h = None - self.orig_w = None - self.input_h = None - self.input_w = None diff --git a/segment_anything/utils/__init__.py b/segment_anything/utils/__init__.py deleted file mode 100644 index 5277f46..0000000 --- a/segment_anything/utils/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. diff --git a/segment_anything/utils/__pycache__/__init__.cpython-38.pyc b/segment_anything/utils/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index ac5aff69e6ef041167fea2ece9f396afc2e26640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210 zcmWIL<>g`kf}Qz#DMx|yV-N=!FakLaKwQiMBvKfH88jLFRx%WUgb~EAa{bWa)S_bj z^2EIK;*8Y1bbX)9q@u*4N`2q_q|BUD1(*Ef(%jU%l4AYj{M@?4f`XjXI_I4H(iEUX zvA%DmduEA8X;M&XL4L7*aAIz}PkxZ2esO9#NKbrXUS&x}CeYB*lFXc9{rLFIyv&mL Yc)fzkTO2mI`6;D2sdgX-eFkC%0Cb-_jsO4v diff --git a/segment_anything/utils/__pycache__/__init__.cpython-39.pyc b/segment_anything/utils/__pycache__/__init__.cpython-39.pyc deleted file mode 100644 index f08880b5529f97c928b174b6e59892edca5cdd03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218 zcmYe~<>g`kf}Qz#DMx|yV-N=!FakLaKwQiMBvKfH88jLFRx%WUgb~EAdi~Ji)S_bj z^2EIK;*8Y1bbX)9q@u*4N`2q_q|BUD1(*Ef(%jU%l4AYj{M@?4f`XjXI_I4H(iEUX zvA%DmduEA8X;M&XL4L7*acVk9scvFkWl2UR&@8AxJY1l(Br~U2KR!M)FS8^*Uaz3? U7Kcr4eoARhsvXE-pMjVG0H+>5RsaA1 diff --git a/segment_anything/utils/__pycache__/amg.cpython-38.pyc b/segment_anything/utils/__pycache__/amg.cpython-38.pyc deleted file mode 100644 index c7e6a3cd31c76357391030672674e532c8f2fa68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12265 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 diff --git a/segment_anything/utils/__pycache__/amg.cpython-39.pyc b/segment_anything/utils/__pycache__/amg.cpython-39.pyc deleted file mode 100644 index 2eb2dcd9013e01aaeccef41f57e596a31182b2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12168 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 diff --git a/segment_anything/utils/__pycache__/transforms.cpython-38.pyc b/segment_anything/utils/__pycache__/transforms.cpython-38.pyc deleted file mode 100644 index c0f1c5b526736d4d05b0041b8921d80eae8d291a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4032 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 H12Fz~Mga(+ diff --git a/segment_anything/utils/amg.py b/segment_anything/utils/amg.py deleted file mode 100644 index 3a13777..0000000 --- a/segment_anything/utils/amg.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import numpy as np -import torch - -import math -from copy import deepcopy -from itertools import product -from typing import Any, Dict, Generator, ItemsView, List, Tuple - - -class MaskData: - """ - A structure for storing masks and their related data in batched format. - Implements basic filtering and concatenation. - """ - - def __init__(self, **kwargs) -> None: - for v in kwargs.values(): - assert isinstance( - v, (list, np.ndarray, torch.Tensor) - ), "MaskData only supports list, numpy arrays, and torch tensors." - self._stats = dict(**kwargs) - - def __setitem__(self, key: str, item: Any) -> None: - assert isinstance( - item, (list, np.ndarray, torch.Tensor) - ), "MaskData only supports list, numpy arrays, and torch tensors." - self._stats[key] = item - - def __delitem__(self, key: str) -> None: - del self._stats[key] - - def __getitem__(self, key: str) -> Any: - return self._stats[key] - - def items(self) -> ItemsView[str, Any]: - return self._stats.items() - - def filter(self, keep: torch.Tensor) -> None: - for k, v in self._stats.items(): - if v is None: - self._stats[k] = None - elif isinstance(v, torch.Tensor): - self._stats[k] = v[torch.as_tensor(keep, device=v.device)] - elif isinstance(v, np.ndarray): - self._stats[k] = v[keep.detach().cpu().numpy()] - elif isinstance(v, list) and keep.dtype == torch.bool: - self._stats[k] = [a for i, a in enumerate(v) if keep[i]] - elif isinstance(v, list): - self._stats[k] = [v[i] for i in keep] - else: - raise TypeError(f"MaskData key {k} has an unsupported type {type(v)}.") - - def cat(self, new_stats: "MaskData") -> None: - for k, v in new_stats.items(): - if k not in self._stats or self._stats[k] is None: - self._stats[k] = deepcopy(v) - elif isinstance(v, torch.Tensor): - self._stats[k] = torch.cat([self._stats[k], v], dim=0) - elif isinstance(v, np.ndarray): - self._stats[k] = np.concatenate([self._stats[k], v], axis=0) - elif isinstance(v, list): - self._stats[k] = self._stats[k] + deepcopy(v) - else: - raise TypeError(f"MaskData key {k} has an unsupported type {type(v)}.") - - def to_numpy(self) -> None: - for k, v in self._stats.items(): - if isinstance(v, torch.Tensor): - self._stats[k] = v.detach().cpu().numpy() - - -def is_box_near_crop_edge( - boxes: torch.Tensor, crop_box: List[int], orig_box: List[int], atol: float = 20.0 -) -> torch.Tensor: - """Filter masks at the edge of a crop, but not at the edge of the original image.""" - crop_box_torch = torch.as_tensor(crop_box, dtype=torch.float, device=boxes.device) - orig_box_torch = torch.as_tensor(orig_box, dtype=torch.float, device=boxes.device) - boxes = uncrop_boxes_xyxy(boxes, crop_box).float() - near_crop_edge = torch.isclose(boxes, crop_box_torch[None, :], atol=atol, rtol=0) - near_image_edge = torch.isclose(boxes, orig_box_torch[None, :], atol=atol, rtol=0) - near_crop_edge = torch.logical_and(near_crop_edge, ~near_image_edge) - return torch.any(near_crop_edge, dim=1) - - -def box_xyxy_to_xywh(box_xyxy: torch.Tensor) -> torch.Tensor: - box_xywh = deepcopy(box_xyxy) - box_xywh[2] = box_xywh[2] - box_xywh[0] - box_xywh[3] = box_xywh[3] - box_xywh[1] - return box_xywh - - -def batch_iterator(batch_size: int, *args) -> Generator[List[Any], None, None]: - assert len(args) > 0 and all( - len(a) == len(args[0]) for a in args - ), "Batched iteration must have inputs of all the same size." - n_batches = len(args[0]) // batch_size + int(len(args[0]) % batch_size != 0) - for b in range(n_batches): - yield [arg[b * batch_size : (b + 1) * batch_size] for arg in args] - - -def mask_to_rle_pytorch(tensor: torch.Tensor) -> List[Dict[str, Any]]: - """ - Encodes masks to an uncompressed RLE, in the format expected by - pycoco tools. - """ - # Put in fortran order and flatten h,w - b, h, w = tensor.shape - tensor = tensor.permute(0, 2, 1).flatten(1) - - # Compute change indices - diff = tensor[:, 1:] ^ tensor[:, :-1] - change_indices = diff.nonzero() - - # Encode run length - out = [] - for i in range(b): - cur_idxs = change_indices[change_indices[:, 0] == i, 1] - cur_idxs = torch.cat( - [ - torch.tensor([0], dtype=cur_idxs.dtype, device=cur_idxs.device), - cur_idxs + 1, - torch.tensor([h * w], dtype=cur_idxs.dtype, device=cur_idxs.device), - ] - ) - btw_idxs = cur_idxs[1:] - cur_idxs[:-1] - counts = [] if tensor[i, 0] == 0 else [0] - counts.extend(btw_idxs.detach().cpu().tolist()) - out.append({"size": [h, w], "counts": counts}) - return out - - -def rle_to_mask(rle: Dict[str, Any]) -> np.ndarray: - """Compute a binary mask from an uncompressed RLE.""" - h, w = rle["size"] - mask = np.empty(h * w, dtype=bool) - idx = 0 - parity = False - for count in rle["counts"]: - mask[idx : idx + count] = parity - idx += count - parity ^= True - mask = mask.reshape(w, h) - return mask.transpose() # Put in C order - - -def area_from_rle(rle: Dict[str, Any]) -> int: - return sum(rle["counts"][1::2]) - - -def calculate_stability_score( - masks: torch.Tensor, mask_threshold: float, threshold_offset: float -) -> torch.Tensor: - """ - Computes the stability score for a batch of masks. The stability - score is the IoU between the binary masks obtained by thresholding - the predicted mask logits at high and low values. - """ - # One mask is always contained inside the other. - # Save memory by preventing unnecesary cast to torch.int64 - intersections = ( - (masks > (mask_threshold + threshold_offset)) - .sum(-1, dtype=torch.int16) - .sum(-1, dtype=torch.int32) - ) - unions = ( - (masks > (mask_threshold - threshold_offset)) - .sum(-1, dtype=torch.int16) - .sum(-1, dtype=torch.int32) - ) - return intersections / unions - - -def build_point_grid(n_per_side: int) -> np.ndarray: - """Generates a 2D grid of points evenly spaced in [0,1]x[0,1].""" - offset = 1 / (2 * n_per_side) - points_one_side = np.linspace(offset, 1 - offset, n_per_side) - points_x = np.tile(points_one_side[None, :], (n_per_side, 1)) - points_y = np.tile(points_one_side[:, None], (1, n_per_side)) - points = np.stack([points_x, points_y], axis=-1).reshape(-1, 2) - return points - - -def build_all_layer_point_grids( - n_per_side: int, n_layers: int, scale_per_layer: int -) -> List[np.ndarray]: - """Generates point grids for all crop layers.""" - points_by_layer = [] - for i in range(n_layers + 1): - n_points = int(n_per_side / (scale_per_layer**i)) - points_by_layer.append(build_point_grid(n_points)) - return points_by_layer - - -def generate_crop_boxes( - im_size: Tuple[int, ...], n_layers: int, overlap_ratio: float -) -> Tuple[List[List[int]], List[int]]: - """ - Generates a list of crop boxes of different sizes. Each layer - has (2**i)**2 boxes for the ith layer. - """ - crop_boxes, layer_idxs = [], [] - im_h, im_w = im_size - short_side = min(im_h, im_w) - - # Original image - crop_boxes.append([0, 0, im_w, im_h]) - layer_idxs.append(0) - - def crop_len(orig_len, n_crops, overlap): - return int(math.ceil((overlap * (n_crops - 1) + orig_len) / n_crops)) - - for i_layer in range(n_layers): - n_crops_per_side = 2 ** (i_layer + 1) - overlap = int(overlap_ratio * short_side * (2 / n_crops_per_side)) - - crop_w = crop_len(im_w, n_crops_per_side, overlap) - crop_h = crop_len(im_h, n_crops_per_side, overlap) - - crop_box_x0 = [int((crop_w - overlap) * i) for i in range(n_crops_per_side)] - crop_box_y0 = [int((crop_h - overlap) * i) for i in range(n_crops_per_side)] - - # Crops in XYWH format - for x0, y0 in product(crop_box_x0, crop_box_y0): - box = [x0, y0, min(x0 + crop_w, im_w), min(y0 + crop_h, im_h)] - crop_boxes.append(box) - layer_idxs.append(i_layer + 1) - - return crop_boxes, layer_idxs - - -def uncrop_boxes_xyxy(boxes: torch.Tensor, crop_box: List[int]) -> torch.Tensor: - x0, y0, _, _ = crop_box - offset = torch.tensor([[x0, y0, x0, y0]], device=boxes.device) - # Check if boxes has a channel dimension - if len(boxes.shape) == 3: - offset = offset.unsqueeze(1) - return boxes + offset - - -def uncrop_points(points: torch.Tensor, crop_box: List[int]) -> torch.Tensor: - x0, y0, _, _ = crop_box - offset = torch.tensor([[x0, y0]], device=points.device) - # Check if points has a channel dimension - if len(points.shape) == 3: - offset = offset.unsqueeze(1) - return points + offset - - -def uncrop_masks( - masks: torch.Tensor, crop_box: List[int], orig_h: int, orig_w: int -) -> torch.Tensor: - x0, y0, x1, y1 = crop_box - if x0 == 0 and y0 == 0 and x1 == orig_w and y1 == orig_h: - return masks - # Coordinate transform masks - pad_x, pad_y = orig_w - (x1 - x0), orig_h - (y1 - y0) - pad = (x0, pad_x - x0, y0, pad_y - y0) - return torch.nn.functional.pad(masks, pad, value=0) - - -def remove_small_regions( - mask: np.ndarray, area_thresh: float, mode: str -) -> Tuple[np.ndarray, bool]: - """ - Removes small disconnected regions and holes in a mask. Returns the - mask and an indicator of if the mask has been modified. - """ - import cv2 # type: ignore - - assert mode in ["holes", "islands"] - correct_holes = mode == "holes" - working_mask = (correct_holes ^ mask).astype(np.uint8) - n_labels, regions, stats, _ = cv2.connectedComponentsWithStats(working_mask, 8) - sizes = stats[:, -1][1:] # Row 0 is background label - small_regions = [i + 1 for i, s in enumerate(sizes) if s < area_thresh] - if len(small_regions) == 0: - return mask, False - fill_labels = [0] + small_regions - if not correct_holes: - fill_labels = [i for i in range(n_labels) if i not in fill_labels] - # If every region is below threshold, keep largest - if len(fill_labels) == 0: - fill_labels = [int(np.argmax(sizes)) + 1] - mask = np.isin(regions, fill_labels) - return mask, True - - -def coco_encode_rle(uncompressed_rle: Dict[str, Any]) -> Dict[str, Any]: - from pycocotools import mask as mask_utils # type: ignore - - h, w = uncompressed_rle["size"] - rle = mask_utils.frPyObjects(uncompressed_rle, h, w) - rle["counts"] = rle["counts"].decode("utf-8") # Necessary to serialize with json - return rle - - -def batched_mask_to_box(masks: torch.Tensor) -> torch.Tensor: - """ - Calculates boxes in XYXY format around masks. Return [0,0,0,0] for - an empty mask. For input shape C1xC2x...xHxW, the output shape is C1xC2x...x4. - """ - # torch.max below raises an error on empty inputs, just skip in this case - if torch.numel(masks) == 0: - return torch.zeros(*masks.shape[:-2], 4, device=masks.device) - - # Normalize shape to CxHxW - shape = masks.shape - h, w = shape[-2:] - if len(shape) > 2: - masks = masks.flatten(0, -3) - else: - masks = masks.unsqueeze(0) - - # Get top and bottom edges - in_height, _ = torch.max(masks, dim=-1) - in_height_coords = in_height * torch.arange(h, device=in_height.device)[None, :] - bottom_edges, _ = torch.max(in_height_coords, dim=-1) - in_height_coords = in_height_coords + h * (~in_height) - top_edges, _ = torch.min(in_height_coords, dim=-1) - - # Get left and right edges - in_width, _ = torch.max(masks, dim=-2) - in_width_coords = in_width * torch.arange(w, device=in_width.device)[None, :] - right_edges, _ = torch.max(in_width_coords, dim=-1) - in_width_coords = in_width_coords + w * (~in_width) - left_edges, _ = torch.min(in_width_coords, dim=-1) - - # If the mask is empty the right edge will be to the left of the left edge. - # Replace these boxes with [0, 0, 0, 0] - empty_filter = (right_edges < left_edges) | (bottom_edges < top_edges) - out = torch.stack([left_edges, top_edges, right_edges, bottom_edges], dim=-1) - out = out * (~empty_filter).unsqueeze(-1) - - # Return to original shape - if len(shape) > 2: - out = out.reshape(*shape[:-2], 4) - else: - out = out[0] - - return out diff --git a/segment_anything/utils/onnx.py b/segment_anything/utils/onnx.py deleted file mode 100644 index 4297b31..0000000 --- a/segment_anything/utils/onnx.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import torch -import torch.nn as nn -from torch.nn import functional as F - -from typing import Tuple - -from ..modeling import Sam -from .amg import calculate_stability_score - - -class SamOnnxModel(nn.Module): - """ - This model should not be called directly, but is used in ONNX export. - It combines the prompt encoder, mask decoder, and mask postprocessing of Sam, - with some functions modified to enable model tracing. Also supports extra - options controlling what information. See the ONNX export script for details. - """ - - def __init__( - self, - model: Sam, - return_single_mask: bool, - use_stability_score: bool = False, - return_extra_metrics: bool = False, - ) -> None: - super().__init__() - self.mask_decoder = model.mask_decoder - self.model = model - self.img_size = model.image_encoder.img_size - self.return_single_mask = return_single_mask - self.use_stability_score = use_stability_score - self.stability_score_offset = 1.0 - self.return_extra_metrics = return_extra_metrics - - @staticmethod - def resize_longest_image_size( - input_image_size: torch.Tensor, longest_side: int - ) -> torch.Tensor: - input_image_size = input_image_size.to(torch.float32) - scale = longest_side / torch.max(input_image_size) - transformed_size = scale * input_image_size - transformed_size = torch.floor(transformed_size + 0.5).to(torch.int64) - return transformed_size - - def _embed_points(self, point_coords: torch.Tensor, point_labels: torch.Tensor) -> torch.Tensor: - point_coords = point_coords + 0.5 - point_coords = point_coords / self.img_size - point_embedding = self.model.prompt_encoder.pe_layer._pe_encoding(point_coords) - point_labels = point_labels.unsqueeze(-1).expand_as(point_embedding) - - point_embedding = point_embedding * (point_labels != -1) - point_embedding = point_embedding + self.model.prompt_encoder.not_a_point_embed.weight * ( - point_labels == -1 - ) - - for i in range(self.model.prompt_encoder.num_point_embeddings): - point_embedding = point_embedding + self.model.prompt_encoder.point_embeddings[ - i - ].weight * (point_labels == i) - - return point_embedding - - def _embed_masks(self, input_mask: torch.Tensor, has_mask_input: torch.Tensor) -> torch.Tensor: - mask_embedding = has_mask_input * self.model.prompt_encoder.mask_downscaling(input_mask) - mask_embedding = mask_embedding + ( - 1 - has_mask_input - ) * self.model.prompt_encoder.no_mask_embed.weight.reshape(1, -1, 1, 1) - return mask_embedding - - def mask_postprocessing(self, masks: torch.Tensor, orig_im_size: torch.Tensor) -> torch.Tensor: - masks = F.interpolate( - masks, - size=(self.img_size, self.img_size), - mode="bilinear", - align_corners=False, - ) - - prepadded_size = self.resize_longest_image_size(orig_im_size, self.img_size) - masks = masks[..., : int(prepadded_size[0]), : int(prepadded_size[1])] - - orig_im_size = orig_im_size.to(torch.int64) - h, w = orig_im_size[0], orig_im_size[1] - masks = F.interpolate(masks, size=(h, w), mode="bilinear", align_corners=False) - return masks - - def select_masks( - self, masks: torch.Tensor, iou_preds: torch.Tensor, num_points: int - ) -> Tuple[torch.Tensor, torch.Tensor]: - # Determine if we should return the multiclick mask or not from the number of points. - # The reweighting is used to avoid control flow. - score_reweight = torch.tensor( - [[1000] + [0] * (self.model.mask_decoder.num_mask_tokens - 1)] - ).to(iou_preds.device) - score = iou_preds + (num_points - 2.5) * score_reweight - best_idx = torch.argmax(score, dim=1) - masks = masks[torch.arange(masks.shape[0]), best_idx, :, :].unsqueeze(1) - iou_preds = iou_preds[torch.arange(masks.shape[0]), best_idx].unsqueeze(1) - - return masks, iou_preds - - @torch.no_grad() - def forward( - self, - image_embeddings: torch.Tensor, - point_coords: torch.Tensor, - point_labels: torch.Tensor, - mask_input: torch.Tensor, - has_mask_input: torch.Tensor, - orig_im_size: torch.Tensor, - ): - sparse_embedding = self._embed_points(point_coords, point_labels) - dense_embedding = self._embed_masks(mask_input, has_mask_input) - - masks, scores = self.model.mask_decoder.predict_masks( - image_embeddings=image_embeddings, - image_pe=self.model.prompt_encoder.get_dense_pe(), - sparse_prompt_embeddings=sparse_embedding, - dense_prompt_embeddings=dense_embedding, - ) - - if self.use_stability_score: - scores = calculate_stability_score( - masks, self.model.mask_threshold, self.stability_score_offset - ) - - if self.return_single_mask: - masks, scores = self.select_masks(masks, scores, point_coords.shape[1]) - - upscaled_masks = self.mask_postprocessing(masks, orig_im_size) - - if self.return_extra_metrics: - stability_scores = calculate_stability_score( - upscaled_masks, self.model.mask_threshold, self.stability_score_offset - ) - areas = (upscaled_masks > self.model.mask_threshold).sum(-1).sum(-1) - return upscaled_masks, scores, stability_scores, areas, masks - - return upscaled_masks, scores, masks diff --git a/segment_anything/utils/transforms.py b/segment_anything/utils/transforms.py deleted file mode 100644 index 3ad3466..0000000 --- a/segment_anything/utils/transforms.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. - -# This source code is licensed under the license found in the -# LICENSE file in the root directory of this source tree. - -import numpy as np -import torch -from torch.nn import functional as F -from torchvision.transforms.functional import resize, to_pil_image # type: ignore - -from copy import deepcopy -from typing import Tuple - - -class ResizeLongestSide: - """ - Resizes images to longest side 'target_length', as well as provides - methods for resizing coordinates and boxes. Provides methods for - transforming both numpy array and batched torch tensors. - """ - - def __init__(self, target_length: int) -> None: - self.target_length = target_length - - def apply_image(self, image: np.ndarray) -> np.ndarray: - """ - Expects a numpy array with shape HxWxC in uint8 format. - """ - target_size = self.get_preprocess_shape(image.shape[0], image.shape[1], self.target_length) - return np.array(resize(to_pil_image(image), target_size)) - - def apply_coords(self, coords: np.ndarray, original_size: Tuple[int, ...]) -> np.ndarray: - """ - Expects a numpy array of length 2 in the final dimension. Requires the - original image size in (H, W) format. - """ - old_h, old_w = original_size - new_h, new_w = self.get_preprocess_shape( - original_size[0], original_size[1], self.target_length - ) - coords = deepcopy(coords).astype(float) - coords[..., 0] = coords[..., 0] * (new_w / old_w) - coords[..., 1] = coords[..., 1] * (new_h / old_h) - return coords - - def apply_boxes(self, boxes: np.ndarray, original_size: Tuple[int, ...]) -> np.ndarray: - """ - Expects a numpy array shape Bx4. Requires the original image size - in (H, W) format. - """ - boxes = self.apply_coords(boxes.reshape(-1, 2, 2), original_size) - return boxes.reshape(-1, 4) - - def apply_image_torch(self, image: torch.Tensor) -> torch.Tensor: - """ - Expects batched images with shape BxCxHxW and float format. This - transformation may not exactly match apply_image. apply_image is - the transformation expected by the model. - """ - # Expects an image in BCHW format. May not exactly match apply_image. - target_size = self.get_preprocess_shape(image.shape[0], image.shape[1], self.target_length) - return F.interpolate( - image, target_size, mode="bilinear", align_corners=False, antialias=True - ) - - def apply_coords_torch( - self, coords: torch.Tensor, original_size: Tuple[int, ...] - ) -> torch.Tensor: - """ - Expects a torch tensor with length 2 in the last dimension. Requires the - original image size in (H, W) format. - """ - old_h, old_w = original_size - new_h, new_w = self.get_preprocess_shape( - original_size[0], original_size[1], self.target_length - ) - coords = deepcopy(coords).to(torch.float) - coords[..., 0] = coords[..., 0] * (new_w / old_w) - coords[..., 1] = coords[..., 1] * (new_h / old_h) - return coords - - def apply_boxes_torch( - self, boxes: torch.Tensor, original_size: Tuple[int, ...] - ) -> torch.Tensor: - """ - Expects a torch tensor with shape Bx4. Requires the original image - size in (H, W) format. - """ - boxes = self.apply_coords_torch(boxes.reshape(-1, 2, 2), original_size) - return boxes.reshape(-1, 4) - - @staticmethod - def get_preprocess_shape(oldh: int, oldw: int, long_side_length: int) -> Tuple[int, int]: - """ - Compute the output size given input size and target long side length. - """ - scale = long_side_length * 1.0 / max(oldh, oldw) - newh, neww = oldh * scale, oldw * scale - neww = int(neww + 0.5) - newh = int(newh + 0.5) - return (newh, neww) From e4827904c1d89a8c249385ae7a94fdf503c8dd14 Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:30:28 +0200 Subject: [PATCH 2/7] add pycache and pretrained_weights folder to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 936da7d..1c8debb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.pth +__pycache__/ +pretrained_weights/ From c07f25822a4ddf86a4b22186bfbbbca38ea85db1 Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:37:25 +0200 Subject: [PATCH 3/7] remove pycache dir --- __pycache__/sam_lora.cpython-39.pyc | Bin 6120 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 __pycache__/sam_lora.cpython-39.pyc diff --git a/__pycache__/sam_lora.cpython-39.pyc b/__pycache__/sam_lora.cpython-39.pyc deleted file mode 100644 index 2730588144d23ada5f992e426a47a77495914fcb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6120 zcmcgw+ix6K8K3*k&aR!clekG5U`k8lP2IIks{&CHnoF-FZb^Ef)0Sa&=h&Y0?9BSi ztQ}jk1>sahf`A0#sj1{h^dWCZ{4YGr141AkA|YOocnB~2zBA)pJ4um{P-isXoXdAE zbI$kuzTX*dV#1Pe{bQ%)-#Q^lf2GX+OGoBKJjq`me94zXsV6&fPjM8P@(S{*ql&Z| zYL137HPjtlyp3MPsg!kQucAn@)T=s{DA7W_S95A2t%vpAgfk)1MmX6!>*^0azH(dtL|T@8)z@y;9mCgsh+l@ExOt3arQ>D z#hIv`E%ecssEh_Zca?d5Qsyb`Vz_3j&vyUu zYY?@A$e&#(>Y944qBOTcF@M){*GK90zO?6#b=vMmXK&$Y{VA=MPjV57RN9et8El zx2H!I+1gu%jzWs%MUX=qa0yRx6C#s#vFvx`Ar^fX3%aXN4tXs9E#n;#@WQgD;<|p^L9r4=xp7q}i4EajrBNqJOX#pLg!zrn{&F(qmr0xjAyx{_6h{h;MHn8tKpy{!nC(tQ2qgk!LZulUAo#jp70 zP0cY!dBSzgsgCl5>Y8Igd*Zh2Px^E(?&RdqitP6Z4IU`a64fjy~44Q5PiRcFX zCfJZ3b1ZFJbORkiz&!&G{KyOd?*kX_ljM0zBc2EIDJZ#+!D}i?-~t#7 zesX5~ndi@+FGoCQzZ1MQd+MUQ_<}2zCt~U1+NlCoX+=m?j3z!E=qr|=8kK9o&y@hZ zr`<=`OrSV!H5>F+4))mRL6pu4%_4q`s|Dh)^R zjwURy5ado3JSv`~1=C2S6u_~g>?#7o5m48(su+8yb#^r1D>d?nM|`ueqWg0P<2p#1kAC_{Z{P(0|W8#4cBy_*@` z$?lh6)uB=&-|g>@{G8eYy;1mt zFPKCoDFoyOXCMvHfsjhRP{nfzPjVX~lXt=8@5srd@ByhSca^S60am26p_=NMENoHv zl>n=xO@)#Z+xtKek03ShqfRJw{8Eq4I2!OE)O(=-Yq13(%z0+p7UwcLblCYwRJ znw!F70N=Sr9G88qIuk;B5MT}Tzobs8k8Hw7`gS17Y^7NS0lWBfelE(_sw0jgK4qOpM+Vax}@91SPTLNm!(U z_cSbW`|*+WJ>2qu&5^wkFAx~~Ya|ZZTq^%e>MA=Rb%GfH2XC6GnxW*fgi^KS3kORz zw81f`YYg==RT<*Ylj&rYnE_e(Y_G-)uH?@)_Y-czBO+9|CxH*+bebE?GO1i^Bu zUg@WaQ*G}h`4TmI1H!T3RwaJrH3YO3I3%rSF;_8b;e$sWwT?eQ4+(`0$(%%Nn2~27 zE%~IlT!6;_8+O>venW_z|K9~vo7wiPGT1J=$M-=T` zql_^1tv{C$X2Q1)M3~xv2=lK45vB%LsBho>vi$yok-t-{8f6GP{|D#i-^D)i7fHND zf*gT=K;oc%^OsPz)SN7goZ<<8o`kUU*C|CIr7&&bMUOK4E2MH20?tC`Sx)hVze(Z; z5cKomLdk;o_o?(+S$c7=bmRm34w!|hi=ZJQ;TY(Ci{{Bw5M=5UZ0a!dy0Z5sv)>nh z#>W4szM3*WhmH;)4n-jPY{7nLy!$@nR+sJ({(>OO9`He|?~^FVHTtoWH`ctM7ep)WAPVTX=!zxJwVnqi zpe5@(6(E)y+lCuJ1SO|#Ki~Jjei?m{{c@zTS`9)PT<)-KEiV?; zX-qYaHohuq=pRMT15a{u9bCt4Zv)+WbT$TaURY$E7oKnR(^agS)mdeowSJ7L+|$rs zQ@ckI?jG&dJrG2R6A_^kNP_cU^JLyg*b4oYa&cY;$%iK7s?SsWar zNSqa%!+Y7*@*wKa{{Sz{t$k_vWlp>4Opg>t)+rpuIsV|-Ey3_;611RBZ6A3QG|rjY zSJD#Qide#*qDc}e7l$daMc<(=3Vw*i;w@xz4aX^e-v*50TW+4k*!cBxo<3Rx{|3B; Yjt+I Date: Thu, 25 Apr 2024 16:49:40 +0200 Subject: [PATCH 4/7] move notebook to folder --- demo.ipynb => notebooks/demo.ipynb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename demo.ipynb => notebooks/demo.ipynb (100%) diff --git a/demo.ipynb b/notebooks/demo.ipynb similarity index 100% rename from demo.ipynb rename to notebooks/demo.ipynb From ce873e3422d815078d761cccfb4ed79cd624af73 Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:50:36 +0200 Subject: [PATCH 5/7] make a real python package move the source code to python modules. Move the test code to a proper test file. --- sam_lora/__init__.py | 0 sam_lora.py => sam_lora/sam_lora.py | 23 +++++------------------ scripts/test_lora.py | 10 ++++++++++ setup.cfg | 16 ++++++++++++++++ setup.py | 4 ++++ 5 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 sam_lora/__init__.py rename sam_lora.py => sam_lora/sam_lora.py (92%) create mode 100644 scripts/test_lora.py create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/sam_lora/__init__.py b/sam_lora/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sam_lora.py b/sam_lora/sam_lora.py similarity index 92% rename from sam_lora.py rename to sam_lora/sam_lora.py index 89295a2..63cd8bd 100644 --- a/sam_lora.py +++ b/sam_lora/sam_lora.py @@ -1,14 +1,9 @@ # Sheng Wang at Apr 6 2023 # What a time to be alive (first half of 2023) -from segment_anything import build_sam, SamPredictor -from segment_anything import sam_model_registry - import math import torch import torch.nn as nn -import torch.nn.functional as F -from torch import Tensor from torch.nn.parameter import Parameter from segment_anything.modeling import Sam from safetensors import safe_open @@ -48,6 +43,7 @@ def forward(self, x): qkv[:, :, :, -self.dim :] += new_v return qkv + class LoRA_Sam(nn.Module): """Applies low-rank adaptation to a Sam model's image encoder. @@ -129,7 +125,7 @@ def save_lora_parameters(self, filename: str) -> None: r"""Only safetensors is supported now. pip install safetensor if you do not have one installed yet. - + save both lora and fc parameters. """ @@ -138,11 +134,11 @@ def save_lora_parameters(self, filename: str) -> None: num_layer = len(self.w_As) # actually, it is half a_tensors = {f"w_a_{i:03d}": self.w_As[i].weight for i in range(num_layer)} b_tensors = {f"w_b_{i:03d}": self.w_Bs[i].weight for i in range(num_layer)} - + _in = self.lora_vit.head.in_features _out = self.lora_vit.head.out_features fc_tensors = {f"fc_{_in}in_{_out}out": self.lora_vit.head.weight} - + merged_dict = {**a_tensors, **b_tensors, **fc_tensors} save_file(merged_dict, filename) @@ -166,7 +162,7 @@ def load_lora_parameters(self, filename: str) -> None: saved_key = f"w_b_{i:03d}" saved_tensor = f.get_tensor(saved_key) w_B_linear.weight = Parameter(saved_tensor) - + _in = self.lora_vit.head.in_features _out = self.lora_vit.head.out_features saved_key = f"fc_{_in}in_{_out}out" @@ -181,12 +177,3 @@ def reset_parameters(self) -> None: nn.init.kaiming_uniform_(w_A.weight, a=math.sqrt(5)) for w_B in self.w_Bs: nn.init.zeros_(w_B.weight) - - # def forward(self, x: Tensor) -> Tensor: - # return self.lora_vit(x) - - -if __name__ == "__main__": - sam = sam_model_registry["vit_b"](checkpoint="sam_vit_b_01ec64.pth") - lora_sam = LoRA_Sam(sam,4) - lora_sam.sam.image_encoder(torch.rand(size=(1,3,1024,1024))) \ No newline at end of file diff --git a/scripts/test_lora.py b/scripts/test_lora.py new file mode 100644 index 0000000..133fdcc --- /dev/null +++ b/scripts/test_lora.py @@ -0,0 +1,10 @@ +from segment_anything import sam_model_registry +from sam_lora.sam_lora import LoRA_Sam +import torch + +if __name__ == "__main__": + sam = sam_model_registry["vit_b"]( + checkpoint="pretrained_weights/sam_vit_b_01ec64.pth" + ) + lora_sam = LoRA_Sam(sam, 4) + lora_sam.sam.image_encoder(torch.rand(size=(1, 3, 1024, 1024))) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..fecdb85 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,16 @@ +[metadata] +name = sam_lora +version=0.0.1 + +[options] +package_dir= + = . +packages=find: +install_requires= + numpy + safetensors + segment-anything @ git+https://github.com/facebookresearch/segment-anything.git@main + + +[options.packages.find] +where = . diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1abbd06 --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +import setuptools + +if __name__ == "__main__": + setuptools.setup() From d754a6841029e07935cde5e97c64de58f1de01df Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:50:43 +0200 Subject: [PATCH 6/7] add egg-info tmp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1c8debb..8cbff2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pth __pycache__/ pretrained_weights/ +*.egg-info From 82a7cbd776a1fffe6605f951ac3a0705f48165ef Mon Sep 17 00:00:00 2001 From: roesch Date: Thu, 25 Apr 2024 16:52:03 +0200 Subject: [PATCH 7/7] Update usage --- README.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 296376c..8963d39 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,17 @@ # LoRA for SAM (meta's segment-anything) ## Usage -``` -from segment_anything import build_sam, SamAutomaticMaskGenerator -from segment_anything import sam_model_registry -from sam_lora import LoRA_Sam -import torch -sam = sam_model_registry["vit_b"](checkpoint="sam_vit_b_01ec64.pth") -lora_sam = LoRA_Sam(sam,r = 4) -result = lora_sam.sam.image_encoder(torch.rand(size=(1,3,1024,1024))) -print(result.shape) -``` +1. Create a conda environment and install pytorch as described [here](https://pytorch.org/get-started/locally/) +2. run `pip install .` or `pip install -e .` +3. Get the model checkpoints [here](https://github.com/facebookresearch/segment-anything/tree/main?tab=readme-ov-file#model-checkpoints) or run +`mkdir pretrained_weights && wget -P pretrained_weights https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth` + +### Example +See the [test](./scripts/test_lora.py) ## Train Coming soon and welcome pull request. ## Thanks The code for LoRA ViT comes form -https://github.com/JamesQFreeman/LoRA-ViT \ No newline at end of file +https://github.com/JamesQFreeman/LoRA-ViT