()
| 144 | |
| 145 | |
| 146 | def main(): |
| 147 | parser = argparse.ArgumentParser() |
| 148 | parser.add_argument("--checkpoint", required=True) |
| 149 | parser.add_argument("--image", required=True) |
| 150 | parser.add_argument("--outdir", default="tests/ref_phase5") |
| 151 | parser.add_argument("--text", default="yellow school bus") |
| 152 | args = parser.parse_args() |
| 153 | |
| 154 | os.makedirs(args.outdir, exist_ok=True) |
| 155 | device = "cpu" |
| 156 | D = 256 |
| 157 | NH = 8 |
| 158 | HD = D // NH |
| 159 | NQ = 200 |
| 160 | T = 32 # text context length |
| 161 | H = 72 # image feature spatial dim (1008 / 14) |
| 162 | |
| 163 | print("Loading checkpoint...") |
| 164 | ckpt = torch.load(args.checkpoint, map_location=device, weights_only=False) |
| 165 | if "model" in ckpt: |
| 166 | ckpt = ckpt["model"] |
| 167 | |
| 168 | # ── Load required weights from specific modules ───────────────────── |
| 169 | |
| 170 | # We need the image features & text features as inputs. |
| 171 | # To get them, we first need to run the ViT backbone + neck + text encoder. |
| 172 | # These were already verified in prior phases, so we load cached reference tensors. |
| 173 | # But we need fresh tensors to match exact C++ inputs. |
| 174 | |
| 175 | # Let's first generate fresh image features using dump_vit_reference approach |
| 176 | print(f"Loading image: {args.image}") |
| 177 | img = Image.open(args.image).convert("RGB") |
| 178 | transform = v2.Compose([ |
| 179 | v2.ToDtype(torch.uint8, scale=True), |
| 180 | v2.Resize(size=(1008, 1008)), |
| 181 | v2.ToDtype(torch.float32, scale=True), |
| 182 | v2.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]), |
| 183 | ]) |
| 184 | img_tensor = v2.functional.to_image(img) |
| 185 | img_preprocessed = transform(img_tensor).unsqueeze(0).to(device) |
| 186 | |
| 187 | # ── ViT forward (reuse from dump_vit_reference.py) ───────────────── |
| 188 | # ... (this is too long to inline, we'll load pre-computed neck features) |
| 189 | # Instead, we'll load from the reference directory if available |
| 190 | ref_dir = "tests/ref" |
| 191 | neck_det_path = os.path.join(ref_dir, "neck_det_2") |
| 192 | if os.path.exists(neck_det_path + ".bin"): |
| 193 | print("Loading pre-computed neck features from tests/ref/") |
| 194 | # Load neck features |
| 195 | def load_tensor(path): |
| 196 | shape = list(map(int, open(path + ".shape").read().strip().split(","))) |
| 197 | data = np.fromfile(path + ".bin", dtype=np.float32).reshape(shape) |
| 198 | return torch.tensor(data) |
| 199 | |
| 200 | # Neck det features: [1, 256, H, H] for scale 2 (72x72) |
| 201 | neck_det_2 = load_tensor(os.path.join(ref_dir, "neck_det_2")) # [1, 256, 72, 72] |
| 202 | neck_det_1 = load_tensor(os.path.join(ref_dir, "neck_det_1")) # [1, 256, 144, 144] |
| 203 | neck_det_0 = load_tensor(os.path.join(ref_dir, "neck_det_0")) # [1, 256, 288, 288] |
no test coverage detected