t29mato Claude Opus 4.6 commited on
Commit
2d204ac
·
1 Parent(s): 8419b53

Fix Dockerfile: extract mmcv.ops shim to separate Python file

Browse files

Move inline Python code from Dockerfile RUN command into
setup_mmcv_shim.py to fix Docker parse errors. Use mmcv lite
instead of mmcv-full to avoid C++ compilation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. Dockerfile +6 -2
  2. setup_mmcv_shim.py +86 -0
Dockerfile CHANGED
@@ -16,8 +16,12 @@ RUN pip install --no-cache-dir \
16
  torchvision==0.14.1+cpu \
17
  -f https://download.pytorch.org/whl/cpu/torch_stable.html
18
 
19
- # Install mmcv-full WITHOUT C++ ops (ops are patched to torchvision at runtime)
20
- RUN MMCV_WITH_OPS=0 FORCE_CUDA=0 pip install --no-cache-dir --no-build-isolation mmcv-full==1.7.2
 
 
 
 
21
 
22
  # Install remaining dependencies
23
  RUN pip install --no-cache-dir \
 
16
  torchvision==0.14.1+cpu \
17
  -f https://download.pytorch.org/whl/cpu/torch_stable.html
18
 
19
+ # Install mmcv (lite version - no C++ ops needed)
20
+ RUN pip install --no-cache-dir mmcv==1.7.2
21
+
22
+ # Copy and run mmcv.ops shim setup
23
+ COPY setup_mmcv_shim.py .
24
+ RUN python setup_mmcv_shim.py
25
 
26
  # Install remaining dependencies
27
  RUN pip install --no-cache-dir \
setup_mmcv_shim.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Create mmcv.ops compatibility shim using torchvision ops."""
2
+ import os
3
+ import mmcv
4
+
5
+ ops_dir = os.path.join(os.path.dirname(mmcv.__file__), 'ops')
6
+ os.makedirs(ops_dir, exist_ok=True)
7
+
8
+ init_code = '''
9
+ import torch
10
+ import torchvision.ops as tv_ops
11
+
12
+ class NMSop(torch.autograd.Function):
13
+ @staticmethod
14
+ def forward(ctx, bboxes, scores, iou_threshold, offset, score_threshold, max_num):
15
+ if score_threshold > 0:
16
+ valid_mask = scores > score_threshold
17
+ bboxes_f, scores_f = bboxes[valid_mask], scores[valid_mask]
18
+ valid_inds = torch.nonzero(valid_mask, as_tuple=False).squeeze(dim=1)
19
+ else:
20
+ bboxes_f, scores_f = bboxes, scores
21
+ valid_inds = None
22
+ if bboxes_f.numel() == 0:
23
+ return torch.zeros(0, dtype=torch.long, device=bboxes.device)
24
+ inds = tv_ops.nms(bboxes_f, scores_f, iou_threshold)
25
+ if max_num > 0:
26
+ inds = inds[:max_num]
27
+ if valid_inds is not None:
28
+ inds = valid_inds[inds]
29
+ return inds
30
+
31
+ def batched_nms(boxes, scores, idxs, nms_cfg, class_agnostic=False):
32
+ nms_cfg_ = nms_cfg.copy()
33
+ class_agnostic = nms_cfg_.pop("class_agnostic", class_agnostic)
34
+ iou_thr = nms_cfg_.get("iou_threshold", nms_cfg_.get("iou_thr", 0.5))
35
+ if class_agnostic:
36
+ boxes_for_nms = boxes
37
+ else:
38
+ if boxes.numel() == 0:
39
+ return boxes.new_zeros((0, 5)), torch.zeros(0, dtype=torch.long, device=boxes.device)
40
+ max_coordinate = boxes.max()
41
+ offsets = idxs.to(boxes) * (max_coordinate + 1)
42
+ boxes_for_nms = boxes + offsets[:, None]
43
+ if boxes_for_nms.numel() == 0:
44
+ return boxes.new_zeros((0, 5)), torch.zeros(0, dtype=torch.long, device=boxes.device)
45
+ keep = tv_ops.nms(boxes_for_nms, scores, iou_thr)
46
+ max_num = nms_cfg_.get("max_num", -1)
47
+ if max_num > 0 and len(keep) > max_num:
48
+ keep = keep[:max_num]
49
+ dets = torch.cat([boxes[keep], scores[keep].unsqueeze(1)], dim=1)
50
+ return dets, keep
51
+
52
+ def nms(boxes, scores, iou_threshold, offset=0, score_threshold=0, max_num=-1):
53
+ inds = NMSop.apply(boxes, scores, iou_threshold, offset, score_threshold, max_num)
54
+ dets = torch.cat([boxes[inds], scores[inds].unsqueeze(1)], dim=1)
55
+ return dets, inds
56
+
57
+ def roi_align(input, rois, output_size, spatial_scale=1.0, sampling_ratio=-1, pool_mode="avg", aligned=True):
58
+ return tv_ops.roi_align(input, rois, output_size, spatial_scale=spatial_scale,
59
+ sampling_ratio=sampling_ratio if sampling_ratio > 0 else 2, aligned=aligned)
60
+
61
+ class RoIAlign(torch.nn.Module):
62
+ def __init__(self, output_size, spatial_scale=1.0, sampling_ratio=-1, pool_mode="avg", aligned=True, use_torchvision=False):
63
+ super().__init__()
64
+ self.output_size = output_size
65
+ self.spatial_scale = spatial_scale
66
+ self.sampling_ratio = sampling_ratio
67
+ self.aligned = aligned
68
+ def forward(self, input, rois):
69
+ return roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio, aligned=self.aligned)
70
+ '''
71
+
72
+ with open(os.path.join(ops_dir, '__init__.py'), 'w') as f:
73
+ f.write(init_code)
74
+
75
+ # Create nms submodule
76
+ nms_dir = os.path.join(ops_dir, 'nms')
77
+ os.makedirs(nms_dir, exist_ok=True)
78
+ with open(os.path.join(nms_dir, '__init__.py'), 'w') as f:
79
+ f.write('from mmcv.ops import NMSop, batched_nms, nms\n')
80
+
81
+ # Create carafe stub
82
+ carafe_path = os.path.join(ops_dir, 'carafe.py')
83
+ with open(carafe_path, 'w') as f:
84
+ f.write('# carafe stub - not needed for CPU inference\n')
85
+
86
+ print('mmcv.ops shim created successfully')