PageSourceSearch

https://aymuos15.github.io/microblogs/deformable-convolutions.js

js aymuos15.github.io collected 2026-10-03 08:41:00 UTC 7,975 bytes, 220 lines download raw bytes

1// ── Deformable Convolution Entry ─────────────────────────────────────────────
2microblogEntries.push({
3  content: `<p>Standard convolutions sample on a fixed rectangular grid, limiting for irregular shapes. Deformable Convolutions (<a href="https://arxiv.org/abs/1703.06211" target="_blank">Dai et al., ICCV 2017</a>) add learnable offsets to each sampling position so the receptive field adapts to the geometry of the content. DCNv2 (<a href="https://arxiv.org/abs/1811.11168" target="_blank">Zhu et al., CVPR 2019</a>) adds per-sample modulation scalars that control <em>how much</em> each offset position contributes. DCNv3 (<a href="https://arxiv.org/abs/2211.05778" target="_blank">Wang et al., CVPR 2023</a>) shares weights across groups and softmax-normalises the modulation, and DCNv4 (<a href="https://arxiv.org/abs/2401.06197" target="_blank">Xiong et al., CVPR 2024</a>) removes the softmax constraint and optimises memory access for faster inference.</p>`,
4  date: "Mar. '26",
5  diagram: "deformable-conv",
6  id: "deformable-convolutions",
7  links: [],
8  tags: ["computer-vision", "convolutions"],
9  title: "Deformable Convolutions",
10});
11
12// ── DCN Diagram Builder ──────────────────────────────────────────────────────
13function buildMicroblogDiagramDCN(type) {
14  if (type !== "deformable-conv") {
15    return;
16  }
17  const container = document.getElementById(
18    "microblog-diagram-deformable-conv"
19  );
20  if (!container) {
21    return;
22  }
23
24  // 3x3 kernel positions on a normalised grid
25  const gridPts = [];
26  for (let r = 0; r < 3; r += 1) {
27    for (let c = 0; c < 3; c += 1) {
28      gridPts.push({ x: 25 + c * 25, y: 25 + r * 25 });
29    }
30  }
31
32  // Deformed offsets — points that hug the ellipse boundary (cx=50, cy=50, rx=34, ry=28, rot=-12deg)
33  const deformedPts = [
34    { x: 20, y: 28 },
35    { x: 50, y: 20 },
36    { x: 80, y: 26 },
37    { x: 16, y: 50 },
38    { x: 50, y: 50 },
39    { x: 84, y: 48 },
40    { x: 22, y: 72 },
41    { x: 50, y: 78 },
42    { x: 78, y: 72 },
43  ];
44
45  let mode = "standard";
46  const currentPts = gridPts.map((p) => ({ x: p.x, y: p.y }));
47
48  // Blob shape (irregular region the kernel adapts to)
49  const blobSvg = `<ellipse cx="50" cy="50" rx="34" ry="28"
50        transform="rotate(-12 50 50)"
51        fill="none" stroke="var(--border)" stroke-width="1.2"
52        stroke-dasharray="4 3" opacity="0.6"/>`;
53
54  // Build SVG
55  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
56  svg.setAttribute("viewBox", "5 12 90 80");
57  svg.setAttribute("class", "dcn-svg");
58  svg.innerHTML = blobSvg;
59
60  // Connection lines (grid edges)
61  const lines = [];
62  const lineIdxPairs = [
63    [0, 1],
64    [1, 2],
65    [3, 4],
66    [4, 5],
67    [6, 7],
68    [7, 8],
69    [0, 3],
70    [3, 6],
71    [1, 4],
72    [4, 7],
73    [2, 5],
74    [5, 8],
75  ];
76  for (const [a, b] of lineIdxPairs) {
77    const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
78    line.setAttribute("class", "dcn-line");
79    svg.appendChild(line);
80    lines.push({ a, b, el: line });
81  }
82
83  // Sample points
84  const dots = gridPts.map(() => {
85    const circle = document.createElementNS(
86      "http://www.w3.org/2000/svg",
87      "circle"
88    );
89    circle.setAttribute("r", "2.8");
90    circle.setAttribute("class", "dcn-dot");
91    svg.appendChild(circle);
92    return circle;
93  });
94
95  // Offset arrows (only visible in deformable mode)
96  const arrows = gridPts.map(() => {
97    const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
98    line.setAttribute("class", "dcn-arrow");
99    svg.appendChild(line);
100    return line;
101  });
102
103  function updatePositions() {
104    for (const [i, dot] of dots.entries()) {
105      dot.setAttribute("cx", currentPts[i].x);
106      dot.setAttribute("cy", currentPts[i].y);
107    }
108    for (const { el, a, b } of lines) {
109      el.setAttribute("x1", currentPts[a].x);
110      el.setAttribute("y1", currentPts[a].y);
111      el.setAttribute("x2", currentPts[b].x);
112      el.setAttribute("y2", currentPts[b].y);
113    }
114    for (const [i, arrow] of arrows.entries()) {
115      arrow.setAttribute("x1", gridPts[i].x);
116      arrow.setAttribute("y1", gridPts[i].y);
117      arrow.setAttribute("x2", currentPts[i].x);
118      arrow.setAttribute("y2", currentPts[i].y);
119    }
120  }
121
122  function animateTo(targetPts) {
123    const startPts = currentPts.map((p) => ({ x: p.x, y: p.y }));
124    const duration = 500;
125    const start = performance.now();
126    function tick(now) {
127      const t = Math.min(1, (now - start) / duration);
128      const ease = 1 - (1 - t) ** 3;
129      for (const [i, p] of currentPts.entries()) {
130        p.x = startPts[i].x + (targetPts[i].x - startPts[i].x) * ease;
131        p.y = startPts[i].y + (targetPts[i].y - startPts[i].y) * ease;
132      }
133      updatePositions();
134      if (t < 1) {
135        requestAnimationFrame(tick);
136      }
137    }
138    requestAnimationFrame(tick);
139  }
140
141  // Toggle buttons
142  const toggle = document.createElement("div");
143  toggle.className = "dcn-toggle";
144
145  const btnStd = document.createElement("button");
146  btnStd.className = "dcn-btn active";
147  btnStd.textContent = "Standard";
148
149  const btnDef = document.createElement("button");
150  btnDef.className = "dcn-btn";
151  btnDef.textContent = "Deformable";
152
153  function applyMode(m) {
154    if (m === mode) {
155      return;
156    }
157    mode = m;
158    btnStd.classList.toggle("active", mode === "standard");
159    btnDef.classList.toggle("active", mode === "deformable");
160    svg.classList.toggle("dcn-deformable", mode === "deformable");
161    animateTo(mode === "deformable" ? deformedPts : gridPts);
162  }
163
164  btnStd.addEventListener("click", () => setMode("standard"));
165  btnDef.addEventListener("click", () => setMode("deformable"));
166
167  toggle.appendChild(btnStd);
168  toggle.appendChild(btnDef);
169
170  // Equation panel
171  const eqPanel = document.createElement("div");
172  eqPanel.className = "dcn-eq";
173  eqPanel.innerHTML = `
174        <div class="dcn-eq-standard dcn-eq-block active">
175            <span class="dcn-eq-label">Standard</span>
176            <span class="dcn-eq-formula">y(p<sub>0</sub>) = &Sigma; w(p<sub>n</sub>) &middot; x(p<sub>0</sub> + p<sub>n</sub>)</span>
177        </div>
178        <div class="dcn-eq-deformable dcn-eq-block">
179            <span class="dcn-eq-label">Deformable</span>
180            <span class="dcn-eq-formula">y(p<sub>0</sub>) = &Sigma; w(p<sub>n</sub>) &middot; x(p<sub>0</sub> + p<sub>n</sub> + <em>&Delta;p<sub>n</sub></em>)</span>
181        </div>
182        <div class="dcn-eq-v2 dcn-eq-block">
183            <span class="dcn-eq-label">v2 / v3 / v4</span>
184            <span class="dcn-eq-formula">y(p<sub>0</sub>) = &Sigma; w(p<sub>n</sub>) &middot; <em>m<sub>n</sub></em> &middot; x(p<sub>0</sub> + p<sub>n</sub> + <em>&Delta;p<sub>n</sub></em>)</span>
185            <span class="dcn-eq-note">v3 &amp; v4 differ architecturally, not in the sampling formula.</span>
186        </div>
187    `;
188
189  const eqBlocks = eqPanel.querySelectorAll(".dcn-eq-block");
190
191  // Wrap SVG + equation side by side
192  const body = document.createElement("div");
193  body.className = "dcn-body";
194  body.appendChild(svg);
195  body.appendChild(eqPanel);
196
197  function setMode(m) {
198    applyMode(m);
199    for (const b of eqBlocks) {
200      b.classList.remove("active");
201    }
202    if (m === "standard") {
203      eqPanel.querySelector(".dcn-eq-standard").classList.add("active");
204    } else {
205      eqPanel.querySelector(".dcn-eq-deformable").classList.add("active");
206      eqPanel.querySelector(".dcn-eq-v2").classList.add("active");
207    }
208  }
209
210  // Caption
211  const caption = document.createElement("p");
212  caption.className = "dcn-caption";
213  caption.textContent =
214    "Click to toggle between fixed and learnable sampling positions.";
215
216  container.appendChild(toggle);
217  container.appendChild(body);
218  container.appendChild(caption);
219  updatePositions();
220}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.